class Admin::Accounting::ChargesController < Admin::Accounting::Controller
  def create
    charges = []
    credits = []
    students.each do |student|
      charge = student.family.accounting_increases.build(charge_params(student))
      charges += student.accounting_transaction_matrix(charge)

      next unless credit?

      credit = student.family.accounting_decreases.build(credit_params(student))
      credits += student.accounting_transaction_matrix(credit)
    end
    charges << validate_charges if charges.blank?
    credits << validate_credits if credit? && credits.blank?
    if transactional_save(charges + credits)
      allocate_funds
      message = charges.many? ? 'Charges' : 'Charge'
      render_success :ok, object: message
    else
      errors = {}
      errors[:charge] = charges.first.errors
      errors[:credit] = credits.first.errors if credit?
      render_error :unprocessable_entity, errors: errors
    end
  end

  private
    def students
      @students ||= current_school.students.where(id: params[:students])
    end

    def subcategory
      @subcategory ||= current_school.accounting_subcategories.find_by(id: params[:subcategory_id])
    end

    def charge_params(student=nil)
      params.require(:charge).permit(:amount, :memo, :posted_on).merge(
        action: :charge,
        student: student,
        subcategory: subcategory,
        tag_ids: params[:charge][:tag_ids]
      )
    end

    def credit_params(student=nil)
      params.require(:credit).permit(:amount, :memo, :tag_ids).merge(
        action: :credit,
        student: student,
        subcategory: subcategory,
        amount: set_amount,
        tag_ids: params[:credit][:tag_ids]
      )
    end

    def set_amount
      credit_amount = params[:credit][:amount].to_f
      return credit_amount unless params[:credit][:type] == 'Percent'

      params[:charge][:amount].to_f * credit_amount / 100
    end

    def credit?
      params[:credit]&.values&.any?(&:present?)
    end

    def validate_charges
      ::Accounting::Increase.new(charge_params)
    end

    def validate_credits
      ::Accounting::Decrease.new(credit_params)
    end

    def allocate_funds
      students.each do |student|
        AllocationJob.perform_now(
          student.family,
          @subcategory,
          student: student,
          audit_user: current_user
        )
        next unless student.family_two

        AllocationJob.perform_now(
          student.family_two,
          @subcategory,
          audit_user: current_user
        )
      end
    end
end
