module SolidusInter
  class InterPix < Spree::PaymentMethod
    preference :client_id, :string
    preference :client_secret, :string
    preference :chave_pix, :string
    preference :conta_corrente, :string
    preference :crt, :text
    preference :key, :text

    def payment_source_class
      PixPaymentSource
    end

    def gateway_class
      InterPix
    end

    def supports?(source)
      source.is_a?(payment_source_class)
    end

    def auto_capture?
      true
    end

    def partial_name
      "inter_pix"
    end

    def create_payment(payment)
      client = set_api_client
      inter_payment = client.create_payment(
        amount: payment.amount,
        payer_tax_id: payment.source.payer_tax_id,
        payer_name: payment.source.payer_name,
        expiration: 3000
      )
      payment.response_code = inter_payment.txid
      payment.source.assign_attributes(
        txid: inter_payment.txid,
        pix_code: inter_payment.copia_e_cola,
        qr_code_svg: inter_payment.qr_code,
        status: inter_payment.status,
        expiration: inter_payment.expiracao,
        internal_error: inter_payment.internal_error
      )
      payment.log_entries.new(parsed_payment_response_details_with_fallback: failure_response(inter_payment.internal_error)) if inter_payment.internal_error
      inter_payment
    end

    def find_payment(txid)
      client = set_api_client
      client.get_payment(txid)
    end

    def invalidate_payment(payment)
      return unless payment && payment.source.txid
      inter_payment = find_payment(payment.source.txid)
      inter_payment.invalidate!
      payment.log_entries.create!(parsed_payment_response_details_with_fallback: failure_response("Pagamento cancelado"))
    end

    def purchase(money, source, options = {})
      client = set_api_client
      inter_payment = client.get_payment(source.txid)
      if inter_payment.paid?
        source.update(status: "approved")
        successful_response("Pagamento realizado", inter_payment.txid)
      else
        failure_response(inter_payment.internal_error || "Ocorreu um erro no pagamento.")
      end
    end

    private

    def set_api_client
      ::InterApi::Client.new(
        client_id: preferences[:client_id],
        client_secret: preferences[:client_secret],
        chave_pix: preferences[:chave_pix],
        conta_corrente: preferences[:conta_corrente],
        crt: temp_file(preferences[:crt]).path,
        key: temp_file(preferences[:key]).path
      )
    end

    def temp_file content
      t = Tempfile.new
      t << content
      t.close
      t
    end

    def successful_response message, transaction_id
      ActiveMerchant::Billing::Response.new(
        true,
        message,
        {},
        authorization: transaction_id
      )
    end

    def failure_response message
      ActiveMerchant::Billing::Response.new(
        false,
        message
      )
    end
  end
end