class Pdf::Accounting::FamilyStatementService < Pdf::NewApplicationService
  include DateRangeHelper

  def initialize(family, params)
    @family = family.decorate
    @school = @family.school
    @dates = params['dates']
    @category_ids = params['category_ids']
    @statement_type = params['statement_type']&.to_sym
  end

  private
    def header
      content = ActionController::Base.new.render_to_string(
        partial: 'pdf/headers/school_info.html.haml',
        locals: {
          school: @school,
          side_content_partial: 'pdf/accounting/family_statement_header',
          side_content: formated_dates
        }
      )
      { content: content, spacing: 25 }
    end

    def body
      ActionController::Base.new.render_to_string(
        partial: 'pdf/accounting/family_statement.html.haml',
        locals: set_local_variables
      )
    end

    def set_local_variables
      {}.tap do |props|
        props[:statement_type] = @statement_type
        props[:family] = @family
        props[:details] = details if [:details, :both].include?(@statement_type)

        if [:summary, :both].include?(@statement_type)
          props[:amounts] = summary
          props[:totals] = @totals
        end
      end
    end

    def summary
      @totals = { charges: 0, credits: 0, payments: 0, transfer_in: 0, transfer_out: 0 }

      query = transaction_details
        .merge(Accounting::Subcategory.ordered)
        .group_by { |t| t.subcategory.decorate.title }

      keys = query.keys
      @amounts = keys.map do |key|
        response = { title: key }

        charges = query[key].select do |charge|
          charge.accounting_transaction.action == 'charge'
        end.sum(&:amount)
        @totals[:charges] += charges
        response[:charges] = charges

        credits = query[key].select do |credit|
          credit.accounting_transaction.action == 'credit'
        end.sum(&:amount)
        @totals[:credits] += credits
        response[:credits] = credits

        payments = query[key].select do |payment|
          payment.accounting_transaction.action == 'payment'
        end.sum(&:amount)
        @totals[:payments] += payments
        response[:payments] = payments

        transfer_in = query[key].select do |transfer|
          transfer.accounting_transaction.action == 'transfer' &&
            !transfer.accounting_transaction.increase?
        end.sum(&:amount)
        @totals[:transfer_in] += transfer_in
        response[:transfer_in] = transfer_in

        transfer_out = query[key].select do |transfer|
          transfer.accounting_transaction.action == 'transfer' &&
            transfer.accounting_transaction.increase?
        end.sum(&:amount)
        @totals[:transfer_out] += transfer_out
        response[:transfer_out] = transfer_out

        response
      end
    end

    def details
      query = transaction_details
        .includes(:student, accounting_transaction: :payment_detail)
        .merge(Accounting::Transaction.ordered)

      query.map do |detail|
        transaction = detail.accounting_transaction.decorate

        {}.tap do |props|
          props[:date] = transaction.posted_date
          props[:category_memo] = "#{detail.subcategory.decorate.title} - #{transaction.memo}"
          props[:student] = detail.student&.full_name(:last_initial)
          props[:amount] = detail.decorate.currency_with_symbol

          unless transaction.increase? || !transaction.payment?
            props[:payment_details] = transaction.payment_with_currency
          end
        end
      end
    end

    def transaction_details
      @family.accounting_transaction_details
        .includes(:accounting_transaction, subcategory: :category)
        .with_subcategory(@category_ids)
        .with_date_range(date_range(@dates))
    end

    def subcategories
      @school.accounting_subcategories
    end

    def formated_dates
      dates = @dates.split(',')
      { start: dates.first.to_date, end: dates.last.to_date }
    end
end
