# represents the purchase of a LessonPackage
module JamRuby
  class LessonPackagePurchase < ActiveRecord::Base

    @@log = Logging.logger[LessonPackagePurchase]

    delegate :sent_billing_notices, :last_billing_attempt_at, :billing_attempts, :billing_should_retry, :billed, :billed_at,
             :billing_error_detail, :billing_error_reason, :is_card_declined?, :is_card_expired?,
             :last_billed_at_date, :sent_billing_notices, to: :lesson_payment_charge
    delegate :test_drive_count, to: :lesson_package_type

    # who purchased the lesson package?
    belongs_to :user, class_name: "JamRuby::User", :foreign_key => "user_id", inverse_of: :lesson_purchases
    belongs_to :lesson_package_type, class_name: "JamRuby::LessonPackageType"
    belongs_to :teacher, class_name: "JamRuby::User"
    belongs_to :lesson_booking, class_name: "JamRuby::LessonBooking"
    belongs_to :lesson_payment_charge, class_name: "JamRuby::LessonPaymentCharge", foreign_key: :charge_id
    belongs_to :posa_card, class_name: "JamRuby::PosaCard", foreign_key: :posa_card_id
    has_one :lesson_session, class_name: "JamRuby::LessonSession", dependent: :destroy
    has_many :teacher_distributions, class_name: "JamRuby::TeacherDistribution"

    has_one :sale_line_item, class_name: "JamRuby::SaleLineItem", dependent: :destroy

    validates :user, presence: true
    validates :lesson_package_type, presence: true
    validates :price, presence: true
    validate :validate_test_drive, on: :create

    after_create :add_test_drives
    after_create :create_charge




    def validate_test_drive
      if user
        # if this is a posa card purchase, we won't stop it from getting created
        if posa_card
          return
        end

        if lesson_package_type.is_test_drive?
          if user.lesson_package_needs_purchase_id
            # if lesson_package_needs_purchase is set, we need to let the purchase go through because the user alrady has the credits; gotta let them pay
            return
          end
          if !user.can_buy_test_drive?
            errors.add(:user, "can not buy test drive right now because you have already purchased it within the last year")
          end
        end
      end
    end

    def create_charge
      if payment_if_school_on_school? && lesson_booking && lesson_booking.is_monthly_payment?
        self.lesson_payment_charge = LessonPaymentCharge.new
        lesson_payment_charge.user = user
        lesson_payment_charge.amount_in_cents = 0
        lesson_payment_charge.fee_in_cents = 0
        lesson_payment_charge.lesson_package_purchase = self
        lesson_payment_charge.save!
      end
    end

    def teacher_distribution
      teacher_distributions.where(education: false).first
    end

    def education_distribution
      teacher_distributions.where(education: true).first
    end

    def add_test_drives
      if posa_card
        #user.jamclass_credits incremented in posa_card.rb
        return
      end

      if self.lesson_package_type.is_test_drive?
        new_test_drives = user.remaining_test_drives + lesson_package_type.test_drive_count
        User.where(id: user.id).update_all(remaining_test_drives: new_test_drives)
        user.remaining_test_drives = new_test_drives
      end
    end

    def to_s
      "#{name}"
    end

    def name
      lesson_package_type.sale_display
    end

    def amount_charged
      lesson_payment_charge.amount_in_cents / 100.0
    end

    def beginning_of_month_at
      Date.new(year, month, 1).to_time.utc.beginning_of_month
    end

    def end_of_month_at
      Date.new(year, month, 1).to_time.utc.end_of_month
    end

    def period_over?
      Time.now.utc  > end_of_month_at
    end

    def self.create(user, lesson_booking, lesson_package_type, year = nil, month = nil, posa_card = nil)
      purchase = LessonPackagePurchase.new
      purchase.user = user
      purchase.lesson_booking = lesson_booking
      purchase.teacher = lesson_booking.teacher if lesson_booking
      purchase.posa_card = posa_card
      if !purchase.posa_card && lesson_booking
         # the lesson booking has a posa card? if so, we should track that
        purchase.posa_card = lesson_booking.posa_card
      end

      if year
        purchase.year = year
        purchase.month = month
        purchase.recurring = true


        # this is for monthly
        if lesson_booking && lesson_booking.requires_teacher_distribution?(purchase)

          if lesson_booking.posa_card.nil? && lesson_booking.payment

            # if there is a payment object, it will describe how everything gets doled out
            payment = JSON.parse(lesson_booking.payment)

            teacher_split = payment["teacher"]
            retailer_split = payment["retailer"]

            retailer_rate = teacher.teacher.retailer.jamkazam_rate + APP_CONFIG.stripe[:charge_fee] # add 0.03 to account for stripe deduction


            if teacher_split && teacher_split > 0
              teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, false, (teacher_split / 100.0).round(2), retailer_rate)
              purchase.teacher_distributions << teacher_dist
              # price should always match  the teacher_distribution, if there is one
              purchase.price = teacher_dist.amount_in_cents / 100
              purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
            end

            if retailer_split && retailer_split > 0
              teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, false, (retailer_split / 100.0).round(2), retailer_rate)
              teacher_dist.retailer = teacher.teacher.retailer
              teacher_dist.save
              purchase.teacher_distributions << teacher_dist
              purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
            end

          else
            teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, false)
            purchase.teacher_distributions << teacher_dist
            purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
            # price should always match  the teacher_distribution, if there is one
            purchase.price = teacher_dist.amount_in_cents / 100

            if lesson_booking.school_on_school_payment? && lesson_booking.school.education
              teacher_dist = TeacherDistribution.create_for_lesson_package_purchase(purchase, true)
              purchase.teacher_distributions << teacher_dist
              purchase.reduced_roll_forward_amount_in_cents += teacher_dist.reduced_roll_forward_amount_in_cents
            end

          end

          # record expected times for times played in the month
          purchase.expected_session_times = lesson_booking.expected_session_times
        end
      else
        purchase.recurring = false
      end

      if lesson_booking

        purchase.lesson_package_type = lesson_package_type ? lesson_package_type : lesson_booking.lesson_package_type
        purchase.price = lesson_booking.booked_price if purchase.price.nil?
      else
        purchase.lesson_package_type = lesson_package_type
        purchase.price = lesson_package_type.price if purchase.price.nil?
      end
      purchase.save
      purchase
    end

    def price_in_cents
      (price * 100).to_i
    end

    def description(lesson_booking)
      lesson_package_type.description(lesson_booking)
    end

    def stripe_description(lesson_booking)
      description(lesson_booking)
    end

    def timed_description
      "Lessons for the month of #{self.month_name} with #{self.lesson_booking.student.name}"
    end

    def month_name
      if recurring
        Date.new(year, month, 1).strftime('%B')
      else
        'non-monthly paid lesson'
      end
    end

    def student
      user
    end

    # test drive purchase doesn't have a tea
    def school_on_school?
      if teacher
        teacher.teacher.school && student.school && (teacher.teacher.school.id == student.school.id)
      else
        false
      end
    end

    def school_on_school_payment?
      #!!(school_on_school? && teacher.teacher.school.education)
      school_on_school?
    end

    def no_school_on_school_payment?
      !!(school_on_school? && !school_on_school_payment?)
    end

    # if this is school-on-school, is payment required?
    def payment_if_school_on_school?
      !!(!school_on_school? || school_on_school_payment?)
    end

    def bill_monthly(force = false)

      if !payment_if_school_on_school?
        puts "SCHOOL ON SCHOOL PAYMENT OH NO"
        raise "school-on-school: should not be here"
      else
        lesson_payment_charge.charge(force)
        success = lesson_payment_charge.billed
      end

      if success
        self.sent_notices = true
        self.sent_notices_at = Time.now
        self.post_processed = true
        self.post_processed_at = Time.now
        self.save(:validate => false)
      end
    end

    def is_card_declined?
      billed == false && billing_error_reason == 'card_declined'
    end

    def is_card_expired?
      billed == false && billing_error_reason == 'card_expired'
    end

    def last_billed_at_date
      last_billing_attempt_at.strftime("%B %d, %Y") if last_billing_attempt_at
    end


    def update_payment_url
      APP_CONFIG.external_root_url + "/client#/jamclass/update-payment"
    end
  end
end

