module Pay
  class Webhook < Pay::ApplicationRecord
    validates :processor, presence: true
    validates :event_type, presence: true
    validates :event, presence: true

    def process!
      Pay::Webhooks.instrument type: "#{processor}.#{event_type}", event: rehydrated_event

      # Remove after successfully processing
      destroy
    end

    # Events have already been verified by the webhook, so we just store the raw data
    # Then we can rehydrate as webhook objects for each payment processor
    def rehydrated_event
      case processor
      when "braintree"
        Pay.braintree_gateway.webhook_notification.parse(event["bt_signature"], event["bt_payload"])
      when "paddle_billing"
        to_recursive_ostruct(event["data"])
      when "paddle_classic"
        to_recursive_ostruct(event)
      when "lemon_squeezy"
        Pay::LemonSqueezy.construct_from_webhook_event(event)
      when "stripe"
        ::Stripe::Event.construct_from(event)
      else
        event
      end
    end

    def to_recursive_ostruct(obj)
      if obj.is_a?(Hash)
        ActiveSupport::InheritableOptions.new(obj.map { |key, val| [key.to_sym, to_recursive_ostruct(val)] }.to_h)
      elsif obj.is_a?(Array)
        obj.map { |o| to_recursive_ostruct(o) }
      else # Assumed to be a primitive value
        obj
      end
    end
  end
end

ActiveSupport.run_load_hooks :pay_webhook, Pay::Webhook
