module JamRuby
  class TeacherPayment < ActiveRecord::Base

    belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id
    belongs_to :teacher_payment_charge, class_name: "JamRuby::TeacherPaymentCharge", foreign_key: :charge_id
    has_one :teacher_distribution, class_name: "JamRuby::TeacherDistribution"
    belongs_to :school, class_name: "JamRuby::School"
    belongs_to :retailer, class_name: "JamRuby::Retailer"


    def self.hourly_check
      teacher_payments
    end

    # pay the school if the payment owns the school; otherwise default to the teacher
    def payable_teacher
      if school
        if school.education
          teacher
        else
          school.owner
        end
      else
        teacher
      end
    end

    def teacher_distributions
      [teacher_distribution]
    end

    def self.pending_teacher_payments
      User.select(['users.id']).joins(:teacher).joins(:user_authorizations).joins(:teacher_distributions).where("user_authorizations.provider = 'stripe_connect' AND user_authorizations.token_expiration > NOW()").where('teacher_distributions.distributed = false').where('teacher_distributions.ready = true').uniq
    end

    def self.teacher_payments
      pending_teacher_payments.each do |row|
        teacher = User.find(row['id'])

        TeacherDistribution.where(teacher_id: teacher.id).where(ready: true).where(distributed: false).each do |distribution|
          payment = TeacherPayment.charge(teacher)
          if payment.nil? || !payment.teacher_payment_charge.billed
            break
          end
        end

      end
    end

    def amount
      amount_in_cents / 100.0
    end

    def is_card_declined?
      teacher_payment_charge.is_card_declined?
    end

    def is_card_expired?
      teacher_payment_charge.is_card_expired?
    end

    def last_billed_at_date
      teacher_payment_charge.last_billed_at_date
    end

    def charge_retry_hours
      24
    end

    def real_distribution_in_cents
      amount_in_cents - fee_in_cents
    end

    def admin_url
      APP_CONFIG.admin_root_url + "/admin/teacher_payments/" + id
    end

    # will find, for a given teacher, an outstading unsuccessful payment or make a new one.
    # it will then associate a charge with it, and then execute the charge.
    def self.charge(teacher)
      payment = TeacherPayment.joins(:teacher_payment_charge).where('teacher_payments.teacher_id = ?', teacher.id).where('charges.billed = false').order(:created_at).first
      if payment.nil?
        payment = TeacherPayment.new
        payment.teacher = teacher
      else
        payment = TeacherPayment.find(payment.id)
      end

      if payment.teacher_distribution.nil?
        teacher_distribution = TeacherDistribution.where(teacher_id: teacher.id).where(ready: true).where(distributed: false).order(:created_at).first
        if teacher_distribution.nil?
          return
        end
        payment.teacher_distribution = teacher_distribution
      end

      payment.school = payment.teacher_distribution.school
      payment.amount_in_cents = payment.teacher_distribution.amount_in_cents
      payment.fee_in_cents = payment.teacher_distribution.calculate_teacher_fee

      if payment.teacher_distribution.amount_in_cents > 0

        effective_in_cents = payment.real_distribution_in_cents

        if payment.teacher_payment_charge.nil?
          charge = TeacherPaymentCharge.new
          charge.user = payment.payable_teacher
          charge.amount_in_cents = (effective_in_cents / (1 - APP_CONFIG.stripe[:ach_pct])).round
          charge.fee_in_cents = payment.fee_in_cents
          charge.teacher_payment = payment
          payment.teacher_payment_charge = charge
          #  charge.save!
        else
          charge = payment.teacher_payment_charge
          charge.amount_in_cents = (effective_in_cents / (1 - APP_CONFIG.stripe[:ach_pct])).round
          charge.fee_in_cents = payment.fee_in_cents
          charge.save!
        end

        payment.save!

        payment.teacher_payment_charge.charge

        if payment.teacher_payment_charge.billed
          payment.teacher_distribution.distributed = true
          payment.teacher_distribution.save!
        end
      else

        # 0 amount distribution; these occur in 100% roll forward scenarios (previous month was completely missed)
        payment.save!
        payment.teacher_distribution.distributed = true
        payment.teacher_distribution.save!

      end

      payment
    end
  end

end