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

  def initialize(student, params)
    @student = student
    @school = student.school
    @family_id = params['family_id']
    @dates_param = 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',
        locals: {
          school: @school.decorate,
          side_content_partial: 'pdf/accounting/student_account_statement_header',
          side_content: { start: dates.first.to_date, end: dates.last.to_date }
        }
      )
      { content: content, spacing: 25 }
    end

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

    def set_local_variables
      {}.tap do |props|
        props[:statement_type] = @statement_type
        props[:student] = @student
        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 = amount_defaults

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

      query.map do |subcategory_title, records|
        amounts = amount_defaults

        records.each do |detail|
          transaction = detail.accounting_transaction

          action = if transaction.action == 'transfer' && transaction.increase?
            :transfer_in
          elsif transaction.action == 'transfer'
            :transfer_out
          else
            transaction.action.to_sym
          end

          amounts[action] += detail.amount
          @totals[action] += detail.amount
        end

        { title: subcategory_title }.merge(amounts)
      end
    end

    def details
      query = transaction_details
        .includes(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[: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
      @student.accounting_transaction_details
        .includes(:accounting_transaction, subcategory: :category)
        .with_subcategory(@category_ids)
        .with_date_range(date_range(@dates_param))
        .by_family_id(@family_id)
    end

    def family
      @family ||= @school.families.find_by(id: @family_id) || @student.family
    end

    def amount_defaults
      { charge: 0, credit: 0, payment: 0, transfer_in: 0, transfer_out: 0 }
    end

    def dates
      @dates ||= @dates_param.split(',')
    end
end
