<?php
declare(strict_types=1);
/**
 * LOA signing page
 * Mirrors contracts.php features but reads/writes under /loa and uses "Authorisation" wording.
 */
error_reporting(E_ALL);
ini_set("display_errors", 1);

date_default_timezone_set("Australia/Hobart");
ini_set("default_charset", "UTF-8");
mb_internal_encoding("UTF-8");

require_once __DIR__ . "/Parsedown.php";
require_once __DIR__ . '/ParsedownExtra.php';
require_once __DIR__ . "/dompdf/autoload.inc.php";
require_once __DIR__ . '/../vendor/autoload.php'; // for setasign/fpdf & setasign/fpdi

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception as MailerException;
require_once __DIR__ . "/../internal/phpmailer/src/Exception.php";
require_once __DIR__ . "/../internal/phpmailer/src/PHPMailer.php";
require_once __DIR__ . "/../internal/phpmailer/src/SMTP.php";

// at the top, before any output
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $ok = isset($_POST["csrf"], $_SESSION["csrf"]) && hash_equals($_SESSION["csrf"], $_POST["csrf"]);
    if (!$ok) {
        http_response_code(403);
        exit("Invalid CSRF token");
    }
}

if (empty($_SESSION["csrf"])) {
    $_SESSION["csrf"] = bin2hex(random_bytes(32));
}
$csrf = $_SESSION["csrf"];

// Load optional config
$cfg = @include __DIR__ . "/config.php";
$cfg = is_array($cfg) ? $cfg : [];

// Core settings (can be overridden by config.php)
$CFG = [
    "brand_name" => $cfg["dev_name"] ?? "Modulos Design",
    "from_email" => $cfg["from_address"] ?? "drafting@modulosdesign.com.au",
    "bcc_email"  => $cfg["bcc_email"] ?? "drafting@modulosdesign.com.au",
    "secret"     => $cfg["loa_secret"] ?? ($cfg["admin_secret"] ?? "change-me"),
];

// Compute base URL
$https  = !empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off";
$scheme = $https ? "https" : "https";
$host   = $_SERVER["HTTP_HOST"] ?? "localhost";
$base   = rtrim(dirname($_SERVER["SCRIPT_NAME"] ?? ""), "/\\");
$CFG["base_url"] = $scheme . "://" . $host . ($base ? $base . "/" : "/");

/* ----------------------------- helpers ----------------------------- */
function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES, "UTF-8"); }

function getClientIp(): string {
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $parts = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
        foreach ($parts as $ip) {
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) return $ip;
        }
        foreach ($parts as $ip) if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
    }
    if (!empty($_SERVER['HTTP_X_REAL_IP']) && filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP)) return $_SERVER['HTTP_X_REAL_IP'];
    if (!empty($_SERVER['REMOTE_ADDR']) && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP)) return $_SERVER['REMOTE_ADDR'];
    return "UNKNOWN";
}

function tokenForJob(string $job, string $secret): string { return hash_hmac("sha256", "loa|" . $job, $secret); }
function verifyToken(string $job, string $token, string $secret): bool {
    return $token !== "" && hash_equals(tokenForJob($job, $secret), $token);
}

/* --------------------------- Front matter --------------------------- */
function _fm_trim_quotes(string $v): string {
    $v = trim($v);
    if ($v !== "" && $v[0] === "'" && substr($v, -1) === "'") return stripslashes(substr($v, 1, -1));
    if ($v !== "" && $v[0] === '"' && substr($v, -1) === '"') return stripslashes(substr($v, 1, -1));
    return $v;
}

function parseFrontMatter(string $text): array {
    if (function_exists("yaml_parse")) {
        $arr = @yaml_parse($text);
        return is_array($arr) ? $arr : [];
    }
    $lines = preg_split('/\R/', rtrim($text));
    $root  = [];
    $stack = [ ["indent" => -1, "ref" => &$root] ];

    foreach ($lines as $raw) {
        if ($raw === "") continue;
        $trimmed = ltrim($raw, " ");
        if ($trimmed === "" || $trimmed[0] === "#") continue;

        $indent = strlen($raw) - strlen($trimmed);
        while (count($stack) > 1 && $indent <= $stack[array_key_last($stack)]["indent"]) {
            array_pop($stack);
        }
        $parent =& $stack[array_key_last($stack)]["ref"];

        // List item
        if (preg_match('/^-\s*(.*)$/', $trimmed, $m)) {
            $val = $m[1];
            if (!is_array($parent)) $parent = [];
            if ($val === "") {
                $parent[] = [];
                $stack[] = ["indent" => $indent, "ref" => &$parent[array_key_last($parent)]];
            } else {
                $parent[] = _fm_trim_quotes($val);
            }
            continue;
        }

        // Key: value or Key:
        if (preg_match('/^([A-Za-z0-9_.-]+):\s*(.*)$/', $trimmed, $m)) {
            $key = $m[1];
            $val = $m[2];
            if ($val === "") {
                if (!isset($parent[$key]) || !is_array($parent[$key])) $parent[$key] = [];
                $stack[] = ["indent" => $indent, "ref" => &$parent[$key]];
            } else {
                $parent[$key] = _fm_trim_quotes($val);
            }
        }
    }
    return $root;
}

function getByPath($arr, string $path, $default = "") {
    $keys = explode(".", $path);
    foreach ($keys as $k) {
        if ($k === "") continue;
        if (is_array($arr) && array_key_exists($k, $arr)) {
            $arr = $arr[$k];
        } else {
            return $default;
        }
    }
    return $arr;
}

function setByPath(array &$arr, string $path, $value): void {
    $keys = explode(".", $path);
    $ref =& $arr;
    foreach ($keys as $k) {
        if ($k === "") continue;
        if (!isset($ref[$k]) || !is_array($ref[$k])) $ref[$k] = [];
        $ref =& $ref[$k];
    }
    $ref = $value;
}

