<?php
declare(strict_types=1);

ini_set('memory_limit', '512M');
@set_time_limit(120);
ini_set('pcre.backtrack_limit', '10000000');
ini_set('pcre.recursion_limit', '10000000');

use Dompdf\Dompdf;
use Dompdf\Options;

require_once __DIR__ . '/../../../vendor/autoload.php';

global $db, $config, $auth;

$id = (int)($_GET['id'] ?? 0);
if ($id <= 0) {
    http_response_code(400);
    exit('Invalid invoice ID.');
}

$stmt = $db->prepare("
  SELECT
    i.*,

    h.hbl_no,
    h.goods_description,
    h.packages,
    h.gross_weight_kg,
    h.cbm,

    h.manifest_no,
    h.hs_code,
    h.icms_bl_no,
    h.cfs,

    m.mbl_no,
    m.vessel_name,
    m.voyage_no,
    m.eta_date,
    m.container_no,

    pol.name AS pol_name,
    pod.name AS pod_name,

    c1.name AS consignee_name, c1.address AS consignee_address,
    c2.name AS billing_name,   c2.address AS billing_address

  FROM invoices i
  JOIN house_bls h ON h.id = i.house_bl_id
  JOIN master_bls m ON m.id = h.master_bl_id
  LEFT JOIN ports pol ON pol.id = m.pol_port_id
  LEFT JOIN ports pod ON pod.id = m.pod_port_id
  JOIN customers c1 ON c1.id = i.consignee_customer_id
  JOIN customers c2 ON c2.id = i.billing_party_customer_id
  WHERE i.id = ?
");
$stmt->execute([$id]);
$inv = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$inv) {
    http_response_code(404);
    exit('Invoice not found.');
}

