<?php
/**
 * PacificCustomerStatementPdf — A4 portrait statement of account.
 *
 * Layout:
 *   Header      — Pacific mark + "STATEMENT OF ACCOUNT" + range
 *   Bill To     — customer name, address, TIN
 *   From/To     — date range strip
 *   Ledger      — Date | Ref | Description | Debit | Credit | Balance
 *   Aging       — 5-bucket strip along the bottom
 *   Balance     — closing balance in a brand-blue banner
 *   Footer      — remittance advice + signatory line
 */
class PacificCustomerStatementPdf extends FPDF
{
    private const C_BRAND    = [ 38,  38, 245];
    private const C_BRAND_D  = [ 20,  20, 214];
    private const C_INK      = [ 15,  18,  32];
    private const C_MUTED    = [107, 116, 132];
    private const C_RULE     = [226, 231, 239];
    private const C_TINT     = [235, 239, 250];
    private const C_GROUND   = [245, 247, 251];
    private const C_DANGER   = [220,  38,  38];
    private const C_SUCCESS  = [ 14, 159, 110];

    private const M_L = 12;
    private const M_R = 12;
    private const M_T = 12;

    private const ROW_H  = 5.5;

    public function __construct()
    {
        if (!defined('FPDF_FONTPATH')) define('FPDF_FONTPATH', ROOT . '/fonts/fpdf/');
        parent::__construct('P', 'mm', 'A4');
        $this->AddFont('OpenSans-Regular', '', 'OpenSans-Regular.php');
        $this->AddFont('OpenSans-Bold',    '', 'opensans-bold.php');
        $this->SetMargins(self::M_L, self::M_T, self::M_R);
        $this->SetAutoPageBreak(true, 30);
    }

    public function Header(): void {}
    public function Footer(): void
    {
        $y = 297 - 8;
        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $this->SetY($y);
        $this->Cell(0, 4, $this->safe('Page ' . $this->PageNo() . ' · Generated ' . date('d M Y H:i') . ' · Pacific Group Company Limited'), 0, 0, 'C');
    }

    public function render(array $s): void
    {
        $this->SetTitle($this->safe('Statement · ' . ($s['customer']['customer_name'] ?? '')));
        $this->SetAuthor($this->safe(defined('COMPANY_NAME') ? COMPANY_NAME : 'Pacific Group'));
        $this->AddPage();
        $this->drawHeader($s);
        $this->drawParties($s);
        $this->drawLedger($s);
        $this->drawSummary($s);
    }

    /* ── Sections ─────────────────────────────────────────────────── */
    private function drawHeader(array $s): void
    {
        $x = self::M_L; $y = self::M_T;
        $w = 210 - self::M_L - self::M_R;

        $logoPath = ROOT . '/images/logo.png';
        if (is_file($logoPath)) {
            @$this->Image($logoPath, $x, $y, 42);
        } else {
            $this->SetFont('OpenSans-Bold', '', 12);
            $this->SetTextColor(...self::C_BRAND);
            $this->Text($x, $y + 8, $this->safe('PACIFIC GROUP'));
        }

        $this->SetFont('OpenSans-Bold', '', 16);
        $this->SetTextColor(...self::C_INK);
        $title = 'STATEMENT OF ACCOUNT';
        $tw = $this->GetStringWidth($title);
        $this->Text($x + $w - $tw, $y + 8, $this->safe($title));

        $this->SetFont('OpenSans-Regular', '', 8);
        $this->SetTextColor(...self::C_MUTED);
        $sub = $this->fmtDate($s['from']) . '  ->  ' . $this->fmtDate($s['to']);
        $sw = $this->GetStringWidth($sub);
        $this->Text($x + $w - $sw, $y + 12, $this->safe($sub));

        // Brand-blue rule
        $this->SetDrawColor(...self::C_BRAND);
        $this->SetLineWidth(0.7);
        $this->Line($x, $y + 20, $x + $w, $y + 20);
    }

