module Effective
  class Subscription < ActiveRecord::Base
    self.table_name = EffectiveOrders.subscriptions_table_name.to_s

    attr_accessor :stripe_subscription

    belongs_to :customer, counter_cache: true
    belongs_to :subscribable, polymorphic: true

    effective_resource do
      stripe_plan_id            :string
      stripe_subscription_id    :string
      name                      :string
      description               :string
      interval                  :string
      quantity                  :integer

      status                    :string

      timestamps
    end

    before_validation(if: -> { plan && (stripe_plan_id_changed? || new_record?) }) do
      self.name = plan[:name]
      self.description = plan[:description]
    end

    after_save do
      subscribable.subscription_name = name if subscribable.respond_to?(:subscription_name=)
      subscribable.subscription_description = description if subscribable.respond_to?(:subscription_description=)
      subscribable.subscription_interval = interval if subscribable.respond_to?(:subscription_interval=)
      subscribable.subscription_quantity = quantity if subscribable.respond_to?(:subscription_quantity=)
      subscribable.subscription_status = status if subscribable.respond_to?(:subscription_status=)
      subscribable.save!(validate: false)
    end

    after_destroy do
      subscribable.subscription_name = nil if subscribable.respond_to?(:subscription_name=)
      subscribable.subscription_description = nil if subscribable.respond_to?(:subscription_description=)
      subscribable.subscription_interval = nil if subscribable.respond_to?(:subscription_interval=)
      subscribable.subscription_quantity = nil if subscribable.respond_to?(:subscription_quantity=)
      subscribable.subscription_status = nil if subscribable.respond_to?(:subscription_status=)
      subscribable.save!(validate: false)
    end

    validates :customer, presence: true
    validates :subscribable, presence: true

    validates :stripe_plan_id, presence: true

    validate(if: -> { stripe_plan_id.present? }) do
      self.errors.add(:stripe_plan_id, 'unknown plan') unless EffectiveOrders.stripe_plans.map { |plan| plan[:id] }.include?(stripe_plan_id)
    end

    validates :stripe_subscription_id, presence: true

    validates :name, presence: true
    validates :interval, presence: true
    validates :quantity, presence: true, numericality: { greater_than: 0 }

    validates :status, inclusion: { in: EffectiveOrders::STATUSES.keys }

    before_validation do
      self.name ||= EffectiveOrders.stripe_plans.find { |plan| plan[:id] == stripe_plan_id }&[:name] || 'Subscribed Plan'
    end

    def to_s
      name || 'New Subscription'
    end

    def plan
      EffectiveOrders.stripe_plans.find { |plan| plan[:id] == stripe_plan_id }
    end

    def stripe_subscription
      @stripe_subscription ||= if stripe_subscription_id.present?
        Rails.logger.info "[STRIPE] get subscription: #{stripe_subscription_id}"
        ::Stripe::Subscription.retrieve(stripe_subscription_id)
      end
    end

    def <=>(other)
      name.to_s <=> other&.name.to_s
    end

    def trialing?
      status == 'trialing'
    end

    def active?
      status == 'active'
    end

    def past_due?
      status == 'past_due'
    end

    def canceled?
      status == 'canceled'
    end

  end
end