module Billing
  module Stripe
    # Passa a Free se il periodo pagato è scaduto (es. disdetta o webhook mancato in locale).
    class FinalizeSubscription
      def self.call(club:)
        new(club: club).call
      end

      def initialize(club:)
        @club = club
      end

      def call
        sub = @club.subscription
        return false unless sub&.stripe_subscription_id.present?
        return false if sub.free?

        stripe_sub = ::Stripe::Subscription.retrieve(sub.stripe_subscription_id)

        if stripe_sub.status.in?(%w[canceled incomplete_expired])
          downgrade!(sub)
          return true
        end

        period_end = period_end_time(sub, stripe_sub)
        return false if period_end.blank? || period_end > Time.current

        if sub.cancel_at_period_end? || stripe_sub.cancel_at_period_end
          downgrade!(sub)
          return true
        end

        false
      rescue ::Stripe::InvalidRequestError => e
        downgrade!(sub) if e.message.include?("No such subscription")
        false
      end

      private

      def period_end_time(sub, stripe_sub)
        local = sub.current_period_end
        return local if local.present?

        start_at, end_at = SubscriptionPeriod.times(stripe_sub)
        end_at
      end

      def downgrade!(sub)
        Billing::AssignPlan.call(
          club: @club,
          plan_slug: "free",
          status: "active",
          stripe_attrs: {
            stripe_subscription_id: nil,
            current_period_start: nil,
            current_period_end: nil,
            cancel_at_period_end: false,
            billing_interval: nil
          }
        )
      end
    end
  end
end