function parseFrontMatterForJob(string $job): array {
    $safe = preg_match('/^\d{1,10}$/', $job) ? $job : "default";
    $path = __DIR__ . "/loa/$safe/" . $safe . ".md";
    if (!is_file($path)) $path = __DIR__ . "/loa/default-authorisation.md";
    $md = @file_get_contents($path);
    if ($md && preg_match('/^\s*---\s*\n(.*?)\n---\s*\n/s', $md, $m)) {
        return parseFrontMatter($m[1]);
    }
    return [];
}

function abs_url(string $rel): string {
    $https  = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
    $scheme = $https ? 'https' : 'https';
    $host   = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $dir    = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/\\');
    $root   = $scheme . '://' . $host . ($dir ? $dir . '/' : '/');
    return $root . ltrim($rel, '/');
}

function council_recipients(array $vars, array $cfg): array {
    $to = [];
    if (!empty($cfg['council_email'])) $to[] = $cfg['council_email'];

    $councilName = (string)getByPath($vars, 'property.council', '');
    if ($councilName && !empty($cfg['council_map'][$councilName])) {
        $to[] = $cfg['council_map'][$councilName];
    }
    // TODO: if you later store locality/postcode, you can look up by locality too.

    return array_values(array_unique(array_filter($to)));
}

/* --------------------- Render LOA Markdown to HTML --------------------- */
function md_to_html(string $md): string {
    $pd = class_exists('ParsedownExtra') ? new ParsedownExtra() : new Parsedown();
    $pd->setSafeMode(true);
    // Optional: $pd->setBreaksEnabled(true); // if you want single newlines as <br>
    return $pd->text($md);
}

function loadLoaHtml(string $job, array $overrides = []): string {
    $safe = preg_match('/^\d{1,10}$/', $job) ? $job : "default";
    $path = __DIR__ . "/loa/$safe/" . $safe . ".md";
    if (!is_file($path)) $path = __DIR__ . "/loa/default-authorisation.md";

    $md = file_get_contents($path);

    // Split front matter and body
    $vars = [];
    $body = $md;
    if (preg_match('/^\s*---\s*\n(.*?)\n---\s*\n(.*)$/s', $md, $m)) {
        $front = $m[1];
        $body  = $m[2];
        $vars  = parseFrontMatter($front);
    }

    // Defaults available
    $base = [
        "dev" => [
            "name"    => $GLOBALS["cfg"]["dev_name"]    ?? "Modulos Design",
            "email"   => $GLOBALS["cfg"]["dev_email"]   ?? "drafting@modulosdesign.com.au",
            "phone"   => $GLOBALS["cfg"]["dev_phone"]   ?? "0402 984 082",
            "address" => $GLOBALS["cfg"]["dev_address"] ?? "34 Coplestone St, Scottsdale, Tas 7260",
        ],
        "client" => [
            "name"    => "",
            "email"   => "",
            "phone"   => "",
            "address" => "",
        ],
        "job"    => $safe,
        "today"  => date("F j, Y"),
    ];

    // Merge: overrides > front matter > base
    $merged = array_replace_recursive($base, $vars, $overrides);

    // Flat GET overrides like client_name=...
    foreach (["client_name" => "client.name", "client_email" => "client.email", "client_phone" => "client.phone"] as $q => $pathKey) {
        if (isset($_GET[$q]) && $_GET[$q] !== "") {
            setByPath($merged, $pathKey, (string)$_GET[$q]);
        }
    }

    // Replace [path.to.value] placeholders
    $body = preg_replace_callback('/\[([a-zA-Z0-9_.-]+)\]/', function ($m) use ($merged) {
        $val = getByPath($merged, $m[1]);
        return is_scalar($val) ? (string)$val : "";
    }, $body);

    // Convert Markdown to HTML (ParsedownExtra supports tables)
    return md_to_html($body);
}

