class Accounting::Increase < Accounting::Transaction
  enum action: [:charge, :refund, :transfer, :void]

  has_many :allocations, through: :transaction_details, source: :increase_allocations

  after_initialize :create_transaction_associations, if: :new_record?
  after_save :mark_invoice_paid_or_unpaid, if: :charge?

  validate :subcategory_required, if: :subcategory_required_with_transaction
  validate :student_required, if: :charge?
  validate :check_totals, if: :new_record?
  validate :void_invoice_charge, if: :void

  scope :with_unattached_charges, -> do
    where(accounting_invoice_charges: { transaction_id: nil })
  end

  scope :with_categories, ->(categories) do
    where(accounting_subcategories: { id: categories }) if categories.present?
  end

  def transfer_distribution
    balances = family.balance_by_subcategory(:increase)
    outstanding_balance = balances.values.reduce(:+)

    {
      balances: balances,
      total_outstanding: outstanding_balance,
      students: students_transfer_breakdown
    }
  end

  private
    def available_decreases
      student.accounting_decreases.where(category: category, closed: false)
    end

    def students_transfer_breakdown
      family.students.map do |student|
        balance = student.balance_by_subcategory(:increase)
        [student, balance]
      end.to_h
    end

    def subcategory_required_with_transaction
      charge? || transfer?
    end

    def mark_invoice_paid_or_unpaid
      return if invoice.blank?

      invoice.mark_as_paid_or_unpaid
    end

    def void_invoice_charge
      return unless charge? && invoice

      errors.add(:void, 'Invoiced charge cannot be voided')
    end
end
