<?php
class PayrollController extends Controller
{
    public function indexAction($page = 1)
    {
        $page    = max(1, (int)$page);
        $perPage = defined('ROWS_PER_PAGE') ? ROWS_PER_PAGE : 20;
        $filters = [
            'status' => trim((string)($_GET['status'] ?? '')),
            'year'   => (int)($_GET['year'] ?? 0),
        ];
        $m = new PayrollPeriods();
        $result = $m->listPaginated($page, $perPage, $filters);

        $qs = http_build_query(array_filter($filters, fn($v) => $v !== '' && $v !== 0));
        $pg = Pagination::paginate($result['total'], $perPage, $page, PROOT . 'Payroll/index/');
        $pgHtml = $pg['html'];
        if ($qs && $pgHtml) $pgHtml = preg_replace('~href=\'([^\']+)\'~', "href='$1?" . htmlspecialchars($qs) . "'", $pgHtml);

        $this->view->setLayout($this->roleLayout());
        $this->view->render('Payroll/index', [
            'page_title' => 'Payroll',
            'rows'       => $result['rows'],
            'total'      => $result['total'],
            'page'       => $page,
            'filters'    => $filters,
            'pg_html'    => $pgHtml,
        ]);
    }

    public function addAction()
    {
        $this->view->setLayout($this->roleLayout());
        $this->view->render('Payroll/add', [
            'page_title' => 'New Payroll Period',
            'fb_msg'     => '',
        ]);
    }

