<?php

namespace Modules\Accounting\Controllers;

use App\Controllers\BaseController;
use App\Models\CustomerInvoiceModel;
use App\Traits\ExportsReport;

class ReceivablesAgingController extends BaseController
{
    use ExportsReport;

    public function index()
    {
        $asOf = $this->request->getGet('as_of') ?: date('Y-m-d');
        $asOfTs = strtotime($asOf) ?: time();

        $invoices = (new CustomerInvoiceModel())
            ->scopeForList()
            ->whereIn('customer_invoices.status', ['posted', 'partially_paid', 'overdue'])
            ->where('customer_invoices.total > customer_invoices.amount_paid', null, false)
            ->orderBy('companies.name', 'ASC')
            ->orderBy('customer_invoices.due_date', 'ASC')
            ->findAll();

        $groups = [];
        $totals = [
            'current'  => 0.0,
            'd1_30'    => 0.0,
            'd31_60'   => 0.0,
            'd61_90'   => 0.0,
            'd90_plus' => 0.0,
            'total'    => 0.0,
        ];

        foreach ($invoices as $inv) {
            $companyId = (int) $inv['company_id'];
            if (! isset($groups[$companyId])) {
                $groups[$companyId] = [
                    'company_name' => $inv['company_name'] ?? '—',
                    'current'      => 0.0,
                    'd1_30'        => 0.0,
                    'd31_60'       => 0.0,
                    'd61_90'       => 0.0,
                    'd90_plus'     => 0.0,
                    'total'        => 0.0,
                    'invoices'     => [],
                ];
            }

            $outstanding = round((float) $inv['total'] - (float) $inv['amount_paid'], 2);
            $refDate = ! empty($inv['due_date']) ? $inv['due_date'] : $inv['invoice_date'];
            $days = (int) floor(($asOfTs - strtotime($refDate)) / 86400);

            if ($days <= 0) {
                $bucket = 'current';
            } elseif ($days <= 30) {
                $bucket = 'd1_30';
            } elseif ($days <= 60) {
                $bucket = 'd31_60';
            } elseif ($days <= 90) {
                $bucket = 'd61_90';
            } else {
                $bucket = 'd90_plus';
            }

            $groups[$companyId][$bucket] += $outstanding;
            $groups[$companyId]['total'] += $outstanding;
            $groups[$companyId]['invoices'][] = array_merge($inv, [
                'outstanding' => $outstanding,
                'days'        => $days,
                'bucket'      => $bucket,
            ]);

            $totals[$bucket] += $outstanding;
            $totals['total'] += $outstanding;
        }

        $rows = array_map(static fn ($g) => [
            $g['company_name'] ?? '',
            number_format((float) $g['current'], 2),
            number_format((float) $g['d1_30'], 2),
            number_format((float) $g['d31_60'], 2),
            number_format((float) $g['d61_90'], 2),
            number_format((float) $g['d90_plus'], 2),
            number_format((float) $g['total'], 2),
        ], array_values($groups));
        $rows[] = [
            'TOTAL',
            number_format((float) $totals['current'], 2),
            number_format((float) $totals['d1_30'], 2),
            number_format((float) $totals['d31_60'], 2),
            number_format((float) $totals['d61_90'], 2),
            number_format((float) $totals['d90_plus'], 2),
            number_format((float) $totals['total'], 2),
        ];

        if ($export = $this->exportTable(
            'receivables_aging',
            'Receivables Aging',
            ['Customer', 'Current', '1-30', '31-60', '61-90', '90+', 'Total'],
            $rows,
            'As of ' . $asOf
        )) {
            return $export;
        }

        return view('Modules\Accounting\Views\receivables_aging\index', array_merge($this->baseViewData(), [
            'title'  => 'Receivables Aging',
            'asOf'   => $asOf,
            'groups' => $groups,
            'totals' => $totals,
        ]));
    }
}
