module JamRuby
  class SaleLineItem < ActiveRecord::Base

    JAMBLASTER = 'JamBlaster'
    JAMCLOUD = 'JamCloud'
    JAMTRACK = 'JamTrack'
    GIFTCARD = 'GiftCardType'
    LESSON = 'LessonPackageType'
    POSACARD = 'PosaCard'
    SUBSCRIPTION = 'Subscription'

    belongs_to :sale, class_name: 'JamRuby::Sale'
    belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
    belongs_to :jam_track_right, class_name: 'JamRuby::JamTrackRight'
    belongs_to :gift_card, class_name: 'JamRuby::GiftCard'
    belongs_to :lesson_package_purchase, class_name: 'JamRuby::LessonPackagePurchase'
    belongs_to :retailer, class_name: 'JamRuby::Retailer'

    # deprecated; use affiliate_distribution !!
    belongs_to :affiliate_referral, class_name: 'JamRuby::AffiliatePartner', foreign_key: :affiliate_referral_id

    has_many   :affiliate_distributions, class_name: 'JamRuby::AffiliateDistribution'

    has_many   :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook', inverse_of: :sale_line_item, foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid'

    validates :product_type, inclusion: {in: [JAMBLASTER, JAMCLOUD, JAMTRACK, GIFTCARD, LESSON, POSACARD, SUBSCRIPTION]}
    validates :unit_price, numericality: {only_integer: false}
    validates :quantity, numericality: {only_integer: true}
    validates :free, numericality: {only_integer: true}
    validates :sales_tax, numericality: {only_integer: false}, allow_nil: true
    validates :shipping_handling, numericality: {only_integer: false}
    validates :affiliate_referral_fee_in_cents, numericality: {only_integer: false}, allow_nil: true
    validates :recurly_plan_code, presence:true
    validates :sale, presence:true

    def is_jam_track?
      product_type == JAMTRACK
    end

    def is_gift_card?
      product_type == GIFTCARD
    end

    def is_subscription?
      product_type == SUBSCRIPTION
    end

    def product
      if product_type == JAMTRACK
        JamTrack.find_by_id(product_id)
      elsif product_type == SUBSCRIPTION
        {name: product_id}
      elsif product_type == GIFTCARD
        GiftCardType.find_by_id(product_id)
      elsif product_type == LESSON
        lesson_package_purchase
      elsif product_type == POSACARD
        PosaCard.find(product_id)
      else


        raise 'unsupported product type'
      end
    end

    def product_info
      item = product
      { name: product.name, product_type: product_type } if item
    end

    def state
      voided = false
      refunded = false
      failed = false
      succeeded = false

      recurly_transactions.each do |transaction|
        if transaction.transaction_type == RecurlyTransactionWebHook::VOID
          voided = true
        elsif transaction.transaction_type == RecurlyTransactionWebHook::REFUND
          refunded = true
        elsif transaction.transaction_type == RecurlyTransactionWebHook::FAILED_PAYMENT
          failed = true
        elsif transaction.transaction_type == RecurlyTransactionWebHook::SUCCESSFUL_PAYMENT
          succeeded = true
        end
      end

      {
          void: voided,
          refund: refunded,
          fail: failed,
          success: succeeded
      }
    end


    # in a shopping-cart less world (ios purchase), let's reuse as much logic as possible
    def self.create_from_jam_track(current_user, sale, jam_track, mark_redeem)
      shopping_cart = ShoppingCart.create(current_user, jam_track, 1, mark_redeem)
      line_item = create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
      shopping_cart.destroy
      line_item
    end

    def add_referral_if_needed(user, shopping_cart, lesson_booking)
      # if the teacher came from an affiliate, this is our chance to account for that (the student's affiliate status was accounted for in create_from_shopping_cart)
      referral_info = user.should_attribute_sale?(shopping_cart, lesson_booking)

      if referral_info
        self.affiliate_distributions << AffiliateDistribution.create(user.affiliate_referral, referral_info[:fee_in_cents], self)
        self.save!
      end
    end


    def self.create_from_subscription(current_user, sale, plan_code, recurly_response)
      sale_line_item = SaleLineItem.new
      sale_line_item.product_type = SUBSCRIPTION
      sale_line_item.product_id = recurly_response.uuid
      sale_line_item.unit_price = recurly_response.unit_amount_in_cents
      sale_line_item.quantity = 1
      sale_line_item.free = false
      sale_line_item.sales_tax = recurly_response.tax_in_cents
      sale_line_item.shipping_handling = 0
      sale_line_item.recurly_plan_code = plan_code

      sale.sale_line_items << sale_line_item
      sale_line_item.save
      sale_line_item
    end

    # in a shopping-cart less world (ios purchase), let's reuse as much logic as possible
    def self.create_from_lesson_package(current_user, sale, lesson_package_type, lesson_booking)
      teacher = lesson_booking.teacher if lesson_booking
      shopping_cart = ShoppingCart.create(current_user, lesson_package_type, 1)
      line_item = create_from_shopping_cart(sale, shopping_cart, nil, nil, nil, lesson_booking)

      if lesson_booking

        teacher = lesson_booking.teacher
        student = lesson_booking.student

        if lesson_booking.is_test_drive?
          # no referral for test drives
        elsif lesson_booking.no_school_on_school_payment?
          # no referral; we don't make money on school-on-school
        else
          line_item.add_referral_if_needed(student, shopping_cart, lesson_booking)

          if lesson_booking.school.nil?
            line_item.add_referral_if_needed(teacher, shopping_cart, lesson_booking)
          end
        end
      end

      shopping_cart.destroy
      line_item
    end

    def self.associate_user_for_posa(posa_card, user)
      sale_line_item = SaleLineItem.where(product_type: POSACARD).where(product_id: posa_card.id).first
      if sale_line_item
        sale_line_item.sale.user = user
        sale_line_item.sale.save!
      end
    end

    def self.create_from_posa_card(sale, retailer, posa_card)
      product_info = posa_card.product_info
      sale_line_item = SaleLineItem.new
      sale_line_item.retailer = retailer
      sale_line_item.product_type = POSACARD
      sale_line_item.product_id = posa_card.id
      sale_line_item.unit_price = product_info[:price]
      sale_line_item.quantity = product_info[:quantity]
      sale_line_item.free = product_info[:marked_for_redeem]
      sale_line_item.sales_tax = nil
      sale_line_item.shipping_handling = 0
      sale_line_item.recurly_plan_code = product_info[:plan_code]


      #referral_info = retailer.referral_info

      #if referral_info
      #  sale_line_item.affiliate_distributions << AffiliateDistribution.create(retailer.affiliate_partner, referral_info[:fee_in_cents], sale_line_item)
      #  sale_line_item.affiliate_referral = retailer.affiliate_partner
      #  sale_line_item.affiliate_referral_fee_in_cents = referral_info[:fee_in_cents]
      #end

      sale.sale_line_items << sale_line_item
      sale_line_item.save
      sale_line_item
    end

    def self.create_from_shopping_cart(sale, shopping_cart, recurly_subscription_uuid, recurly_adjustment_uuid, recurly_adjustment_credit_uuid, instance = nil)
      product_info = shopping_cart.product_info(instance)

      sale.order_total = sale.order_total + product_info[:real_price]

      sale_line_item = SaleLineItem.new
      sale_line_item.product_type = shopping_cart.cart_type
      sale_line_item.variant = shopping_cart.variant
      sale_line_item.unit_price = product_info[:price]
      sale_line_item.quantity = product_info[:quantity]
      sale_line_item.free = product_info[:marked_for_redeem]
      sale_line_item.sales_tax = nil
      sale_line_item.shipping_handling = 0
      sale_line_item.recurly_plan_code = product_info[:plan_code]
      sale_line_item.product_id = shopping_cart.cart_id
      sale_line_item.recurly_subscription_uuid = recurly_subscription_uuid
      sale_line_item.recurly_adjustment_uuid = recurly_adjustment_uuid
      sale_line_item.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid

      # determine if we need to associate this sale with a partner
      user = shopping_cart.user
      referral_info = user.should_attribute_sale?(shopping_cart, instance) if !instance || !instance.is_a?(LessonBooking) # all affiliate stuff is handled elsewhere

      if referral_info
        sale_line_item.affiliate_distributions << AffiliateDistribution.create(user.affiliate_referral, referral_info[:fee_in_cents], sale_line_item)
        sale_line_item.affiliate_referral = user.affiliate_referral
        sale_line_item.affiliate_referral_fee_in_cents = referral_info[:fee_in_cents]
      end

      sale.sale_line_items << sale_line_item
      sale_line_item.save
      sale_line_item
    end
  end
end