<?php
// ============================================================
// pages/pdf_view.php — Dedicated PDF source page
// ============================================================
// Renders an invoice or quote at fixed A4-portrait dimensions
// with PDF-optimised typography and zero app chrome. Loaded in
// a hidden iframe by view_invoice.php / view_quote.php and
// captured by html2canvas → jsPDF.
//
// Can also be opened directly for preview/debugging:
//   pages/pdf_view.php?type=invoice&id=123&token=...
// ============================================================
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>PDF Preview</title>
  <style>
    /* ── Reset + body ── */
    * { box-sizing: border-box; }
    html, body {
      margin: 0;
      padding: 0;
      background: #ffffff;
      color: #1a1d23;
      font-family: 'Helvetica Neue', Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
    }

    /* ── PDF page container — fixed A4 portrait dimensions ── */
    .pdf-page {
      width: 210mm;
      min-height: 297mm;
      padding: 14mm 14mm;
      background: #ffffff;
      page-break-after: always;
    }
    .pdf-page:last-child { page-break-after: auto; }

    /* ── Header (logo + company info | doc heading + meta) ── */
    .pdf-header {
      display: flex;
      justify-content: space-between;
      align-items: flex-start;
      margin-bottom: 8mm;
    }
    .pdf-header .left { flex: 1; max-width: 60%; }
    .pdf-header .right { text-align: right; }
    .pdf-logo {
      max-width: 50mm;
      max-height: 22mm;
      object-fit: contain;
      display: block;
      margin-bottom: 3mm;
    }
    .pdf-company {
      font-size: 9pt;
      line-height: 1.4;
      color: #5c636e;
    }
    .pdf-doctype {
      font-size: 18pt;
      font-weight: 700;
      letter-spacing: 0.04em;
      margin-bottom: 1mm;
      color: #1a1d23;
    }
    .pdf-status {
      display: inline-block;
      font-size: 8pt;
      font-weight: 600;
      padding: 1mm 2.5mm;
      border-radius: 1mm;
      background: #f1f3f5;
      color: #5c636e;
      letter-spacing: 0.05em;
      vertical-align: middle;
      margin-left: 2mm;
    }
    .pdf-meta {
      margin-top: 3mm;
      font-size: 9pt;
    }
    .pdf-meta-row { display: flex; justify-content: flex-end; margin: 0.6mm 0; gap: 6mm; }
    .pdf-meta-label {
      color: #adb5bd;
      text-transform: uppercase;
      letter-spacing: 0.06em;
      font-size: 7.5pt;
      font-weight: 600;
    }
    .pdf-meta-val {
      font-weight: 700;
      color: #1a1d23;
      font-family: 'DM Mono', 'Courier New', monospace;
      min-width: 28mm;
      text-align: right;
    }
    .pdf-meta-val.expired { color: #e03131; }

    /* ── Validity bar (quotes only) ── */
    .pdf-validity {
      display: inline-block;
      padding: 1.5mm 3mm;
      font-size: 9pt;
      border-radius: 1mm;
      background: #eef2ff;
      color: #3b5bdb;
      margin-bottom: 5mm;
    }
    .pdf-validity.expired {
      background: #fff1f2;
      color: #e03131;
    }

    /* ── Bill To / Prepared For ── */
    .pdf-billto {
      background: #f8f9fa;
      padding: 4mm 5mm;
      border-radius: 1.5mm;
      margin-bottom: 5mm;
    }
    .pdf-billto-label {
      font-size: 7.5pt;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      color: #adb5bd;
      font-weight: 600;
      margin-bottom: 1.5mm;
    }
    .pdf-billto-name { font-size: 12pt; font-weight: 700; color: #1a1d23; margin-bottom: 1mm; }
    .pdf-billto-detail { font-size: 9pt; color: #5c636e; line-height: 1.5; }

    /* ── Description note ── */
    .pdf-desc {
      font-size: 9pt;
      padding: 3mm 4mm;
      background: #fcfcfd;
      border-left: 1mm solid #e5e7eb;
      margin-bottom: 5mm;
      line-height: 1.5;
      white-space: pre-wrap;
      color: #495057;
    }

    /* ── Line items ── */
    .pdf-items {
      width: 100%;
      border-collapse: collapse;
      margin-bottom: 4mm;
    }
    .pdf-items thead th {
      font-size: 8pt;
      text-transform: uppercase;
      letter-spacing: 0.06em;
      color: #5c636e;
      font-weight: 600;
      text-align: left;
      padding: 2.5mm 2.5mm;
      border-bottom: 0.4mm solid #1a1d23;
    }
    .pdf-items thead th.num { text-align: right; }
    .pdf-items tbody td {
      font-size: 10pt;
      padding: 2.5mm 2.5mm;
      border-bottom: 0.2mm solid #e5e7eb;
      vertical-align: top;
    }
    .pdf-items tbody td.num {
      text-align: right;
      font-family: 'DM Mono', 'Courier New', monospace;
    }
    .pdf-items tbody td.subtotal { font-weight: 700; }

    /* ── Total ── */
    .pdf-total {
      text-align: right;
      margin-top: 4mm;
      padding-top: 4mm;
      border-top: 0.5mm solid #1a1d23;
    }
    .pdf-total-label {
      font-size: 8pt;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      color: #adb5bd;
      font-weight: 600;
    }
    .pdf-total-value {
      font-size: 18pt;
      font-weight: 700;
      color: #1a1d23;
      font-family: 'DM Mono', 'Courier New', monospace;
      margin-top: 1mm;
    }

    /* ── Payments table (invoices only) ── */
    .pdf-payments {
      margin-top: 6mm;
      padding-top: 4mm;
      border-top: 0.2mm solid #e5e7eb;
    }
    .pdf-payments h3 {
      font-size: 9pt;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      color: #5c636e;
      font-weight: 600;
      margin: 0 0 2mm 0;
    }
    .pdf-balance-due {
      display: flex;
      justify-content: space-between;
      padding: 3mm 4mm;
      margin-top: 2mm;
      border-radius: 1mm;
      background: #f1f3f5;
      font-family: 'DM Mono', 'Courier New', monospace;
      font-weight: 700;
      font-size: 11pt;
    }
    .pdf-balance-due.paid { background: #d3f9d8; color: #2b8a3e; }
    .pdf-balance-due.due  { background: #fff5f5; color: #c92a2a; }

    /* ── T&Cs page (always page 2) ── */
    .pdf-terms-page {
      page-break-before: always;
    }
    .pdf-terms-title {
      font-size: 10pt;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      color: #5c636e;
      font-weight: 600;
      margin-bottom: 3mm;
    }
    .pdf-terms-intro {
      font-size: 9pt;
      color: #495057;
      margin-bottom: 4mm;
      line-height: 1.5;
    }
    .pdf-terms-body {
      font-size: 9pt;
      line-height: 1.55;
      color: #495057;
      white-space: pre-wrap;
    }

    /* ── Loading state (visible only while data fetches) ── */
    #pdf-loading {
      padding: 50mm 14mm;
      text-align: center;
      font-size: 10pt;
      color: #adb5bd;
    }
  </style>
</head>
<body>
  <div id="pdf-loading">Loading…</div>
  <div id="pdf-root"></div>

  <script>
    // ── URL params ──
    const params = new URLSearchParams(location.search);
    const TYPE   = (params.get('type') || 'invoice').toLowerCase();    // 'invoice' | 'quote'
    const ID     = parseInt(params.get('id')) || 0;
    const TOKEN  = params.get('token') || '';

    // Compute app root the same way page.js does, so this page also works
    // when the app is deployed at a sub-path (e.g. /proart/).
    const _pIdx    = location.pathname.split('/').indexOf('pages');
    const BASE_URL = _pIdx > 0
      ? location.pathname.split('/').slice(0, _pIdx).join('/')
      : '';

    // ── Helpers ──
    const fmtCurrency = v => 'R ' + Number(v || 0).toLocaleString('en-ZA', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    const fmtDate     = iso => {
      if (!iso || iso === '0000-00-00') return '—';
      const [y, m, d] = iso.split(/[-T]/);
      return d + '/' + m + '/' + y;
    };
    const escape = s => String(s == null ? '' : s)
      .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;').replace(/'/g, '&#39;');

    function parseLines(content) {
      if (!content || !content.trim()) return [];
      return content.split(';').map(s => s.trim()).filter(Boolean).map(line => {
        const p = line.split(',');
        return {
          description: p[0] || '',
          quantity:    parseFloat(p[1]) || 0,
          price:       parseFloat(p[2]) || 0,
          discount:    parseFloat(p[3]) || 0,
          total:       parseFloat(p[4]) || 0,
        };
      });
    }

    async function apiGet(path) {
      const sep = path.includes('?') ? '&' : '?';
      const r = await fetch(BASE_URL + path + sep + 'token=' + encodeURIComponent(TOKEN));
      const j = await r.json();
      if (!j.success) throw new Error(j.error || 'API error');
      return j.data;
    }

    // ── Renderers ──
    function renderHeader(company, doctype, number, status, meta) {
      const logoSrc = company.logo_path
        ? (BASE_URL + '/' + company.logo_path.replace(/^\//, ''))
        : (BASE_URL + '/logo.svg');
      const companyLines = [];
      if (company.address) companyLines.push(escape(company.address));
      const ep = [company.email, company.phone].filter(Boolean).join(' | ');
      if (ep) companyLines.push(escape(ep));
      if (company.reg_no) companyLines.push('Reg: ' + escape(company.reg_no));
      if (company.bank)   companyLines.push('Bank: ' + escape(company.bank) + ' | Acc: ' + escape(company.acc || '') + ' | Branch: ' + escape(company.branch || ''));

      const metaRows = meta.map(m =>
        `<div class="pdf-meta-row">
          <span class="pdf-meta-label">${escape(m.label)}</span>
          <span class="pdf-meta-val${m.cls ? ' ' + m.cls : ''}">${escape(m.value)}</span>
        </div>`
      ).join('');

      return `
        <div class="pdf-header">
          <div class="left">
            <img class="pdf-logo" src="${escape(logoSrc)}" alt="" onerror="this.style.display='none'">
            <div class="pdf-company">${companyLines.join('<br>')}</div>
          </div>
          <div class="right">
            <div class="pdf-doctype">${escape(doctype)}${status ? `<span class="pdf-status">${escape(status)}</span>` : ''}</div>
            <div class="pdf-meta">${metaRows}</div>
          </div>
        </div>`;
    }

    function renderBillTo(label, client) {
      if (!client) return '';
      const details = [];
      if (client.address) details.push(escape(client.address));
      const ep = [client.email, client.cell].filter(Boolean).join(' · ');
      if (ep) details.push(escape(ep));
      return `
        <div class="pdf-billto">
          <div class="pdf-billto-label">${escape(label)}</div>
          <div class="pdf-billto-name">${escape(client.clients_name || '—')}</div>
          ${details.length ? `<div class="pdf-billto-detail">${details.join('<br>')}</div>` : ''}
        </div>`;
    }

    function renderDescription(desc) {
      if (!desc || !desc.trim()) return '';
      return `<div class="pdf-desc">${escape(desc)}</div>`;
    }

    function renderItems(lines) {
      if (!lines.length) {
        return `<table class="pdf-items">
          <thead><tr>
            <th>Description</th><th class="num">Qty</th><th class="num">Unit Price</th><th class="num">Discount</th><th class="num">Subtotal</th>
          </tr></thead>
          <tbody><tr><td colspan="5" style="padding:8mm;text-align:center;color:#adb5bd;">No line items</td></tr></tbody>
        </table>`;
      }
      const rows = lines.map(l => {
        const disc = l.discount > 0 ? (l.discount * 100).toFixed(0) + '%' : '—';
        return `<tr>
          <td>${escape(l.description)}</td>
          <td class="num">${l.quantity}</td>
          <td class="num">${fmtCurrency(l.price)}</td>
          <td class="num">${disc}</td>
          <td class="num subtotal">${fmtCurrency(l.total)}</td>
        </tr>`;
      }).join('');
      return `<table class="pdf-items">
        <thead><tr>
          <th>Description</th>
          <th class="num" style="width:18mm;">Qty</th>
          <th class="num" style="width:28mm;">Unit Price</th>
          <th class="num" style="width:22mm;">Discount</th>
          <th class="num" style="width:30mm;">Subtotal</th>
        </tr></thead>
        <tbody>${rows}</tbody>
      </table>`;
    }

    function renderTotal(label, total) {
      return `<div class="pdf-total">
        <div class="pdf-total-label">${escape(label)}</div>
        <div class="pdf-total-value">${fmtCurrency(total)}</div>
      </div>`;
    }

    function renderPaymentsBlock(invoiceTotal, payments) {
      if (!payments || !payments.length) return '';
      const totalPaid = payments.reduce((s, p) => s + (parseFloat(p.amount) || 0), 0);
      const balance   = invoiceTotal - totalPaid;
      const isPaid    = balance <= 0.005;
      const dueClass  = isPaid ? 'paid' : 'due';
      const rows = payments.map(p =>
        `<tr><td>${fmtDate(p.date_paid || p.payment_date)}</td><td>${escape(p.notes || '')}</td><td class="num">${fmtCurrency(p.amount)}</td></tr>`
      ).join('');
      return `<div class="pdf-payments">
        <h3>Payment History</h3>
        <table class="pdf-items">
          <thead><tr><th>Date</th><th>Notes</th><th class="num">Amount</th></tr></thead>
          <tbody>${rows}</tbody>
        </table>
        <div class="pdf-balance-due ${dueClass}">
          <span>${isPaid ? 'PAID IN FULL' : 'BALANCE DUE'}</span>
          <span>${fmtCurrency(Math.max(0, balance))}</span>
        </div>
      </div>`;
    }

    function renderTermsPage(introText, terms) {
      if (!terms || !terms.trim()) return '';
      return `<div class="pdf-page pdf-terms-page">
        ${introText ? `<div class="pdf-terms-intro">${escape(introText)}</div>` : ''}
        <div class="pdf-terms-title">Terms &amp; Conditions</div>
        <div class="pdf-terms-body">${escape(terms)}</div>
      </div>`;
    }

    // ── Type-specific assemblers ──
    async function renderInvoice() {
      const [resp, company] = await Promise.all([
        apiGet('/api/invoices.php?action=get&id=' + ID),
        apiGet('/api/data.php?module=company&action=get'),
      ]);
      const inv      = resp.invoice;
      const payments = resp.payments || [];
      const lines    = parseLines(inv.invoice_content);

      document.title = 'Invoice #' + inv.invoice_no;

      const meta = [
        { label: 'Invoice #', value: inv.invoice_no },
        { label: 'Date',      value: fmtDate(inv.date_created || inv.date_sent) },
        { label: 'Due Date',  value: fmtDate(inv.date_due) },
      ];

      const html = `
        <div class="pdf-page">
          ${renderHeader(company, 'INVOICE', inv.invoice_no, inv.status, meta)}
          ${renderBillTo('Bill To', inv)}
          ${renderDescription(inv.description)}
          ${renderItems(lines)}
          ${renderTotal('Invoice Total', inv.total)}
          ${renderPaymentsBlock(parseFloat(inv.total) || 0, payments)}
        </div>
        ${renderTermsPage(
          'This invoice is payable on the due date stated above. Thank you for your business.',
          company.Tc_Cs
        )}`;
      document.getElementById('pdf-root').innerHTML = html;
    }

    async function renderQuote() {
      const [q, company] = await Promise.all([
        apiGet('/api/quotes.php?action=get&id=' + ID),
        apiGet('/api/data.php?module=company&action=get'),
      ]);
      const lines = parseLines(q.quote_content);

      document.title = 'Quote #' + q.quote_no;

      const isExpired = q.date_exp && new Date(q.date_exp) < new Date(new Date().toDateString());
      const meta = [
        { label: 'Quote #',     value: q.quote_no },
        { label: 'Date',        value: fmtDate(q.date_created || q.date_sent) },
        { label: 'Valid Until', value: fmtDate(q.date_exp), cls: isExpired ? 'expired' : '' },
      ];

      const validityHtml = q.date_exp
        ? `<div class="pdf-validity${isExpired ? ' expired' : ''}">${isExpired ? 'Expired on ' : 'Valid until '}${fmtDate(q.date_exp)}</div>`
        : '';

      const html = `
        <div class="pdf-page">
          ${renderHeader(company, 'QUOTATION', q.quote_no, q.status, meta)}
          ${validityHtml}
          ${renderBillTo('Prepared For', q)}
          ${renderDescription(q.description)}
          ${renderItems(lines)}
          ${renderTotal('Quotation Total', q.total)}
        </div>
        ${renderTermsPage(
          'This quotation is valid for the period stated above unless otherwise agreed.',
          company.Tc_Cs
        )}`;
      document.getElementById('pdf-root').innerHTML = html;
    }

    // ── Boot ──
    (async () => {
      try {
        if (!ID) throw new Error('Missing id parameter');
        if (!TOKEN) throw new Error('Missing token parameter');
        if (TYPE === 'quote')  await renderQuote();
        else                   await renderInvoice();
      } catch (e) {
        document.getElementById('pdf-root').innerHTML =
          '<div style="padding:14mm;color:#c92a2a;font-size:10pt;">Error: ' + escape(e.message) + '</div>';
      } finally {
        document.getElementById('pdf-loading').style.display = 'none';
        // Signal to the parent window (if any) that rendering is complete
        if (window.parent && window.parent !== window) {
          try { window.parent.postMessage({ type: 'pdf-view-ready' }, '*'); } catch (_) {}
        }
        document.body.dataset.pdfReady = '1';
      }
    })();
  </script>
</body>
</html>