module Billing
  module Stripe
    # Estrae riferimenti pagamento da Invoice Stripe (API Basil+: niente payment_intent top-level).
    module InvoicePaymentRefs
      EXPAND = ["payments.data.payment.payment_intent"].freeze

      module_function

      def payment_intent_id(invoice)
        each_payment_intent(invoice) { |pi| stripe_id(pi) }
      end

      def charge_id(invoice)
        each_payment_intent(invoice) do |pi|
          stripe_id(safe_get(pi, :latest_charge))
        end
      end

      def each_payment_intent(invoice)
        payment_entries(invoice).each do |entry|
          payment = safe_get(entry, :payment)
          next if payment.blank?

          pi = safe_get(payment, :payment_intent)
          result = yield(pi) if block_given?
          return result if result.present?
        end
        nil
      end

      def payment_entries(invoice)
        payments = safe_get(invoice, :payments)
        return [] if payments.blank?

        safe_get(payments, :data) || []
      end

      def stripe_id(value)
        return nil if value.blank?
        return value if value.is_a?(String)

        safe_get(value, :id)
      end

      def safe_get(obj, key)
        return nil if obj.blank?
        return obj[key] if obj.is_a?(Hash)
        return obj.public_send(key) if obj.respond_to?(key)

        nil
      rescue NoMethodError
        nil
      end
    end
  end
end