    private function drawParties(array $s): void
    {
        $x = self::M_L; $y = self::M_T + 24;
        $w = 210 - self::M_L - self::M_R;

        // Bill To (customer) on the left
        $blockW = ($w - 4) / 2;
        $this->SetFillColor(...self::C_GROUND);
        $this->Rect($x, $y, $blockW, 30, 'F');
        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($x + 3, $y + 4, $this->safe('BILL TO'));

        $this->SetFont('OpenSans-Bold', '', 11);
        $this->SetTextColor(...self::C_INK);
        $this->Text($x + 3, $y + 10, $this->safe($s['customer']['customer_name']));

        $this->SetFont('OpenSans-Regular', '', 8);
        $this->SetTextColor(...self::C_INK);
        $line2 = trim(($s['customer']['physical_address'] ?? '') . (($s['customer']['city']) ? ', ' . $s['customer']['city'] : ''));
        if ($line2 !== '') $this->Text($x + 3, $y + 15, $this->safe($line2));
        if (!empty($s['customer']['phone_1'])) $this->Text($x + 3, $y + 20, $this->safe($s['customer']['phone_1']));
        if (!empty($s['customer']['customer_tin'])) {
            $this->SetTextColor(...self::C_BRAND_D);
            $this->Text($x + 3, $y + 25, $this->safe('TIN  ' . $s['customer']['customer_tin']));
        }

        // Summary strip on the right
        $xR = $x + $blockW + 4;
        $this->SetFillColor(...self::C_TINT);
        $this->Rect($xR, $y, $blockW, 30, 'F');
        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($xR + 3, $y + 4, $this->safe('OPENING BALANCE'));
        $this->SetFont('OpenSans-Bold', '', 10);
        $this->SetTextColor(...self::C_INK);
        $this->Text($xR + 3, $y + 10, $this->safe('TZS ' . number_format($s['opening'], 2)));

        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($xR + 3, $y + 15, $this->safe('CLOSING BALANCE'));
        $this->SetFont('OpenSans-Bold', '', 12);
        $this->SetTextColor(...($s['closing'] > 0 ? self::C_DANGER : self::C_SUCCESS));
        $this->Text($xR + 3, $y + 22, $this->safe('TZS ' . number_format($s['closing'], 2)));

        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $status = $s['closing'] > 0 ? 'amount due' : ($s['closing'] < 0 ? 'credit on account' : 'settled');
        $this->Text($xR + 3, $y + 27, $this->safe(strtoupper($status)));
    }

