<?php

namespace Modules\Accounting\Controllers;

use App\Controllers\BaseController;
use App\Models\CompanyModel;
use App\Models\CreditNoteModel;
use App\Models\CustomerInvoiceModel;
use App\Models\CustomerReceiptModel;

class CustomerStatementController extends BaseController
{
    public function index()
    {
        $companies = (new CompanyModel())->getActive();
        $companyId = $this->request->getGet('company_id') ? (int) $this->request->getGet('company_id') : null;
        $dateFrom  = $this->request->getGet('date_from') ?: null;
        $dateTo    = $this->request->getGet('date_to') ?: null;

        $rows = [];
        $company = null;
        $balance = 0.0;

        if ($companyId) {
            $company = (new CompanyModel())->find($companyId);
            $entries = [];

            $invoiceModel = new CustomerInvoiceModel();
            $invoiceModel->where('customer_invoices.company_id', $companyId)
                ->whereIn('customer_invoices.status', ['posted', 'partially_paid', 'paid', 'overdue']);
            if ($dateFrom) {
                $invoiceModel->where('customer_invoices.invoice_date >=', $dateFrom);
            }
            if ($dateTo) {
                $invoiceModel->where('customer_invoices.invoice_date <=', $dateTo);
            }
            foreach ($invoiceModel->orderBy('customer_invoices.invoice_date', 'ASC')->orderBy('customer_invoices.id', 'ASC')->findAll() as $inv) {
                $entries[] = [
                    'date'   => $inv['invoice_date'],
                    'doc'    => $inv['number'],
                    'type'   => 'Invoice',
                    'debit'  => (float) $inv['total'],
                    'credit' => 0.0,
                    'sort'   => $inv['id'],
                ];
            }

            $receiptModel = new CustomerReceiptModel();
            $receiptModel->where('customer_receipts.company_id', $companyId)
                ->where('customer_receipts.status', 'posted');
            if ($dateFrom) {
                $receiptModel->where('customer_receipts.receipt_date >=', $dateFrom);
            }
            if ($dateTo) {
                $receiptModel->where('customer_receipts.receipt_date <=', $dateTo);
            }
            foreach ($receiptModel->orderBy('customer_receipts.receipt_date', 'ASC')->orderBy('customer_receipts.id', 'ASC')->findAll() as $rct) {
                $entries[] = [
                    'date'   => $rct['receipt_date'],
                    'doc'    => $rct['number'],
                    'type'   => 'Receipt',
                    'debit'  => 0.0,
                    'credit' => (float) $rct['amount'],
                    'sort'   => $rct['id'],
                ];
            }

            $noteModel = new CreditNoteModel();
            $noteModel->where('credit_notes.company_id', $companyId)
                ->where('credit_notes.status', 'posted');
            if ($dateFrom) {
                $noteModel->where('credit_notes.credit_date >=', $dateFrom);
            }
            if ($dateTo) {
                $noteModel->where('credit_notes.credit_date <=', $dateTo);
            }
            foreach ($noteModel->orderBy('credit_notes.credit_date', 'ASC')->orderBy('credit_notes.id', 'ASC')->findAll() as $cn) {
                $entries[] = [
                    'date'   => $cn['credit_date'],
                    'doc'    => $cn['number'],
                    'type'   => 'Credit Note',
                    'debit'  => 0.0,
                    'credit' => (float) $cn['total'],
                    'sort'   => $cn['id'],
                ];
            }

            usort($entries, static function (array $a, array $b): int {
                $cmp = strcmp($a['date'], $b['date']);
                if ($cmp !== 0) {
                    return $cmp;
                }

                return $a['sort'] <=> $b['sort'];
            });

            foreach ($entries as $entry) {
                $balance = round($balance + $entry['debit'] - $entry['credit'], 2);
                $rows[] = array_merge($entry, ['balance' => $balance]);
            }
        }

        return view('Modules\Accounting\Views\customer_statements\index', array_merge($this->baseViewData(), [
            'title'     => 'Customer Statements',
            'companies' => $companies,
            'company'   => $company,
            'rows'      => $rows,
            'balance'   => $balance,
            'filters'   => [
                'companyId' => $companyId,
                'dateFrom'  => $dateFrom,
                'dateTo'    => $dateTo,
            ],
        ]));
    }
}