    public function saveAction()
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') { Router::redirect('Payroll/add'); return; }
        $r = (new PayrollPeriods())->createPeriod((int)($_POST['year'] ?? 0), (int)($_POST['month'] ?? 0), $this->currentUserId());
        if (!$r['ok']) {
            $_SESSION['flash_tenant_msg']  = $r['msg'];
            $_SESSION['flash_tenant_type'] = 'danger';
            if (!empty($r['id'])) { Router::redirect('Payroll/view/' . $r['id']); return; }
            Router::redirect('Payroll/add'); return;
        }
        Router::redirect('Payroll/view/' . $r['id']);
    }

    public function viewAction($id = 0)
    {
        $m = new PayrollPeriods();
        $p = $m->byId((int)$id);
        if (!$p) { $this->notFound('Period'); return; }
        $this->view->setLayout($this->roleLayout());
        $this->view->render('Payroll/view', [
            'page_title' => $p['period_no'] . ' · Payroll',
            'p'          => $p,
            'records'    => $m->recordsFor((int)$id),
        ]);
    }

    public function computeAction($id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') { Router::redirect('Payroll/view/' . (int)$id); return; }
        $r = (new PayrollPeriods())->compute((int)$id, $this->currentUserId());
        $_SESSION['flash_tenant_msg']  = $r['msg'];
        $_SESSION['flash_tenant_type'] = $r['ok'] ? 'success' : 'danger';
        Router::redirect('Payroll/view/' . (int)$id);
    }

    public function approveAction($id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') { Router::redirect('Payroll/view/' . (int)$id); return; }
        $r = (new PayrollPeriods())->approve((int)$id, $this->currentUserId(), $_SESSION['full_name'] ?? '');
        $_SESSION['flash_tenant_msg']  = $r['msg'];
        $_SESSION['flash_tenant_type'] = $r['ok'] ? 'success' : 'danger';
        Router::redirect('Payroll/view/' . (int)$id);
    }

    public function payAction($id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') { Router::redirect('Payroll/view/' . (int)$id); return; }
        $method = trim((string)($_POST['method'] ?? 'bank_transfer'));
        $r = (new PayrollPeriods())->pay((int)$id, $method, $this->currentUserId(), $_SESSION['full_name'] ?? '');
        $_SESSION['flash_tenant_msg']  = $r['msg'];
        $_SESSION['flash_tenant_type'] = $r['ok'] ? 'success' : 'danger';
        Router::redirect('Payroll/view/' . (int)$id);
    }

    public function updateRecordAction($id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') { Router::redirect('Payroll'); return; }
        $rec = (new PayrollPeriods())->recordById((int)$id);
        if (!$rec) { $this->notFound('Record'); return; }
        $r = (new PayrollPeriods())->updateRecord((int)$id, $_POST, $this->currentUserId());
        $_SESSION['flash_tenant_msg']  = $r['msg'];
        $_SESSION['flash_tenant_type'] = $r['ok'] ? 'success' : 'danger';
        Router::redirect('Payroll/view/' . (int)$rec['period_id']);
    }

    public function voidPeriodAction($id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') { Router::redirect('Payroll/view/' . (int)$id); return; }
        $reason = trim((string)($_POST['reason'] ?? ''));
        if ($reason === '') { $_SESSION['flash_tenant_msg'] = 'Reason required.'; $_SESSION['flash_tenant_type'] = 'danger'; Router::redirect('Payroll/view/' . (int)$id); return; }
        $r = (new PayrollPeriods())->voidPeriod((int)$id, $reason, $this->currentUserId());
        $_SESSION['flash_tenant_msg']  = $r['msg'];
        $_SESSION['flash_tenant_type'] = $r['ok'] ? 'success' : 'danger';
        Router::redirect('Payroll/view/' . (int)$id);
    }

    public function payslipAction($id = 0)
    {
        $rec = (new PayrollPeriods())->recordById((int)$id);
        if (!$rec) { $this->notFound('Payslip'); return; }
        $this->view->setLayout('l_auth');   // bare shell for print
        $this->view->render('Payroll/payslip', [
            'page_title' => 'Payslip · ' . $rec['full_name'],
            'r'          => $rec,
        ]);
    }

    /**
     * Brand-consistent A5 payslip PDF.
     *   /Payroll/payslipPdf/12          → single payslip, inline preview
     *   /Payroll/payslipPdf/12?dl=1     → forces download
     */
    public function payslipPdfAction($id = 0)
    {
        $rec = (new PayrollPeriods())->recordById((int)$id);
        if (!$rec) { $this->notFound('Payslip'); return; }

        if (!class_exists('FPDF')) require_once ROOT . '/core/FPDF.php';
        $pdf = new PacificPayslipPdf();
        $pdf->renderOne($rec);

        if (ob_get_length()) ob_clean();
        $filename = 'Payslip-' . preg_replace('/[^A-Za-z0-9_-]/', '_',
            ($rec['period_no'] . '-' . ($rec['employee_no'] ?: $rec['full_name']))) . '.pdf';
        $mode = !empty($_GET['dl']) ? 'D' : 'I';
        $pdf->Output($mode, $filename);
        exit();
    }

    /**
     * Annual P9 certificate for one driver.
     *   /Payroll/p9/{driverId}?year=2026        → inline
     *   /Payroll/p9/{driverId}?year=2026&dl=1   → download
     */
    public function p9Action($driverId = 0)
    {
        $driverId = (int)$driverId;
        $year     = (int)($_GET['year'] ?? date('Y'));
        if ($year < 2000 || $year > 2100) $year = (int)date('Y');

        $cert = (new TaxReturns())->p9($driverId, $year);
        if (!$cert) {
            $this->view->setLayout($this->roleLayout());
            $this->view->render('generals/fb_page', [
                'page_title' => 'No P9',
                'fb_msg'     => '<div class="alert alert-warning">No approved payroll records for driver #'
                              . $driverId . ' in ' . $year . '.</div>',
            ]);
            return;
        }

        if (!class_exists('FPDF')) require_once ROOT . '/core/FPDF.php';
        $pdf = new PacificP9Pdf();
        $pdf->renderOne($cert);

        if (ob_get_length()) ob_clean();
        $filename = 'P9-' . $year . '-' . preg_replace('/[^A-Za-z0-9_-]/', '_',
            ($cert['driver']['employee_no'] ?: $cert['driver']['full_name'])) . '.pdf';
        $mode = !empty($_GET['dl']) ? 'D' : 'I';
        $pdf->Output($mode, $filename);
        exit();
    }

    /**
     * Batch P9 sheet: every driver who had a payroll record in the year,
     * one page per driver.
     *   /Payroll/p9Batch/2026
     *   /Payroll/p9Batch/2026?dl=1
     */
    public function p9BatchAction($year = 0)
    {
        $year = (int)$year ?: (int)date('Y');

        // Enumerate distinct driver_ids that had at least one approved
        // payroll record in the year, in name order for consistent output.
        $db = new DB();
        $ids = $db->mySelect(
            "SELECT DISTINCT pr.driver_id
               FROM payroll_records pr
               JOIN payroll_periods pp ON pp.c0d = pr.period_id
               JOIN drivers d          ON d.c0d = pr.driver_id
              WHERE YEAR(pp.period_start) = :yr
                AND pp.status IN ('approved','paid')
                AND pp.deleted = 0
           ORDER BY d.full_name",
            [':yr' => $year]
        ) ?: [];
        if (empty($ids)) { $this->notFound('P9 batch'); return; }

        $tax   = new TaxReturns();
        $certs = [];
        foreach ($ids as $row) {
            $c = $tax->p9((int)$row['driver_id'], $year);
            if ($c) $certs[] = $c;
        }
        if (empty($certs)) { $this->notFound('P9 batch'); return; }

        if (!class_exists('FPDF')) require_once ROOT . '/core/FPDF.php';
        $pdf = new PacificP9Pdf();
        $pdf->renderMany($certs);

        if (ob_get_length()) ob_clean();
        $filename = 'P9-' . $year . '-batch.pdf';
        $mode = !empty($_GET['dl']) ? 'D' : 'I';
        $pdf->Output($mode, $filename);
        exit();
    }

    /**
     * Batch — one PDF containing all payslips for a period (A5 per page).
     *   /Payroll/payslipsBatch/7        → inline preview
     *   /Payroll/payslipsBatch/7?dl=1   → download
     */
    public function payslipsBatchAction($periodId = 0)
    {
        $m = new PayrollPeriods();
        $p = $m->byId((int)$periodId);
        if (!$p) { $this->notFound('Period'); return; }
        $records = $m->recordsFor((int)$periodId);
        if (!$records) { $this->notFound('Payslips'); return; }

        if (!class_exists('FPDF')) require_once ROOT . '/core/FPDF.php';
        $pdf = new PacificPayslipPdf();
        $pdf->renderMany($records);

        if (ob_get_length()) ob_clean();
        $filename = 'Payslips-' . preg_replace('/[^A-Za-z0-9_-]/', '_', $p['period_no']) . '.pdf';
        $mode = !empty($_GET['dl']) ? 'D' : 'I';
        $pdf->Output($mode, $filename);
        exit();
    }

    private function notFound(string $what): void
    {
        $this->view->setLayout($this->roleLayout());
        $this->view->render('generals/fb_page', [
            'page_title' => 'Not found',
            'fb_msg'     => '<div class="alert alert-danger">' . htmlspecialchars($what) . ' not found.</div>',
        ]);
    }
}