    private function drawLedger(array $s): void
    {
        $x = self::M_L; $y = self::M_T + 58;
        $w = 210 - self::M_L - self::M_R;

        // Header
        $this->SetFillColor(...self::C_BRAND);
        $this->Rect($x, $y, $w, self::ROW_H, 'F');
        $this->SetFont('OpenSans-Bold', '', 7);
        $this->SetTextColor(255, 255, 255);
        $cols = [
            ['DATE',        22, 'L'],
            ['REF',         30, 'L'],
            ['DESCRIPTION', 66, 'L'],
            ['DEBIT',       26, 'R'],
            ['CREDIT',      26, 'R'],
            ['BALANCE',     26, 'R'],
        ];
        $cx = $x;
        foreach ($cols as [$label, $cw, $al]) { $this->tcell($cx, $y, $cw, self::ROW_H, $label, $al, 1.5); $cx += $cw; }

        $y += self::ROW_H;
        $this->SetTextColor(...self::C_INK);

        // Opening-balance row
        $this->SetFillColor(...self::C_GROUND);
        $this->Rect($x, $y, $w, self::ROW_H, 'F');
        $this->SetFont('OpenSans-Bold', '', 7.5);
        $this->tcell($x, $y, $cols[0][1], self::ROW_H, $this->fmtDate($s['from']), 'L', 2);
        $this->tcell($x + $cols[0][1], $y, $cols[1][1], self::ROW_H, '—', 'L', 2);
        $this->tcell($x + $cols[0][1] + $cols[1][1], $y, $cols[2][1], self::ROW_H, 'Opening balance', 'L', 2);
        $this->tcell($x + $w - $cols[5][1], $y, $cols[5][1], self::ROW_H, number_format($s['opening'], 2), 'R', 2);
        $y += self::ROW_H;

        // Data rows
        if (empty($s['rows'])) {
            $this->SetFont('OpenSans-Regular', '', 8);
            $this->SetTextColor(...self::C_MUTED);
            $this->tcell($x, $y + 4, $w, self::ROW_H, 'No activity in this period.', 'L', 2);
            $y += self::ROW_H * 2;
        } else {
            foreach ($s['rows'] as $idx => $r) {
                // Page break if we're within footer/summary territory
                if ($y > 210) { $this->AddPage(); $y = self::M_T + 6; }

                if ($idx % 2 === 1) {
                    $this->SetFillColor(...self::C_GROUND);
                    $this->Rect($x, $y, $w, self::ROW_H, 'F');
                }
                $this->SetFont('OpenSans-Regular', '', 7);
                $this->SetTextColor(...self::C_INK);
                $cx = $x;
                $this->tcell($cx, $y, $cols[0][1], self::ROW_H, $this->fmtDate($r['date']), 'L', 2); $cx += $cols[0][1];
                $this->SetFont('OpenSans-Bold', '', 7);
                $this->tcell($cx, $y, $cols[1][1], self::ROW_H, $r['ref'], 'L', 2); $cx += $cols[1][1];
                $this->SetFont('OpenSans-Regular', '', 7);
                $this->tcell($cx, $y, $cols[2][1], self::ROW_H, $r['label'], 'L', 2); $cx += $cols[2][1];
                $this->tcell($cx, $y, $cols[3][1], self::ROW_H, $r['debit']  > 0 ? number_format($r['debit'], 2)  : '', 'R', 2); $cx += $cols[3][1];
                $this->tcell($cx, $y, $cols[4][1], self::ROW_H, $r['credit'] > 0 ? number_format($r['credit'], 2) : '', 'R', 2); $cx += $cols[4][1];
                $this->SetFont('OpenSans-Bold', '', 7);
                $this->tcell($cx, $y, $cols[5][1], self::ROW_H, number_format($r['running'], 2), 'R', 2);
                $y += self::ROW_H;
            }
        }

        // Totals row + closing
        $this->SetFillColor(...self::C_BRAND);
        $this->Rect($x, $y, $w, self::ROW_H + 1, 'F');
        $this->SetFont('OpenSans-Bold', '', 7.5);
        $this->SetTextColor(255, 255, 255);
        $this->tcell($x, $y, $cols[0][1] + $cols[1][1] + $cols[2][1], self::ROW_H + 1, 'Period totals / closing', 'L', 2);
        $this->tcell($x + $cols[0][1] + $cols[1][1] + $cols[2][1], $y, $cols[3][1], self::ROW_H + 1, number_format($s['total_debit'], 2), 'R', 2);
        $this->tcell($x + $cols[0][1] + $cols[1][1] + $cols[2][1] + $cols[3][1], $y, $cols[4][1], self::ROW_H + 1, number_format($s['total_credit'], 2), 'R', 2);
        $this->tcell($x + $w - $cols[5][1], $y, $cols[5][1], self::ROW_H + 1, number_format($s['closing'], 2), 'R', 2);
        $this->_ledgerEndY = $y + self::ROW_H + 6;
    }

    private float $_ledgerEndY = 0.0;

