<?php
/**
 * PacificPayslipPdf — A5-portrait payslip in the Pacific brand.
 *
 * Uses the same palette + fonts as PacificInvoicePdf and PacificStaffIdPdf
 * so the finance stack reads as one system. A5 (148 × 210 mm) fits two
 * payslips per A4 sheet for batch printing — controller offers ?sheet=1.
 *
 * Contents:
 *   Header    — Pacific mark, period no, status pill
 *   Employee  — name, employee no, bank / mobile money
 *   Earnings  — base + commission + allowances → gross
 *   Deductions — PAYE + NSSF(ee) + health ins + other → total
 *   Net pay   — bold, brand accent
 *   Employer  — informational NSSF(er), SDL, WCF strip at the bottom
 */
class PacificPayslipPdf 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];

    // A5 portrait
    private const PAGE_W = 148;
    private const PAGE_H = 210;

    private const M_L = 12;   // left margin
    private const M_R = 12;   // right margin
    private const M_T = 12;   // top margin

    public function __construct()
    {
        if (!defined('FPDF_FONTPATH')) define('FPDF_FONTPATH', ROOT . '/fonts/fpdf/');
        parent::__construct('P', 'mm', 'A5');
        $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(false);
    }

    public function Header(): void {}
    public function Footer(): void {}

    /* ══════════════════════════════════════════════════════════════════
       Public — single payslip
       ══════════════════════════════════════════════════════════════════ */
    public function renderOne(array $r): void
    {
        $this->SetTitle($this->safe('Payslip · ' . ($r['full_name'] ?? '')));
        $this->SetAuthor($this->safe(defined('COMPANY_NAME') ? COMPANY_NAME : 'Pacific Group'));
        $this->AddPage();
        $this->drawPayslip($r, self::M_L, self::M_T, self::PAGE_W - self::M_L - self::M_R);
    }

    /* ══════════════════════════════════════════════════════════════════
       Public — batch print: N payslips, one per page
       ══════════════════════════════════════════════════════════════════ */
    public function renderMany(array $records): void
    {
        $this->SetTitle($this->safe('Payslips · batch'));
        foreach ($records as $r) {
            $this->AddPage();
            $this->drawPayslip($r, self::M_L, self::M_T, self::PAGE_W - self::M_L - self::M_R);
        }
    }

    /* ── Payslip body ─────────────────────────────────────────────── */
    private function drawPayslip(array $r, float $x, float $y, float $w): void
    {
        // ── Header ──
        $logoPath = ROOT . '/images/logo.png';
        if (is_file($logoPath)) {
            @$this->Image($logoPath, $x, $y, 40);
            $headerH = 13;
        } else {
            $this->SetFont('OpenSans-Bold', '', 12);
            $this->SetTextColor(...self::C_BRAND);
            $this->Text($x, $y + 6, $this->safe('PACIFIC GROUP'));
            $headerH = 8;
        }

        $this->SetFont('OpenSans-Bold', '', 8);
        $this->SetTextColor(...self::C_MUTED);
        $rightText = 'PAYSLIP';
        $rw = $this->GetStringWidth($rightText);
        $this->Text($x + $w - $rw, $y + 4, $rightText);

        $this->SetFont('OpenSans-Bold', '', 10);
        $this->SetTextColor(...self::C_INK);
        $periodNo = (string)($r['period_no'] ?? '');
        $pw = $this->GetStringWidth($periodNo);
        $this->Text($x + $w - $pw, $y + 10, $this->safe($periodNo));

        // Rule
        $ruleY = $y + $headerH + 3;
        $this->SetDrawColor(...self::C_BRAND);
        $this->SetLineWidth(0.6);
        $this->Line($x, $ruleY, $x + $w, $ruleY);

        // ── Period meta ──
        $mY = $ruleY + 4;
        $this->SetFont('OpenSans-Regular', '', 8);
        $this->SetTextColor(...self::C_MUTED);
        $periodStart = $this->fmtDate($r['period_start'] ?? '');
        $periodEnd   = $this->fmtDate($r['period_end']   ?? '');
        $this->Text($x, $mY, $this->safe('Period ' . $periodStart . ' - ' . $periodEnd));

        $status = strtoupper((string)($r['status'] ?? ''));
        $sw = $this->GetStringWidth($status);
        $chipW = $sw + 4;
        $this->SetFillColor(...self::C_TINT);
        $this->Rect($x + $w - $chipW, $mY - 3, $chipW, 4.5, 'F');
        $this->SetFont('OpenSans-Bold', '', 6);
        $this->SetTextColor(...self::C_BRAND_D);
        $this->Text($x + $w - $chipW + 2, $mY, $status);

        // ── Employee card ──
        $eY = $mY + 6;
        $this->SetFillColor(...self::C_GROUND);
        $this->Rect($x, $eY, $w, 22, 'F');

        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($x + 3, $eY + 4, $this->safe('EMPLOYEE'));

        $this->SetFont('OpenSans-Bold', '', 12);
        $this->SetTextColor(...self::C_INK);
        $this->Text($x + 3, $eY + 10, $this->safe($r['full_name'] ?? '—'));

        $this->SetFont('OpenSans-Regular', '', 8);
        $this->SetTextColor(...self::C_BRAND_D);
        $this->Text($x + 3, $eY + 15, $this->safe(($r['employee_no'] ?? '—') . ($r['phone_1'] ? '  ·  ' . $r['phone_1'] : '')));

        // Bank / mobile money on the right
        $rightX = $x + $w / 2 + 6;
        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($rightX, $eY + 4, $this->safe('PAYMENT DESTINATION'));
        $this->SetFont('OpenSans-Bold', '', 8);
        $this->SetTextColor(...self::C_INK);
        $dest = $r['bank_account_no'] ?: $r['mobile_money_msisdn'] ?: '—';
        $destLabel = $r['bank_account_no'] ? 'Bank · ' : ($r['mobile_money_msisdn'] ? 'Mobile · ' : '');
        $this->Text($rightX, $eY + 10, $this->safe($destLabel . $dest));
        $this->SetFont('OpenSans-Regular', '', 7);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($rightX, $eY + 15, $this->safe(sprintf('%d trips · TZS %s revenue', (int)$r['trip_count'], number_format((float)$r['trip_revenue'], 0))));

        // ── Earnings table ──
        $tY = $eY + 26;
        $tY = $this->drawTable($x, $tY, $w, 'EARNINGS', [
            ['Base salary',       (float)$r['base_salary']],
            (float)$r['commission']     > 0 ? ['Commission',        (float)$r['commission']]     : null,
            (float)$r['allowances']     > 0 ? ['Allowances',        (float)$r['allowances']]     : null,
            (float)$r['other_earnings'] > 0 ? ['Other earnings',    (float)$r['other_earnings']] : null,
        ], 'Gross pay', (float)$r['gross_pay']);

        // ── Deductions table ──
        $tY = $this->drawTable($x, $tY + 2, $w, 'DEDUCTIONS', [
            ['PAYE',              (float)$r['paye']],
            ['NSSF (employee)',   (float)$r['nssf_ee']],
            (float)$r['health_ins']       > 0 ? ['Health insurance', (float)$r['health_ins']]       : null,
            (float)$r['other_deductions'] > 0 ? ['Other deductions', (float)$r['other_deductions']] : null,
        ], 'Total deductions', (float)$r['paye'] + (float)$r['nssf_ee'] + (float)$r['health_ins'] + (float)$r['other_deductions']);

        // ── Net pay block ──
        $nY = $tY + 4;
        $this->SetFillColor(...self::C_BRAND);
        $this->Rect($x, $nY, $w, 14, 'F');
        $this->SetFont('OpenSans-Regular', '', 8);
        $this->SetTextColor(255, 255, 255);
        $this->Text($x + 3, $nY + 5.5, $this->safe('NET PAY'));
        $this->SetFont('OpenSans-Bold', '', 14);
        $netStr = 'TZS ' . number_format((float)$r['net_pay'], 2);
        $nsW = $this->GetStringWidth($netStr);
        $this->Text($x + $w - $nsW - 3, $nY + 10, $this->safe($netStr));

        // ── Employer contributions strip ──
        $iY = $nY + 18;
        $this->SetFont('OpenSans-Regular', '', 6.5);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($x, $iY, $this->safe('EMPLOYER CONTRIBUTIONS (informational — not deducted from pay)'));
        $this->SetFont('OpenSans-Regular', '', 7);
        $this->SetTextColor(...self::C_INK);
        $this->Text($x, $iY + 4, $this->safe(sprintf(
            'NSSF (10%%) TZS %s   ·   SDL (3.5%%) TZS %s   ·   WCF (0.5%%) TZS %s',
            number_format((float)$r['nssf_er'], 2),
            number_format((float)$r['sdl'],     2),
            number_format((float)$r['wcf'],     2)
        )));

        // ── Footer ──
        $fY = $y + self::PAGE_H - self::M_T - 10;
        $this->SetDrawColor(...self::C_RULE);
        $this->SetLineWidth(0.15);
        $this->Line($x, $fY, $x + $w, $fY);
        $this->SetFont('OpenSans-Regular', '', 6);
        $this->SetTextColor(...self::C_MUTED);
        $this->Text($x, $fY + 4, $this->safe('Generated ' . date('d M Y H:i') . ' · system-generated · contact HR for queries.'));
        $rightFoot = defined('COMPANY_NAME') ? COMPANY_NAME : 'Pacific Group Company Limited';
        $rfw = $this->GetStringWidth($rightFoot);
        $this->Text($x + $w - $rfw, $fY + 4, $this->safe($rightFoot));
    }

    /**
     * A simple 2-column table (label / money) with a header strip and a
     * bold total row. Skips null rows so callers can inline conditionals.
     * Returns the Y after the total row.
     */
    private function drawTable(float $x, float $y, float $w, string $title, array $rows, string $totalLabel, float $totalVal): float
    {
        // Header
        $this->SetFillColor(...self::C_TINT);
        $this->Rect($x, $y, $w, 5, 'F');
        $this->SetFont('OpenSans-Bold', '', 6.5);
        $this->SetTextColor(...self::C_BRAND_D);
        $this->Text($x + 2, $y + 3.5, $this->safe($title));
        $tzs = 'TZS';
        $tzsW = $this->GetStringWidth($tzs);
        $this->Text($x + $w - $tzsW - 2, $y + 3.5, $tzs);

        $y += 5;
        $this->SetTextColor(...self::C_INK);
        foreach ($rows as $r) {
            if ($r === null) continue;
            [$label, $val] = $r;
            $this->SetFont('OpenSans-Regular', '', 8);
            $this->Text($x + 2, $y + 4, $this->safe($label));
            $money = number_format($val, 2);
            $mw = $this->GetStringWidth($money);
            $this->Text($x + $w - $mw - 2, $y + 4, $money);

            $this->SetDrawColor(...self::C_RULE);
            $this->SetLineWidth(0.1);
            $this->Line($x, $y + 5.5, $x + $w, $y + 5.5);
            $y += 5.5;
        }

        // Total row
        $this->SetFont('OpenSans-Bold', '', 8);
        $this->Text($x + 2, $y + 4, $this->safe($totalLabel));
        $money = number_format($totalVal, 2);
        $mw = $this->GetStringWidth($money);
        $this->Text($x + $w - $mw - 2, $y + 4, $money);
        $this->SetDrawColor(...self::C_BRAND);
        $this->SetLineWidth(0.3);
        $this->Line($x, $y + 5.5, $x + $w, $y + 5.5);
        return $y + 6;
    }

    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;
    }
}
