<?php

namespace Modules\Accounting\Controllers;

use App\Controllers\BaseController;
use App\Models\ApPaymentModel;
use App\Models\DebitNoteModel;
use App\Models\SupplierBillModel;
use App\Models\SupplierModel;

class SupplierStatementController extends BaseController
{
    protected SupplierModel $suppliers;
    protected SupplierBillModel $bills;
    protected ApPaymentModel $payments;
    protected DebitNoteModel $debitNotes;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->suppliers  = new SupplierModel();
        $this->bills      = new SupplierBillModel();
        $this->payments   = new ApPaymentModel();
        $this->debitNotes = new DebitNoteModel();
    }

    public function index()
    {
        $supplierId = $this->request->getGet('supplier_id') ? (int) $this->request->getGet('supplier_id') : null;
        $dateFrom   = $this->request->getGet('date_from') ?: null;
        $dateTo     = $this->request->getGet('date_to') ?: null;

        $supplier   = null;
        $entries    = [];
        $balance    = 0.0;

        if ($supplierId) {
            $supplier = $this->suppliers->find($supplierId);
            if ($supplier) {
                $billQuery = $this->bills
                    ->where('supplier_id', $supplierId)
                    ->whereNotIn('status', ['draft', 'cancelled']);
                if ($dateFrom) {
                    $billQuery->where('bill_date >=', $dateFrom);
                }
                if ($dateTo) {
                    $billQuery->where('bill_date <=', $dateTo);
                }
                foreach ($billQuery->findAll() as $bill) {
                    $entries[] = [
                        'date'        => $bill['bill_date'],
                        'type'        => 'bill',
                        'number'      => $bill['number'],
                        'description' => 'Supplier bill',
                        'debit'       => (float) $bill['total'],
                        'credit'      => 0.0,
                        'sort'        => $bill['id'],
                    ];
                }

                $payQuery = $this->payments
                    ->where('supplier_id', $supplierId)
                    ->where('status', 'posted');
                if ($dateFrom) {
                    $payQuery->where('payment_date >=', $dateFrom);
                }
                if ($dateTo) {
                    $payQuery->where('payment_date <=', $dateTo);
                }
                foreach ($payQuery->findAll() as $pay) {
                    $entries[] = [
                        'date'        => $pay['payment_date'],
                        'type'        => 'payment',
                        'number'      => $pay['number'],
                        'description' => 'Payment' . ($pay['method'] ? ' · ' . $pay['method'] : ''),
                        'debit'       => 0.0,
                        'credit'      => (float) $pay['amount'],
                        'sort'        => $pay['id'],
                    ];
                }

                $dnQuery = $this->debitNotes
                    ->where('supplier_id', $supplierId)
                    ->where('status', 'posted');
                if ($dateFrom) {
                    $dnQuery->where('debit_date >=', $dateFrom);
                }
                if ($dateTo) {
                    $dnQuery->where('debit_date <=', $dateTo);
                }
                foreach ($dnQuery->findAll() as $dn) {
                    $entries[] = [
                        'date'        => $dn['debit_date'],
                        'type'        => 'debit_note',
                        'number'      => $dn['number'],
                        'description' => 'Debit note',
                        'debit'       => 0.0,
                        'credit'      => (float) $dn['total'],
                        'sort'        => $dn['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 &$row) {
                    $balance += $row['debit'] - $row['credit'];
                    $row['balance'] = round($balance, 2);
                }
                unset($row);
            }
        }

        return view('Modules\Accounting\Views\supplier_statements\index', array_merge($this->baseViewData(), [
            'title'     => 'Supplier Statements',
            'suppliers' => $this->suppliers->getActive(),
            'supplier'  => $supplier,
            'entries'   => $entries,
            'balance'   => round($balance, 2),
            'filters'   => compact('supplierId', 'dateFrom', 'dateTo'),
        ]));
    }
}