    private function drawSummary(array $s): void
    {
        $x  = self::M_L;
        $y  = $this->_ledgerEndY;
        $w  = 210 - self::M_L - self::M_R;

        // Aging strip
        $labels = [
            ['Current',  $s['age_buckets']['current']],
            ['1-30',     $s['age_buckets']['d1_30']],
            ['31-60',    $s['age_buckets']['d31_60']],
            ['61-90',    $s['age_buckets']['d61_90']],
            ['Over 90',  $s['age_buckets']['d90_plus']],
        ];
        $cw = $w / 5;
        $this->SetFont('OpenSans-Bold', '', 7);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($x, $y, $this->safe('AGED BALANCE (' . $s['open_count'] . ' open invoice' . ($s['open_count'] === 1 ? '' : 's') . ')'));
        $y += 4;

        $this->SetDrawColor(...self::C_RULE);
        $this->SetLineWidth(0.15);
        for ($i = 0; $i < 5; $i++) {
            $cx = $x + $i * $cw;
            $this->Rect($cx, $y, $cw, 14, 'D');
            $this->SetFont('OpenSans-Regular', '', 6.5);
            $this->SetTextColor(...self::C_MUTED);
            $this->Text($cx + 2, $y + 4, $this->safe(strtoupper($labels[$i][0])));

            $col = self::C_INK;
            if ($labels[$i][0] === '61-90')   $col = self::C_DANGER;
            if ($labels[$i][0] === 'Over 90') $col = self::C_DANGER;
            if ($labels[$i][0] === '31-60')   $col = [180, 90, 20];
            $this->SetFont('OpenSans-Bold', '', 9);
            $this->SetTextColor(...$col);
            $this->Text($cx + 2, $y + 11, $this->safe(number_format($labels[$i][1], 0)));
        }
        $y += 20;

        // Remittance advice
        $this->SetFont('OpenSans-Regular', '', 7);
        $this->SetTextColor(...self::C_MUTED);
        $this->SetXY($x, $y);
        $this->MultiCell($w, 3.6, $this->safe(
            'Please remit the amount due to Pacific Group Company Limited using any of the accounts below '
            . 'and quote your customer number ' . ($s['customer']['customer_no'] ?: '—')
            . ' as the payment reference. Contact accounts@pacificgroup.co.tz for any discrepancy.'
        ), 0, 'L');
        $y += 12;

        // Bank details strip
        $this->SetFillColor(...self::C_GROUND);
        $this->Rect($x, $y, $w, 14, 'F');
        $this->SetFont('OpenSans-Regular', '', 7);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($x + 3, $y + 4, $this->safe('REMIT TO'));
        $this->SetFont('OpenSans-Bold', '', 8);
        $this->SetTextColor(...self::C_INK);
        $this->Text($x + 3,  $y + 9, $this->safe('CRDB Bank   ·   A/C 0150-2233-4499'));
        $this->Text($x + 3,  $y + 12.5, $this->safe('NMB Bank    ·   A/C 4001-2233-4499'));

        $this->SetFont('OpenSans-Regular', '', 7);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($x + $w - 60, $y + 4, $this->safe('MOBILE MONEY'));
        $this->SetFont('OpenSans-Bold', '', 8);
        $this->SetTextColor(...self::C_INK);
        $this->Text($x + $w - 60, $y + 9, $this->safe('M-Pesa · Lipa 123456'));
        $this->Text($x + $w - 60, $y + 12.5, $this->safe('Airtel · Lipa 654321'));
    }

    /* ── helpers ───────────────────────────────────────────────────── */
    private function tcell(float $x, float $y, float $w, float $h, string $text, string $align, float $pad): void
    {
        $text = $this->safe($text);
        if ($align === 'R') {
            $tw = $this->GetStringWidth($text);
            $this->Text($x + $w - $tw - $pad, $y + $h * 0.72, $text);
        } else {
            $this->Text($x + $pad, $y + $h * 0.72, $text);
        }
    }

    private function fmtDate(?string $ymd): string
    {
        if (!$ymd) return '—';
        $t = strtotime($ymd);
        return $t ? date('d M Y', $t) : $ymd;
    }

    private function safe($s): string
    {
        $s = (string)$s;
        $s = strtr($s, [
            "\u{2013}" => '-',   "\u{2014}" => '-',
            "\u{2018}" => "'",   "\u{2019}" => "'",
            "\u{201C}" => '"',   "\u{201D}" => '"',
            "\u{2026}" => '...', "\u{2192}" => '->',
            "\u{00A0}" => ' ',   "\u{00B7}" => '.',
        ]);
        return @iconv('UTF-8', 'CP1252//TRANSLIT//IGNORE', $s) ?: $s;
    }
}
