class Accounting::TransactionsService
  def initialize(family, transaction)
    @family = family
    @transaction = transaction
  end

  def distribution(subcategory=nil)
    balances = @family.balance_by_subcategory(:increase)
    outstanding_balance = balances.values.reduce(:+)

    data = {
      balances: @family.balance_by_subcategory(:increase),
      outstanding_balance: outstanding_balance,
      students: students_payment_breakdown,
      subcategories: balances.sort_by(&:last).reverse
    }

    if payment?
      payment_disbursement(data, payment_amount)
    else
      data.merge(subcategory_balance: @family.balance(:decrease, subcategory))
    end
  end

  def build_details(subcategory, params)
    subcategory.each do |item|
      data = params.find { |f| f[:subcategory_id] == item.id }
      next if data.nil? || data[:applied].to_f.zero?

      @transaction.build_details(item, data[:applied], data[:students], data[:split])
    end
  end

  private
    def defaults
      @transaction.autopay_defaults.clone
    end

    def payment?
      @transaction.action == 'payment'
    end

    def payment_amount
      @payment_amount ||= @transaction.amount.to_f if payment?
    end

    def students
      @students ||= @family.students
    end

    def students_payment_breakdown
      students.map do |student|
        balances = student.balance_by_subcategory(:increase)
        balances = { auto: defaults, balance: balances } if payment?
        [student, balances]
      end.to_h
    end

    def payment_disbursement(data, payment_amount)
      increases = @family.accounting_transaction_details
        .opened
        .only_increases
        .without_void(true)
        .includes(:subcategory, :student)
        .order('accounting_transactions.posted_on ASC')

      data.tap do |hash|
        outstanding_balance = hash[:outstanding_balance]

        hash[:auto] = defaults
        hash[:total_autopay] = [outstanding_balance, payment_amount].min
        hash[:disable_auto] = payment_amount > outstanding_balance

        increases.each do |increase|
          student = increase.student
          subcategory = increase.subcategory
          amount = [increase.balance, payment_amount].min
          hash[:auto][increase.subcategory] += amount
          hash[:students][student][:auto][subcategory] += amount
          payment_amount -= amount
          break if payment_amount.zero?
        end
      end
    end
end