/* --------------------------- HTML wrappers --------------------------- */
function headerWithTitle(string $title, ?string $job = null, ?string $preparedDate = null, string $context = "web"): string {
    $safeTitle        = h($title);
    $safeJob          = h((string)$job);
    $safePreparedDate = h((string)$preparedDate);

    $https  = !empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off";
    $scheme = $https ? "https" : "https";
    $host   = $_SERVER["HTTP_HOST"] ?? "localhost";
    $dir    = rtrim(dirname($_SERVER["SCRIPT_NAME"] ?? ""), "/\\") . "/";

    $cssLinks = $context === "web"
        ? <<<HTML
  <link rel="preconnect" href="https://cdn.jsdelivr.net">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
  <link href="../internal/css/blueprint.css" rel="stylesheet">
  <link href="../internal/css/print.css" rel="stylesheet" media="print">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
  <link href="style.css" rel="stylesheet">
HTML
        : <<<HTML
  <link href="../internal/css/blueprint.css" rel="stylesheet">
  <link href="style.css" rel="stylesheet">
  <style>
    @page { margin: 5mm 10mm 10mm 10mm; }
    body { background:#fff;}
    .container { max-width: 780px; margin: 0 auto; font-size:0.7rem; }
    .shadow-sm { box-shadow: none !important; }
    .rounded-3 { border-radius: 0 !important; }
    .bg-white { background: #fff !important; }
    .d-print-none, .noprint { display: none !important; }
    .img-logo { max-height: 40px; }
    .page-header { display: table; width: 100%; table-layout: fixed; }
    .page-header > .col-4 { display: table-cell; width: 33.333%; vertical-align: middle; padding: 0 8px; }
    .page-header .text-start { text-align: left; }
    .page-header .text-center { text-align: center; }
    .page-header .text-end { text-align: right; }
    .compiled-signatures { display: table; width: 100%; table-layout: fixed; margin-top: 1rem; }
    .compiled-signatures .compiled-signature { display: table-cell; width: 35%; vertical-align: bottom; padding: 0 8px; }
    .compiled-signatures img { max-width: 100%; height: auto; }
    table { border-collapse: collapse; width: 100%; margin: 12px 0; }
	th, td { border: 1px solid #ddd; padding: 2px 4px; vertical-align: top; }
	th { background: #f6f6f6; text-align: left; }
  </style>
HTML;

    $jsLinks = $context === "web"
        ? <<<HTML
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.bundle.min.js"></script>
HTML
        : "";

    $nav = $context === "web"
        ? <<<HTML
  <nav class="navbar bg-brown-dark brown-light border-bottom border-body d-print-none" data-bs-theme="dark">
    <div class="container-fluid">
      <a class="navbar-brand brown-light" href="#">
        <img src="../internal/images/blueprint-logo-light.png" alt="Modulos Design" width="30" height="24" class="d-inline-block align-text-top" >
        Modulos Design
      </a>
    </div>
  </nav>
HTML
        : "";

    return <<<HTML
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>{$safeJob} - {$safeTitle}</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="robots" content="noindex">
  <link rel="shortcut icon" href="../internal/images/blueprint.ico" type="image/x-icon">
  <base href="{$scheme}://{$host}{$dir}">
{$cssLinks}
{$jsLinks}
</head>
<body>
{$nav}
  <main class="container my-4">
    <div class="bg-white p-4 p-md-5 rounded-0 shadow-sm">
      <div class="row align-items-center page-header">
        <div class="col-12 col-md-4 text-start">
          <img class="img-fluid pt-2 img-logo" src="../internal/images/blueprint-full-logo-medium.png" height="100" alt="Modulos Design">
        </div>
        <div class="col-12 col-md-8 text-end pt-3">
          <h3 class="fw-bold mb-1" style="color:#373a3c;">Job: {$safeJob}</h3>
          <h4 class="mb-1"><span class="fw-bold text-secondary">{$safePreparedDate}</span></h4>
        </div>
      </div>
HTML;
}

function footerFor(string $context = "web"): string {
    $extra = $context === "web"
        ? <<<HTML
  <script>
    function printDoc(){ window.print(); }
  </script>
HTML
        : "";
    return <<<HTML
    </div>
  </main>
{$extra}
</body>
</html>
HTML;
}

/* --------------------------- Email helpers --------------------------- */
function salutationFromName(string $fullName): string {
    $name = str_replace("\xC2\xA0", " ", $fullName);
    $name = trim(preg_replace('/\s+/u', ' ', $name));
    if ($name === "") return "there";

    $name = preg_replace('/,?\s*(Jr\.?|Sr\.?|II|III|IV|MD|Ph\.?D|Esq\.?|J\.?D\.?|M\.?B\.?A\.?|RN|DDS|DMD)\s*$/iu', '', $name);
    $honorifics = '(mr|mrs|ms|miss|mx|dr|prof|sir|dame|lord|lady|hon|rev|fr|father|pastor|rabbi|imam|capt|cpt|gen|col|maj|sgt|officer|chief|coach|pres|sen|rep)';
    $name = preg_replace('/^(?:' . $honorifics . ')\.?[\s\x{00A0}]+/iu', '', $name);
    while (preg_match('/^' . $honorifics . '\.?[\s\x{00A0}]+/iu', $name)) {
        $name = preg_replace('/^' . $honorifics . '(\.?)[\s\x{00A0}]+/iu', '', $name, 1);
    }

    $tokens = preg_split('/[\s\x{00A0}]+/u', $name);
    if (!$tokens) return "there";
    foreach ($tokens as $tok) {
        $t = rtrim($tok, ".");
        if (!preg_match('/^[A-Za-z]\.?$/u', $t)) return $t;
    }
    return $tokens[0] ?: "there";
}

function email_logo_png_cid(PHPMailer $mail, string $dataUrl, string $alt = "Modulos Design", int $width = 140): string {
    if ($dataUrl === "") return "";
    $dataUrl = trim($dataUrl);
    $prefix = "data:image/png;base64,";
    if (stripos($dataUrl, $prefix) !== 0) return "";
    $bin = base64_decode(substr($dataUrl, strlen($prefix)), true);
    if ($bin === false || $bin === "") return "";
    $cid = "logo_" . substr(sha1($bin), 0, 12) . "@modulos";
    $mail->addStringEmbeddedImage($bin, $cid, "logo.png", "base64", "image/png");
    return '<img src="cid:' . $cid . '" alt="' . h($alt) . '" width="' . (int)$width . '" style="display:block;border:0;outline:0;text-decoration:none;height:auto;">';
}

function email_cta(string $href, string $label): string {
    $safeUrl = h($href);
    $safeLbl = h($label);
    return <<<HTML
<!--[if mso]>
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" href="{$safeUrl}"
        style="height:42px;v-text-anchor:middle;width:240px;" stroked="f" fillcolor="#635A4A">
  <w:anchorlock/>
  <center style="color:#ffffff;font-family:Arial,sans-serif;font-size:16px;line-height:1.6;">{$safeLbl}</center>
</v:rect>
<![endif]-->
<!--[if !mso]><!-- -->
<a href="{$safeUrl}"
   style="background:#635A4A;border-radius:0;display:inline-block;padding:12px 24px;color:#ffffff;
          text-decoration:none;font-weight:700;font-size:14px;line-height:1.6;mso-hide:all"
   target="_blank" rel="noopener">{$safeLbl}</a>
<!--<![endif]-->
HTML;
}

function email_signature_block(string $safeSignatureHtml, string $company = "Modulos Design"): string {
    $safeCo = h($company);
    return <<<HTML
<div style="font-size:14px;line-height:1.6;margin-top:18px;">
  <b>Kind Regards,</b><br><br>{$safeSignatureHtml}<br>
  Benjamin Harris<br>{$safeCo}<br>
  0402 984 082  |  drafting@modulosdesign.com.au
</div>
HTML;
}

/**
 * Reusable frame: preheader + header band + {contentHtml} + footer band
 */
function email_frame(string $preheader, string $logoHtml, string $job, string $contentHtml, string $footerNote = "This is an automated message. Please reply to this email if you have any questions."): string {
    $safePre  = h($preheader);
    $safeJob  = h($job);
    $safeFoot = h($footerNote);

    return <<<HTML
<!-- Preheader -->
<div style="display:none;max-height:0;overflow:hidden;opacity:0;mso-hide:all;font-size:0;line-height:0;">{$safePre}</div>

<div style="background:#f6f7fb;padding:24px;font-size:14px;line-height:1.6;">
  <table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" width="600"
         style="width:600px;max-width:100%;background:#ffffff;border-radius:8px;overflow:hidden;
                font-size:14px;line-height:1.6;font-family:Arial,Helvetica,sans-serif;">
    <tr>
      <td style="font-size:14px;line-height:1.6;padding:20px 24px;background:#D9CCC1;color:#ffffff;">
        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="font-size:14px;line-height:1.6;">
          <tr>
            <td style="font-size:14px;line-height:1.6;">{$logoHtml}</td>
            <td align="right" style="font-weight:700;font-size:14px;line-height:1.6;">Job #{$safeJob}</td>
          </tr>
        </table>
      </td>
    </tr>

    {$contentHtml}

    <tr>
      <td style="padding:12px 24px;background:#28261E;color:#D9CCC1;font-size:14px;line-height:1.6;">
        {$safeFoot}
      </td>
    </tr>
  </table>
</div>
HTML;
}


function buildSignedLoaEmail(
    string $logoHtml,
    string $viewUrl,
    string $job,
    string $clientName = "",
    string $preparedDate = "",
    string $company = "Modulos Design",
    string $safeSignature = ""
): array {
    $firstName     = salutationFromName($clientName);
    $firstNameSafe = h($firstName);
    $safeUrl       = h($viewUrl);
    $safeJob       = h($job);
    $safePrepared  = h($preparedDate);
    $preparedPart  = $preparedDate ? " (prepared {$safePrepared})" : "";

    $subject = "{$safeJob} – Copy of Signed Authorisation";

    $cta = email_cta($safeUrl, "View Authorisation");
    $sig = email_signature_block($safeSignature, $company);

    $content = <<<HTML
    <tr>
      <td style="padding:28px 24px 8px;line-height:1.6;color:#635A4A;font-size:14px;">
        <div style="font-size:14px;margin-bottom:8px;line-height:1.6;">Hello {$firstNameSafe},</div>
        <div>Thank you for signing the authorisation{$preparedPart}. A copy is attached for your records,
        and you can view or download it anytime using the link below:</div>
      </td>
    </tr>
    <tr>
      <td align="center" style="padding:20px 24px 8px;font-size:14px;line-height:1.6;">{$cta}</td>
    </tr>
    <tr>
      <td style="padding:8px 24px 24px;font-size:14px;line-height:1.6;color:#635A4A;">
        <div>If the button doesn’t work, copy and paste this link into your browser:<br>
          <span style="word-break:break-all;color:#635A4A;">{$safeUrl}</span>
        </div>
        {$sig}
      </td>
    </tr>
HTML;

    $html = email_frame(
        "Thank you for signing your authorisation — here’s your copy and access link.",
        $logoHtml,
        $job,
        $content
    );

    $alt = "Hello {$firstName},\n\nThe authorisation has been signed{$preparedPart}.\n\nView/download: {$viewUrl}\n\nThanks,\n{$company}";

    return [$subject, $html, $alt];
}


function buildCouncilRequestEmail(
    string $logoHtml,
    string $job,
    array  $vars,
    string $loaPublicUrl,
    string $company = "Modulos Design",
    string $safeSignature = ""
): array {
    $addr     = (string)getByPath($vars, 'property.address', '');
    $pid      = (string)getByPath($vars, 'property.pid', '');
    $title    = (string)getByPath($vars, 'property.title', '');
    $vol      = (string)getByPath($vars, 'property.vol', '');
    $folio    = (string)getByPath($vars, 'property.folio', '');
    $owners   = (string)getByPath($vars, 'client.name', '');
    $prepared = (string)getByPath($vars, 'dates.prepared', date('F j, Y'));

    $titleRef  = $title ?: trim($vol . '/' . $folio, '/');
    $safeAddr  = h($addr);
    $safePid   = h($pid);
    $safeTitle = h($titleRef);
    $safeOwners= h($owners);
    $safeJob   = h($job);
    $safeDate  = h($prepared);
    $safeUrl   = h($loaPublicUrl);
    $safeCo    = h($company);

    $subject = "Request for Planning & Plumbing Information – {$safeAddr} (PID {$safePid}, Title {$safeTitle}) – Job #{$safeJob}";

    $sig = email_signature_block($safeSignature, $company);
    $cta = email_cta($safeUrl, "View Signed LOA");

    $content = <<<HTML
    <tr><td style="padding:22px 24px;color:#222;">
      <p>Good day,</p>
      <p>We’re requesting planning and plumbing information for:</p>

      <table role="presentation" cellpadding="0" cellspacing="0" width="100%" style="border-collapse:collapse;">
        <tr><td style="border:1px solid #ddd;padding:8px;font-weight:600;width:160px;">Property Address</td><td style="border:1px solid #ddd;padding:8px;">{$safeAddr}</td></tr>
        <tr><td style="border:1px solid #ddd;padding:8px;font-weight:600;">Registered Owner(s)</td><td style="border:1px solid #ddd;padding:8px;">{$safeOwners}</td></tr>
        <tr><td style="border:1px solid #ddd;padding:8px;font-weight:600;">PID</td><td style="border:1px solid #ddd;padding:8px;">{$safePid}</td></tr>
        <tr><td style="border:1px solid #ddd;padding:8px;font-weight:600;">Title / Volume–Folio</td><td style="border:1px solid #ddd;padding:8px;">{$safeTitle}</td></tr>
        <tr><td style="border:1px solid #ddd;padding:8px;font-weight:600;">LOA prepared</td><td style="border:1px solid #ddd;padding:8px;">{$safeDate}</td></tr>
      </table>

      <p style="margin-top:14px;">Specifically, could you please supply or confirm:</p>
      <ul style="margin:0 0 0 18px;padding:0;">
        <li>Record of any recent or active Development/Building/Plumbing Applications and associated permit numbers and decisions;</li>
        <li>Any additional planning advice or pre-application notes Council considers relevant.</li>
      </ul>

      <p style="margin-top:14px;">A signed Letter of Authority is attached. You can also view it here:</p>
      <div style="margin:10px 0 18px;">{$cta}</div>
      <div style="font-size:12px;color:#555;">If the button doesn’t work, copy and paste this link:<br>
        <span style="word-break:break-all;color:#635A4A;">{$safeUrl}</span>
      </div>

      {$sig}
    </td></tr>
HTML;

    $html = email_frame(
        "Request for planning & plumbing information for {$addr}.",
        $logoHtml,
        $job,
        $content,
        "Please reply to this email with the requested information or next steps."
    );

    $alt = "Request for planning & plumbing info\n\n"
        . "Address: {$addr}\n"
        . "Owners: {$owners}\n"
        . "PID: {$pid}\n"
        . "Title: {$titleRef}\n"
        . "LOA prepared: {$prepared}\n\n"
        . "Please provide scheme & zoning, overlays, constraints/easements, stormwater/sewer/water service info, "
        . "any recent DA/BA/Plumbing records, and any other relevant advice.\n\n"
        . "LOA (view): {$loaPublicUrl}\n\n"
        . "Thanks,\n{$company}";

    return [$subject, $html, $alt];
}


function getHtmlUrl(string $htmlName): string {
    $https  = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
    $scheme = $https ? 'https' : 'https';
    $host   = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $dir    = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? ''), '/\\');
    return $scheme . '://' . $host . ($dir ? $dir : '') . '/' . $htmlName;
}

/* ------------------------------- Routing ------------------------------- */
$job   = isset($_REQUEST["job"]) ? preg_replace('/\D+/', '', (string)$_REQUEST["job"]) : "";
$token = $_REQUEST["token"] ?? "";

// Resolve some prepared/derived values
$preparedDate = getByPath(parseFrontMatterForJob($job), "dates.prepared", date("F j, Y"));

if ($_SERVER["REQUEST_METHOD"] === "GET") {
    if (!$job || !verifyToken($job, $token, $CFG["secret"])) {
        http_response_code(403);
        echo "Auth required";
        exit;
    }

    // If a signed file already exists for this job, redirect there
    $pattern = __DIR__ . "/loa/{$job}/{$job}_signed_loa*.pdf";
    $matches = glob($pattern);
    if ($matches) {
        usort($matches, fn($a, $b) => filemtime($b) <=> filemtime($a));
        $latest = basename($matches[0]);
        header("Location: loa/{$job}/" . $latest, true, 302);
        exit;
    }

    // Render unsigned page
    $HEADER = headerWithTitle("Unsigned Authorisation", $job, $preparedDate, "web");
    $LOA_HTML = loadLoaHtml($job);

    echo $HEADER;
    echo $LOA_HTML;

    // Signature UI (mirrors contracts.php)
?>
<div id="ui-unsigned"> 
    <form method="post" class="noprint" id="signature_form">
        <div id="signature-container">
            <div id="canvas-container">
                <canvas id="signature-pad" class="signature-pad" width="188" height="58.66"></canvas>
            </div>
        </div>

        <div class="animate slide">
            <div id="signature-controls" class="d-flex gap-2 justify-content-center mt-3">
                <button id="reset" type="button" class="btn btn-warning rounded-0">Clear</button>
                <button data-bs-toggle="modal" data-bs-target="#modal-qr" type="button" class="btn btn-secondary rounded-0">Sign on mobile</button>
                <button id="confirm" type="submit" class="btn btn-success rounded-0" disabled>Sign</button>
            </div>
        </div>

        <div class="flow" style="max-width: 330px; margin-inline-start: auto;">
            <h3 class="margin-top loading-signed hidden | animate slide" style="color: var(--clr-green-500); font-weight: 700;">Saving authorisation…</h3>
            <small class="loading-signed hidden | animate slide delay-16"
                   style="font-weight: 600; color: var(--clr-blue-700);">
                This shouldnt take more than a minute.
            </small>
        </div>

        <input type="hidden" name="csrf" value="<?php echo $csrf; ?>">
        <input type="hidden" name="job" value="<?php echo h($job); ?>">
        <input type="hidden" name="token" value="<?php echo h($token); ?>">
        <input type="hidden" id="client_signature" name="client_signature" />
        <input type="hidden" name="client_tz" value="">
    </form>

    <div class="modal fade" tabindex="-1" id="modal-qr" aria-labelledby="modal-qrLabel" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content">
                <div class="modal-body qr-code-container">
                    <button id="close-modal-qr" type="button" class="btn-close" data-bs-dismiss="modal-qr" aria-label="Close"></button>
                    <canvas id="qr-code"></canvas>
                </div>
            </div>
        </div>
    </div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/qrious@4.0.2/dist/qrious.min.js"></script>
<script id="loa_script_unsigned" type="module">
  signature("#signature-pad");
  function signature(selector) {
      if (!document.querySelector(selector)) return;

      const canvas = document.querySelector(selector);
      const sigPad = new SignaturePad(canvas, {
          penColor: "hsl(200, 100%, 30%)",
          minDistance: 2,
      });

      resizeCanvas();

      if (localStorage.getItem("client_signature_loa_<?php echo h($job); ?>")) {
          document.querySelector("#confirm").disabled = false;
      }

      sigPad.addEventListener("afterUpdateStroke", () => {
          let data = sigPad.toDataURL("image/png");
          document.querySelector("#client_signature").value = data;
          localStorage.setItem("client_signature_loa_<?php echo h($job); ?>", data);
          document.querySelector("#confirm").disabled = false;
      });

      document.querySelector("#reset")?.addEventListener("click", (e) => {
          sigPad.clear();
          localStorage.removeItem("client_signature_loa_<?php echo h($job); ?>");
          document.querySelector("#client_signature").value = null;
          document.querySelector("#confirm").disabled = true;
      });

      document.querySelector("#signature_form").addEventListener("submit", (e) => {
          e.target.querySelectorAll(".loading-signed").forEach((el) => el.classList.remove("hidden"));
          e.target.querySelector("#canvas-container").classList.add("just-signed");
          // allow submit to continue
      });

      window.onresize = resizeCanvas;

      function resizeCanvas() {
          const ratio = Math.max(window.devicePixelRatio || 1, 1);
          canvas.width = canvas.offsetWidth * ratio;
          canvas.height = canvas.offsetHeight * ratio;
          canvas.getContext("2d").scale(ratio, ratio);

          let data = localStorage.getItem("client_signature_loa_<?php echo h($job); ?>");
          if (data) {
              sigPad.fromDataURL(data);
              document.querySelector("#client_signature").value = data;
          }
      }
  }
</script>
<script>
    (function () {
        const modal = document.getElementById('modal-qr');
        const btnClose = document.getElementById('close-modal-qr');
        const canvas = document.getElementById('qr-code');

        if (canvas && window.QRious) {
            new QRious({
                element: canvas,
                value: window.location.href,
                foreground: 'hsl(200, 30%, 20%)',
                padding: 0,
                size: 500
            });
        }

        btnClose?.addEventListener('click', function () {
        try { if (modal.open) modal.close(); else modal.removeAttribute('open'); } catch (e) { modal.removeAttribute('open'); }
    });

        modal?.addEventListener('click', function (e) {
        const r = modal.getBoundingClientRect();
        const inside = e.clientY >= r.top && e.clientY <= r.bottom && e.clientX >= r.left && e.clientX <= r.right;
        if (!inside) {
        try { modal.close(); } catch (err) { modal.removeAttribute('open'); }
    }
    });

        try {
        var tz = Intl.DateTimeFormat().resolvedOptions().timeZone || '';
        var tzField = document.querySelector('input[name="client_tz"]');
        if (tzField) tzField.value = tz;
    } catch (e) {}
    })();
</script>
</body>
</html>
<?php
    exit;
}

/* ---------------------------------- POST ------------------------------------- */
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    if (!hash_equals($_SESSION["csrf"] ?? "", $_POST["csrf"] ?? "")) {
        http_response_code(403);
        exit("Invalid CSRF");
    }
    $job   = preg_replace('/\D+/', '', (string)($_POST["job"] ?? ""));
    $token = (string)($_POST["token"] ?? "");
    if (!$job || !verifyToken($job, $token, $CFG["secret"])) { http_response_code(403); exit("Auth required"); }

    $jobDir = __DIR__ . "/loa/{$job}";
    if (!is_dir($jobDir)) {
        mkdir($jobDir, 0775, true);
    }

    $clientSignature = $_POST["client_signature"] ?? null;
    if (!is_string($clientSignature) || strpos($clientSignature, "data:image/png;base64,") !== 0) {
        http_response_code(400);
        exit("No signature");
    }

    // Load variables/body again
    $LOA_HTML = loadLoaHtml($job);
    $vars = parseFrontMatterForJob($job);

    // Save signature PNG
    $sigData = base64_decode(substr($clientSignature, strlen("data:image/png;base64,")));
    if ($sigData === false) { http_response_code(400); exit("Bad signature data"); }
    $sigPathRel = "loa/{$job}/{$job}_signature.png";
    $sigPathAbs = $jobDir . "/{$job}_signature.png";
    file_put_contents($sigPathAbs, $sigData);	

    // Build compiled signatures block
    $clientTz = $_POST["client_tz"] ?? "";
    if ($clientTz && in_array($clientTz, timezone_identifiers_list(), true)) {
        $tz = new DateTimeZone($clientTz);
        $clientDate = (new DateTime("now", $tz))->format("F j, Y \a\t g:i:s A T");
    } else {
        $clientDate = gmdate("F j, Y \a\t g:i:s A \G\M\T");
    }
    $clientIp = getClientIp();

    $CLIENT_SIGNATURE = '<strong>' . h(getByPath($vars, "client.name", "")) . '</strong>';
    $CLIENT_SIGNATURE .= '<div id="date-ip" class="date-ip">'
        . '<strong>Signed on:</strong> ' . h($clientDate) . '<br>'
        . '<strong>Client IP:</strong> ' . h($clientIp) . '</div>'
        . '<img id="sig" src="' . h($sigPathRel) . '" style="max-height: 117px;padding:10px;" alt="Client Signature">';

    $compiled = <<<HTML
    <div class="row compiled-signatures align-items-start">      
      <div class="col compiled-signature">{$CLIENT_SIGNATURE}</div>
    </div>
    <br>
    <div class="row download-pdf d-print-none">
      <a href="loa/{$job}/{$job}_signed_loa.pdf" download class="btn btn-light rounded-0" id="downloadpdf">Download PDF</a>
    </div>
HTML;

    // Build final HTML (web and pdf versions)
    $headerWeb  = headerWithTitle("{$job} - Signed Authorisation", $job, getByPath($vars, "dates.prepared", date("F j, Y")), "web");
    $footerWeb  = footerFor("web");
    $outputWeb  = $headerWeb . $LOA_HTML . $compiled . $footerWeb;

    $headerPdf  = headerWithTitle("{$job} - Signed Authorisation", $job, getByPath($vars, "dates.prepared", date("F j, Y")), "pdf");
    $footerPdf  = footerFor("pdf");
    $outputPdf  = $headerPdf . $LOA_HTML . $compiled . $footerPdf;

    // Render and save PDF
    $options = new \Dompdf\Options();
    $options->set('defaultFont', 'Helvetica');
    $options->set('isRemoteEnabled', true);

    $dompdf = new \Dompdf\Dompdf($options);
    $dompdf->loadHtml($outputPdf, "UTF-8");
    $dompdf->setPaper("A4", "portrait");
    $https  = !empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off";
    $scheme = $https ? "https" : "http";
    $host = $_SERVER["HTTP_HOST"] ?? "localhost";
    $dir  = rtrim(dirname($_SERVER["SCRIPT_NAME"] ?? ""), "/\\") . "/";
    $dompdf->setBasePath($scheme . "://" . $host . $dir);
    $dompdf->render();

    $pdfPathRel = "{$job}_signed_loa.pdf";
    $pdfPathAbs = __DIR__ . "/loa/{$job}/" . $pdfPathRel;
    $pdfPublicRel = "loa/{$job}/{$pdfPathRel}";
    file_put_contents($pdfPathAbs, $dompdf->output());

    // Email client + dev
    $clientEmail = (string)(getByPath($vars, "client.email", "") ?: "");
    $devEmail    = (string)($cfg["dev_email"] ?? "drafting@modulosdesign.com.au");
    $fromAddress = (string)($cfg["from_address"] ?? "drafting@modulosdesign.com.au");

    // --- Dorset council PDF + email (only if Dorset is the council) ---
    try {
        // Guard so we only do this for Dorset; set in your LOA front matter:
        // council:
        //   name: "Dorset Council"
        //   email: "development@dorset.tas.gov.au"
        $councilName  = (string) getByPath($vars, 'council.name', '');
        $councilEmail = (string) getByPath($vars, 'council.email', '');

        if ($councilEmail && stripos($councilEmail, 'tazz.com.au') !== false) { //dorset.tas.gov.au
            require_once __DIR__ . '/dorset_fill.php';

            $templatePath = __DIR__ . '/loa/dorset_consent_form.pdf';
            $dorsetOutAbs = __DIR__ . "/loa/{$job}/{$job}_dorset_consent_form.pdf";

            $dorsetPdf = generate_dorset_application($job, $vars, $cfg, $templatePath, $dorsetOutAbs);

            if ($dorsetPdf) {
    // Email Dorset + BCC dev
    $mailCouncil = new PHPMailer(true);

    // SMTP (optional but recommended if set in config)
    if (!empty($cfg['smtp_host'])) {
        $mailCouncil->isSMTP();
        $mailCouncil->Host       = $cfg['smtp_host'] ?? '';
        $mailCouncil->SMTPAuth   = true;
        $mailCouncil->Username   = $cfg['smtp_username'] ?? '';
        $mailCouncil->Password   = $cfg['smtp_password'] ?? '';
        $mailCouncil->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
        $mailCouncil->Port       = (int)($cfg['smtp_port'] ?? 465);
    }

    // From/Reply-To
    $fromAddress = (string)($cfg['from_address'] ?? 'drafting@modulosdesign.com.au');
    $mailCouncil->CharSet  = 'UTF-8';
    $mailCouncil->Encoding = 'base64';
    $mailCouncil->setFrom($fromAddress, $CFG['brand_name'] ?? 'Modulos Design');
    if (!empty($cfg['dev_email'])) $mailCouncil->addReplyTo($cfg['dev_email']);

    // ✅ REQUIRED: recipient(s)
    $mailCouncil->addAddress($councilEmail);
    if (!empty($CFG['bcc_email'])) $mailCouncil->addBCC($CFG['bcc_email']);

    // Build body using shared template
    $logoCouncil = email_logo_png_cid($mailCouncil, $cfg['dark_logo'] ?? "", $CFG['brand_name'] ?? 'Modulos Design', 200);
    $sigCouncil  = email_logo_png_cid($mailCouncil, $cfg['dev_signature'] ?? "", "Signature", 100);
    $loaUrl      = abs_url($pdfPublicRel);

    [$subject, $html, $alt] = buildCouncilRequestEmail(
        $logoCouncil,
        $job,
        $vars,
        $loaUrl,
        (string)($CFG['brand_name'] ?? 'Modulos Design'),
        $sigCouncil
    );

    $mailCouncil->isHTML(true);
    $mailCouncil->Subject = $subject;
    $mailCouncil->Body    = $html;
    $mailCouncil->AltBody = $alt;

    // Attach Dorset form + (optionally) the signed LOA
    if (is_file($dorsetPdf)) $mailCouncil->addAttachment($dorsetPdf, basename($dorsetPdf));
    if (is_file($pdfPathAbs)) $mailCouncil->addAttachment($pdfPathAbs, basename($pdfPathAbs));

    try {
        $mailCouncil->send();
    } catch (Throwable $e) {
        error_log("Council email failed for job {$job} to {$councilEmail}: ".$e->getMessage());
    }
}

        }
    } catch (Throwable $e) {
        error_log("Dorset generation error for job {$job}: ".$e->getMessage());
    }

    // Build the mailer once per recipient (same as contracts.php)
    $targets = [];
    if ($clientEmail) $targets[] = ["to" => $clientEmail, "kind" => "client"];
    if ($devEmail)    $targets[] = ["to" => $devEmail,    "kind" => "dev"];

    foreach ($targets as $t) {
        $mail = new PHPMailer(true);
        $mail->SMTPDebug = SMTP::DEBUG_OFF;
        if (!empty($cfg["smtp_host"])) {
            $mail->isSMTP();
            $mail->Host       = $cfg["smtp_host"] ?? "";
            $mail->SMTPAuth   = true;
            $mail->Username   = $cfg["smtp_username"] ?? "";
            $mail->Password   = $cfg["smtp_password"] ?? "";
            $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; // 465/SSL
            $mail->Port       = $cfg["smtp_port"] ?? 465;
        }

        $mail->CharSet  = "UTF-8";
        $mail->Encoding = "base64";
        $mail->setFrom($fromAddress, $CFG["brand_name"] ?? "Modulos Design");

        if ($t["kind"] === "client" && $devEmail)   $mail->addReplyTo($devEmail);
        if ($t["kind"] === "dev"    && $clientEmail)$mail->addReplyTo($clientEmail);

        $mail->addAddress($t["to"]);
        $mail->isHTML(true);

        // Embed assets per message
        $logoHtml      = email_logo_png_cid($mail, $cfg["dark_logo"] ?? "", $CFG["brand_name"] ?? "Modulos Design", 200);
        $safeSignature = email_logo_png_cid($mail, $cfg["dev_signature"] ?? "", "Signature", 100);

        [$subject, $html, $alt] = buildSignedLoaEmail(
            $logoHtml,
            abs_url($pdfPublicRel),    // <= FIX: public URL, not the filesystem path
            $job,
            (string)getByPath($vars, "client.name", ""),
            (string)getByPath($vars, "dates.prepared", date("F j, Y")),
            (string)($CFG["brand_name"] ?? "Modulos Design"),
            $safeSignature
        );

        // Developer copy extra info
        if ($t["kind"] === "dev") {
            $subject = $job . " – Authorisation has been signed";
            $signedBy = h($clientEmail ?: "unknown");
            $inject   = '<tr><td style="padding:4px 24px 0;font-size:14px;color:#444;">Signed by: ' . $signedBy . '</td></tr>';
            $html = preg_replace('/(<tr>\s*<td[^>]*>.*?<\/td>\s*<\/tr>)/s', '$1' . $inject, $html, 1)
                ?: str_replace('</tr><tr>', '</tr>' . $inject . '<tr>', $html);
            $alt .= "\n\nSigned by: " . ($clientEmail ?: "unknown");
        }

        $mail->Subject = $subject;
        $mail->Body    = $html;
        if (!empty($alt)) $mail->AltBody = $alt;

        if (!empty($CFG["bcc_email"])) $mail->addBCC($CFG["bcc_email"]);
        if (is_file($pdfPathAbs)) $mail->addAttachment($pdfPathAbs, basename($pdfPathAbs));

        try {
            $mail->send();
        } catch (MailerException $e) {
            error_log("LOA mailer error to {$t['to']}: {$mail->ErrorInfo}\n");
        }
    }

    // Public URL to the signed LOA (for the link in the email body)
    $loaUrl = abs_url($pdfPublicRel);

    // Council recipients
    $councilTo = council_recipients($vars, $cfg);
    foreach ($councilTo as $addr) {
        try {
            $mail = new PHPMailer(true);
            $mail->SMTPDebug = SMTP::DEBUG_OFF;
            if (!empty($cfg["smtp_host"])) {
                $mail->isSMTP();
                $mail->Host       = $cfg["smtp_host"] ?? "";
                $mail->SMTPAuth   = true;
                $mail->Username   = $cfg["smtp_username"] ?? "";
                $mail->Password   = $cfg["smtp_password"] ?? "";
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
                $mail->Port       = $cfg["smtp_port"] ?? 465;
            }

            $mail->CharSet  = "UTF-8";
            $mail->Encoding = "base64";
            $mail->setFrom($CFG["from_email"] ?? "drafting@modulosdesign.com.au", $CFG["brand_name"] ?? "Modulos Design");

            // Replies come back to you
            if (!empty($cfg["dev_email"])) $mail->addReplyTo($cfg["dev_email"]);

            $mail->addAddress($addr);
            $mail->isHTML(true);

            // Embed assets
            $logoHtml      = email_logo_png_cid($mail, $cfg["dark_logo"] ?? "", $CFG["brand_name"] ?? "Modulos Design", 200);
            $safeSignature = email_logo_png_cid($mail, $cfg["dev_signature"] ?? "", "Signature", 100);

            // Build council email
            [$subject, $html, $alt] = buildCouncilRequestEmail(
                $logoHtml,
                $job,
                $vars,
                $loaUrl,
                (string)($CFG["brand_name"] ?? "Modulos Design"),
                $safeSignature
            );

            $mail->Subject = $subject;
            $mail->Body    = $html;
            $mail->AltBody = $alt;

            if (!empty($CFG["bcc_email"])) $mail->addBCC($CFG["bcc_email"]);
            if (is_file($pdfPathAbs))      $mail->addAttachment($pdfPathAbs, basename($pdfPathAbs)); // attach signed LOA

            $mail->send();
        } catch (MailerException $e) {
            error_log("Council mailer error to {$addr}: {$mail->ErrorInfo}\n");
        }
    }

    // Redirect to signed HTML
    header("Location: " . $pdfPublicRel, true, 303);
    exit;
}