$items = $db->prepare("
  SELECT
    ii.*,
    ct.name AS charge_name
  FROM invoice_items ii
  JOIN charge_types ct ON ct.id = ii.charge_type_id
  WHERE ii.invoice_id = ?
  ORDER BY ii.id
");
$items->execute([$id]);
$rows = $items->fetchAll(PDO::FETCH_ASSOC);

if (!function_exists('h')) {
    function h(?string $v): string {
        return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8');
    }
}
if (!function_exists('n2')) {
    function n2($v): string {
        return number_format((float)$v, 2);
    }
}
if (!function_exists('n3')) {
    function n3($v): string {
        return number_format((float)$v, 3);
    }
}
if (!function_exists('safe_utf8_invoice')) {
    function safe_utf8_invoice($value): string {
        $value = (string)$value;
        if ($value === '') return '';

        if (function_exists('mb_convert_encoding')) {
            $converted = @mb_convert_encoding($value, 'UTF-8', 'UTF-8, ISO-8859-1, Windows-1252');
            if (is_string($converted) && $converted !== '') {
                $value = $converted;
            }
        } else {
            $converted = @iconv('UTF-8', 'UTF-8//IGNORE', $value);
            if ($converted !== false) {
                $value = $converted;
            }
        }

        $value = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/u', '', $value) ?? '';
        return $value;
    }
}

function itemLabel(array $it): string {
    $desc = trim((string)($it['description'] ?? ''));
    $name = strtoupper(trim((string)($it['charge_name'] ?? '')));
    return $desc !== '' ? strtoupper($desc) : $name;
}

function normalizeSpaces(string $value): string {
    $value = safe_utf8_invoice($value);
    return preg_replace('/\s+/u', ' ', trim($value)) ?? '';
}

function firstTwoNames(string $fullName): string {
    $fullName = normalizeSpaces($fullName);
    if ($fullName === '') {
        return 'UNKNOWN';
    }
    $parts = preg_split('/\s+/u', $fullName) ?: [];
    if (count($parts) > 2) {
        $parts = array_slice($parts, 0, 2);
    }
    return implode(' ', $parts);
}

function safeFilenamePart(string $value): string {
    $value = normalizeSpaces($value);
    $value = preg_replace('/[\\\\\/:*?"<>|]+/u', '', $value) ?? '';
    $value = preg_replace('/\s+/u', ' ', $value) ?? '';
    $value = trim($value, " .-\t\n\r\0\x0B");
    return $value !== '' ? strtoupper($value) : 'NA';
}

function buildInvoicePdfFilename(array $inv): string {
    $consignee = safeFilenamePart(firstTwoNames((string)($inv['consignee_name'] ?? '')));
    $blNumber  = safeFilenamePart((string)(($inv['hbl_no'] ?? '') !== '' ? $inv['hbl_no'] : ($inv['mbl_no'] ?? 'NA')));
    $vesselVoy = safeFilenamePart(trim(((string)($inv['vessel_name'] ?? '')) . ' ' . ((string)($inv['voyage_no'] ?? ''))));
    return 'INV-' . $consignee . '-' . $blNumber . '-' . $vesselVoy . '-INVOICE.pdf';
}

foreach ($inv as $k => $v) {
    if (!is_numeric($v) && $v !== null) {
        $inv[$k] = safe_utf8_invoice((string)$v);
    }
}
foreach ($rows as &$r) {
    foreach ($r as $k => $v) {
        if (!is_numeric($v) && $v !== null) {
            $r[$k] = safe_utf8_invoice((string)$v);
        }
    }
}
unset($r);

$subtotal = (float)($inv['subtotal'] ?? 0);
$discount = 0.00;
$net      = $subtotal;
$vatRate  = 16.0;

$flatBase = 0.0;
foreach ($rows as $it) {
    $basis = strtoupper(trim((string)($it['basis'] ?? '')));
    if ($basis === 'FLAT') {
        $flatBase += (float)($it['amount'] ?? 0);
    }
}
$vatAmount = round($flatBase * 0.16, 2);

$total = (float)($inv['total'] ?? 0);
$expectedTotal = round($net + $vatAmount, 2);
if (abs($total - $expectedTotal) > 0.009) {
    $total = $expectedTotal;
}

$issueDate = (string)($inv['issue_date'] ?: date('Y-m-d'));
$invoiceNo = (string)($inv['invoice_no'] ?: ('INV-' . $id));

$vessel      = (string)($inv['vessel_name'] ?? '');
$voyage      = (string)($inv['voyage_no'] ?? '');
$polName     = (string)($inv['pol_name'] ?? '');
$podName     = (string)($inv['pod_name'] ?? '');
$mblNo       = (string)($inv['mbl_no'] ?? '');
$hblNo       = (string)($inv['hbl_no'] ?? '');
$weightKg    = (float)($inv['gross_weight_kg'] ?? 0);
$cbm         = (float)($inv['cbm'] ?? 0);
$pkgs        = (string)($inv['packages'] ?? '');
$desc        = (string)($inv['goods_description'] ?? '');
$containerNo = (string)($inv['container_no'] ?? '');
$manifestNo  = (string)($inv['manifest_no'] ?? '');
$hsCode      = (string)($inv['hs_code'] ?? '');
$icmsBlNo    = (string)($inv['icms_bl_no'] ?? '');
$cfs         = (string)($inv['cfs'] ?? '');

$servedBy = '';
if (isset($auth) && $auth instanceof Auth) {
    $authUser = $auth->user();
    if (is_array($authUser) && !empty($authUser['full_name'])) {
        $servedBy = trim((string)$authUser['full_name']);
    }
}
if ($servedBy === '' && !empty($_SESSION['uid'])) {
    try {
        $uStmt = $db->prepare("SELECT full_name FROM users WHERE id = ? LIMIT 1");
        $uStmt->execute([(int)$_SESSION['uid']]);
        $uRow = $uStmt->fetch(PDO::FETCH_ASSOC);
        if ($uRow && !empty($uRow['full_name'])) {
            $servedBy = trim((string)$uRow['full_name']);
        }
    } catch (Throwable $e) {
        $servedBy = '';
    }
}
$servedBy = strtoupper($servedBy);

$basePath = rtrim((string)($config['app']['base_path'] ?? ''), '/');
$docRoot  = rtrim((string)($_SERVER['DOCUMENT_ROOT'] ?? ''), '/\\');
$bannerFsPath = $docRoot . $basePath . '/assets/wcs-banner.png';

$bannerDataUri = '';
if (is_file($bannerFsPath)) {
    $imgData = @file_get_contents($bannerFsPath);
    if ($imgData !== false) {
        $mime = function_exists('mime_content_type') ? mime_content_type($bannerFsPath) : 'image/png';
        $bannerDataUri = 'data:' . $mime . ';base64,' . base64_encode($imgData);
    }
}

$filename = buildInvoicePdfFilename($inv);

$itemsHtml = '';
if ($rows) {
    foreach ($rows as $it) {
        $itemsHtml .= '
        <tr class="item-row">
            <td>' . h((string)itemLabel($it)) . '</td>
            <td class="r">' . h((string)n2($it['unit_price'] ?? 0)) . '</td>
            <td class="r">' . h((string)n3($it['qty'] ?? 0)) . '</td>
            <td class="r">' . h((string)n2($it['amount'] ?? 0)) . '</td>
        </tr>';
    }
} else {
    $itemsHtml = '
        <tr>
            <td colspan="4">&nbsp;</td>
        </tr>';
}

$bannerHtml = $bannerDataUri !== ''
    ? '<img class="banner" src="' . $bannerDataUri . '" alt="WSC Banner">'
    : '';

$html = '<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>' . h((string)$invoiceNo) . '</title>
<style>
  @page { margin: 18mm 12mm 18mm 12mm; }

  html, body {
    margin: 0;
    padding: 0;
    background: #fff;
  }

  body{
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    color: #000;
  }

  table {
    border-collapse: collapse;
  }

  .page-frame{
    border: 3px solid #f97316;
    padding: 16px 18px 18px 18px;
    box-sizing: border-box;
  }

  .header-block{
    page-break-inside: avoid;
    margin-bottom: 8px;
  }

  .banner-wrap{
    margin-bottom: 8px;
  }

  .banner{
    width: auto;
    max-width: 520px;
    height: auto;
    display: block;
  }

  .divider{
    border-top: 3px solid #f97316;
    margin: 8px -18px 14px -18px;
  }

  .title{
    text-align: center;
    color: #f97316;
    font-weight: bold;
    letter-spacing: .5px;
    margin: 0 0 12px 0;
    font-size: 22px;
  }

  .lbl{
    font-weight: 700;
    text-transform: uppercase;
  }

  .top-shell,
  .top-left-grid,
  .mid-table,
  .bottom-table,
  .tot,
  .kv,
  .items{
    width: 100%;
    table-layout: fixed;
  }

  .top-shell td,
  .top-left-grid td,
  .mid-table td,
  .bottom-table td,
  .tot td,
  .kv td,
  .items td,
  .items th{
    vertical-align: top;
  }

  .top-shell{
    margin-bottom: 8px;
  }

  .top-left-wrap{
    width: 50%;
    padding-right: 18px;
  }

  .top-right-wrap{
    width: 50%;
    padding-left: 18px;
  }

  .top-left-grid .to-col{
    width: 50%;
    padding-right: 12px;
  }

  .top-left-grid .bill-col{
    width: 50%;
    padding-left: 12px;
  }

  .top-value{
    margin-top: 6px;
    white-space: pre-line;
  }

  .meta-stack{
    margin-left: 160px;
    width: auto;
  }

  .meta-block{
    margin-bottom: 8px;
  }

  .meta-label{
    display: block;
    font-weight: 700;
    text-transform: uppercase;
  }

  .meta-value{
    display: block;
    margin-top: 6px;
    white-space: pre-line;
  }

  .mid-table{
    margin-top: 8px;
    margin-bottom: 14px;
  }

  .mid-left{
    width: 50%;
    padding-right: 18px;
  }

  .mid-right{
    width: 50%;
    padding-left: 18px;
  }

  .kv td{
    padding: 1px 0;
  }

  .kv .k{
    width: 165px;
    font-weight: 700;
    text-transform: uppercase;
    padding-right: 10px;
  }

  .kv .v{
    width: auto;
  }

  .items{
    margin-top: 6px;
    font-size: 12px;
    page-break-inside: auto;
  }

  .items thead{
    display: table-header-group;
  }

  .items tbody{
    display: table-row-group;
  }

  .items tr{
    page-break-inside: avoid;
    page-break-after: auto;
  }

  .items th{
    border-bottom: 1px solid #000;
    padding: 6px 4px;
    text-align: left;
    font-weight: 700;
    text-transform: uppercase;
  }

  .items td{
    padding: 7px 4px;
    border-bottom: 1px solid #ddd;
    word-wrap: break-word;
  }

  .items .col-item  { width: 58%; }
  .items .col-price { width: 14%; }
  .items .col-qty   { width: 12%; }
  .items .col-total { width: 16%; }

  .r{
    text-align: right;
  }

  .totals-block{
    page-break-inside: avoid;
    margin-top: 12px;
  }

  .bottom-table{
    margin-top: 12px;
  }

  .remit{
    width: 58%;
    white-space: pre-line;
    line-height: 1.35;
    padding-right: 20px;
  }

  .remit .hdr{
    font-weight: 700;
    margin: 0 0 6px 0;
  }

  .totals-cell{
    width: 42%;
  }

  .tot td{
    padding: 4px 0;
  }

  .tot .label{
    font-weight: 700;
    font-size: 12px;
    white-space: nowrap;
    padding-right: 12px;
  }

  .tot .amount{
    text-align: right;
    width: 110px;
  }

  .grand{
    font-weight: 700;
  }

  .audit-footer{
    margin-top: 28px;
    padding-top: 8px;
    border-top: 1px dashed #d1d5db;
    font-size: 11px;
    color: #6b7280;
    text-align: right;
  }
</style>
</head>
<body>
  <div class="page-frame">

    <div class="header-block">
      <div class="banner-wrap">
        ' . $bannerHtml . '
      </div>

      <div class="divider"></div>

      <h2 class="title">INVOICE</h2>

      <table class="top-shell">
        <tr>
          <td class="top-left-wrap">
            <table class="top-left-grid">
              <tr>
                <td class="to-col">
                  <div class="lbl">TO</div>
                  <div class="top-value">' . strtoupper(h((string)$inv['consignee_name'])) . "\n" . h((string)$inv['consignee_address']) . '</div>
                </td>
                <td class="bill-col">
                  <div class="lbl">BILL TO</div>
                  <div class="top-value">' . strtoupper(h((string)$inv['billing_name'])) . "\n" . h((string)$inv['billing_address']) . '</div>
                </td>
              </tr>
            </table>
          </td>

          <td class="top-right-wrap">
            <div class="meta-stack">
              <div class="meta-block">
                <span class="meta-label">DATE</span>
                <span class="meta-value">' . h((string)$issueDate) . '</span>
              </div>

              <div class="meta-block">
                <span class="meta-label">INVOICE NO.</span>
                <span class="meta-value">' . h((string)$invoiceNo) . '</span>
              </div>
            </div>
          </td>
        </tr>
      </table>

      <table class="mid-table">
        <tr>
          <td class="mid-left">
            <table class="kv">
              <tr><td class="k">VESSEL</td><td class="v">' . h((string)$vessel) . '</td></tr>
              <tr><td class="k">PORT OF LOADING</td><td class="v">' . h((string)$polName) . '</td></tr>
              <tr><td class="k">PORT OF DISCHARGE</td><td class="v">' . h((string)$podName) . '</td></tr>
              <tr><td class="k">CONTAINER NUMBER</td><td class="v">' . h((string)$containerNo) . '</td></tr>
              <tr><td class="k">MBL</td><td class="v">' . h((string)$mblNo) . '</td></tr>
              <tr><td class="k">HBL</td><td class="v">' . h((string)$hblNo) . '</td></tr>
              <tr><td class="k">WEIGHT</td><td class="v">' . h((string)n2($weightKg)) . ' KGS</td></tr>
              <tr><td class="k">VOLUME</td><td class="v">' . h((string)n3($cbm)) . ' CBM</td></tr>
            </table>
          </td>

          <td class="mid-right">
            <table class="kv">
              <tr><td class="k">VOYAGE</td><td class="v">' . h((string)$voyage) . '</td></tr>
              <tr><td class="k">DESCRIPTION</td><td class="v">' . h((string)$desc) . '</td></tr>
              <tr><td class="k">PACKAGES</td><td class="v">' . h((string)$pkgs) . '</td></tr>
              <tr><td class="k">HSCODE</td><td class="v">' . h((string)$hsCode) . '</td></tr>
              <tr><td class="k">MANIFEST NO.</td><td class="v">' . h((string)$manifestNo) . '</td></tr>
              <tr><td class="k">CFS</td><td class="v">' . h((string)$cfs) . '</td></tr>
              <tr><td class="k">ICMS BL NO</td><td class="v">' . h((string)$icmsBlNo) . '</td></tr>
            </table>
          </td>
        </tr>
      </table>
    </div>

    <table class="items">
      <thead>
        <tr>
          <th class="col-item">ITEM</th>
          <th class="col-price r">PRICE</th>
          <th class="col-qty r">QTY</th>
          <th class="col-total r">TOTAL</th>
        </tr>
      </thead>
      <tbody>
        ' . $itemsHtml . '
      </tbody>
    </table>

    <div class="totals-block">
      <table class="bottom-table">
        <tr>
          <td class="remit">
            <div class="hdr">Remarks / Payment Instructions:</div>
DIRECT REMITTANCE TO ACCOUNT
WSC LOGISTICS KENYA LTD
KENYA COMMERCIAL BANK
MVITA BRANCH - MOMBASA
ACCOUNT NUMBER 132 - 1815 - 573
BRANCH CODE 136
SWIFT CODE KCBLKENX
P O BOX 81194 – 80100 MOMBASA KENYA
          </td>

          <td class="totals-cell">
            <table class="tot">
              <tr>
                <td class="label">Subtotal</td>
                <td class="amount">' . h((string)n2($subtotal)) . '</td>
              </tr>
              <tr>
                <td class="label">Discount</td>
                <td class="amount">' . h((string)n2($discount)) . '</td>
              </tr>
              <tr>
                <td class="label">Subtotal Less Discount</td>
                <td class="amount">' . h((string)n2($net)) . '</td>
              </tr>
              <tr>
                <td class="label">Vat Rate ' . h((string)rtrim(rtrim(number_format($vatRate, 2), '0'), '.')) . '%</td>
                <td class="amount">' . h((string)n2($vatAmount)) . '</td>
              </tr>
              <tr>
                <td class="label grand">Total</td>
                <td class="amount grand">' . h((string)n2($total)) . '</td>
              </tr>
              <tr>
                <td class="label grand">Balance Due (USD)</td>
                <td class="amount grand">' . h((string)n2($total)) . '</td>
              </tr>
            </table>
          </td>
        </tr>
      </table>
    </div>

    <div class="audit-footer">
      Served by: ' . h((string)($servedBy !== '' ? $servedBy : '—')) . '
    </div>

  </div>
</body>
</html>';

$options = new Options();
$options->set('isRemoteEnabled', true);
$options->set('isHtml5ParserEnabled', true);
$options->set('defaultFont', 'Arial');

$dompdf = new Dompdf($options);
$dompdf->loadHtml($html, 'UTF-8');
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();

$pdfBytes = $dompdf->output();

while (ob_get_level() > 0) {
    @ob_end_clean();
}

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . str_replace('"', '', $filename) . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: public');

echo $pdfBytes;
exit;