<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);

date_default_timezone_set("Australia/Hobart");

session_start();
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    // allow the public "mark_signed" webhook to skip CSRF (it uses a shared secret)
    $isMarkSigned = (($_POST['action'] ?? '') === 'mark_signed');
    if (!$isMarkSigned) {
        $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 = htmlspecialchars($_SESSION["csrf"] ?? "", ENT_QUOTES, "UTF-8");

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

// HTTP Basic Auth — must be configured in .env
$_au = $cfg['admin_user'] ?? '';
$_ap = $cfg['admin_pass'] ?? '';
if ($_au === '' || $_ap === '' ||
    !isset($_SERVER['PHP_AUTH_USER']) ||
    $_SERVER['PHP_AUTH_USER'] !== $_au ||
    ($_SERVER['PHP_AUTH_PW'] ?? '') !== $_ap) {
    header('WWW-Authenticate: Basic realm="Modulos Contracts Admin"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Authentication required.';
    exit;
}
unset($_au, $_ap);

// PHPMailer (same as contracts-admin)
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require_once "../internal/phpmailer/src/Exception.php";
require_once "../internal/phpmailer/src/PHPMailer.php";
require_once "../internal/phpmailer/src/SMTP.php";

// tiny JSON responder
function json_response(array $payload, int $code = 200): void {
    http_response_code($code);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    exit;
}


// Where to store correspondence PDFs (filesystem) and how to serve them (URL)
if (!defined('CORR_UPLOAD_DIR')) define('CORR_UPLOAD_DIR', __DIR__ . '/uploads');
if (!defined('CORR_UPLOAD_URL')) define('CORR_UPLOAD_URL', '/contracts/uploads');
if (!is_dir(CORR_UPLOAD_DIR)) @mkdir(CORR_UPLOAD_DIR, 0775, true);

// Where your .md contracts live (adjust if different)
if (!defined('PROGRESS_BASE_URL')) {
    define('PROGRESS_BASE_URL', 'https://modulosdesign.com.au/contracts');
}
if (!defined('CONTRACTS_DIR')) {
    $contractsDir = realpath(__DIR__ . '/contracts');
    if ($contractsDir === false) {
        // fallback if the folder doesn't exist or path differs
        $contractsDir = __DIR__ . '/../contracts';
    }
    define('CONTRACTS_DIR', $contractsDir);
}

$dsn = 'mysql:host=' . $cfg['db_host'] . ';dbname=' . $cfg['db_name'] . ';charset=utf8mb4';
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];

try {
    $pdo = new PDO($dsn, $cfg['db_username'], $cfg['db_password'], $options);
} catch (PDOException $e) {
    exit('Database connection failed: ' . $e->getMessage());
}

$app_id_raw = $_GET['id'] ?? '';
$app_id = preg_match('/^\d+$/', $app_id_raw) ? $app_id_raw : '0';

// Load existing stages for this application
$rows = $pdo->prepare("SELECT * FROM application_stages WHERE application_id = ? ORDER BY position ASC, id ASC");
$rows->execute([$app_id]);
$existing = [];
foreach ($rows as $r) {
    $pos = is_null($r['position']) ? null : (int)$r['position'];
    if ($pos !== null) $existing[$pos] = $r;
}

$stmt = $pdo->prepare("SELECT * FROM applications WHERE id = ?");
$stmt->execute([$app_id]);
$app = $stmt->fetch();

if (!$app) {
    http_response_code(404);
    exit("Application not found.");
}

// Pick the id that matches your contracts/{clientid}.md filename.
$prefer = (string)($app['client_id'] ?? $app['clientid'] ?? $app_id);
$prefer = preg_replace('/[^A-Za-z0-9_-]/', '', $prefer);

$candidates = array_unique(array_filter([
    $prefer,
    preg_replace('/[^A-Za-z0-9_-]/', '', (string)($app['reference'] ?? '')),
]));

$progressUrl = '';
$progressErr = '';
$usedClientId = null;

$clientEmail = trim((string)($app['client_email'] ?? ''));
if (!filter_var($clientEmail, FILTER_VALIDATE_EMAIL)) { $clientEmail = ''; }

foreach ($candidates as $cid) {
    if ($cid === '') continue;
    $md = contract_path($cid);
    if (is_file($md)) {
        $usedClientId = $cid;

        $clientEmail = '';
        if ($usedClientId) {
            $meta = extract_front_matter_fields(contract_path($cid));
            if (!empty($meta['client_email']) && filter_var($meta['client_email'], FILTER_VALIDATE_EMAIL)) {
                $clientEmail = trim($meta['client_email']);
            }
        }
        if (!$clientEmail) {
            $clientEmail = trim((string)($app['client_email'] ?? ''));
        }
        if (!filter_var($clientEmail, FILTER_VALIDATE_EMAIL)) {
            $clientEmail = '';
        }

        try {
            $progressUrl = progress_public_url($cid, $app_id);
        } catch (Throwable $e) {
            $progressErr = $e->getMessage();
        }
        break;
    }
}

if (!$progressUrl && !$progressErr) {
    $tried = [];
    foreach ($candidates as $cid) { $tried[] = contract_path($cid); }
    $progressErr = "Contract file not found. Tried: " . implode(' | ', $tried);
}

// Predefine default stages (can be adjusted per application later)
$defaultStages = [
    'Submission to Council',
    'Council Acknowledgement',
    'Fees Paid',
    'Confirmed Valid (42 Days Start)',
    'Public Advertisement Start',
    'Public Advertisement End',
    'Council Decision Due'
];

// --- Create correspondence entry ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'add_correspondence') {
    $tz = new DateTimeZone('Australia/Hobart');

    $typeAllow      = ['incoming','outgoing','note'];
    $channelAllow   = ['email','phone','meeting','other'];
    $visibilityAllow= ['client','internal'];

    $type       = in_array($_POST['type'] ?? 'note', $typeAllow, true) ? $_POST['type'] : 'note';
    $channel    = in_array($_POST['channel'] ?? 'other', $channelAllow, true) ? $_POST['channel'] : 'other';
    $visibility = in_array($_POST['visibility'] ?? 'client', $visibilityAllow, true) ? $_POST['visibility'] : 'client';
    $subject    = trim($_POST['subject'] ?? '') ?: null;
    $author     = trim($_POST['author'] ?? '') ?: null;
    $pin        = isset($_POST['pin']) ? 1 : 0;

    $bodyRaw    = trim($_POST['body'] ?? '');
    if ($bodyRaw === '') { $bodyRaw = '(no content)'; }

    // event_at: prefer user input, else "now"
    $eventAtRaw = trim($_POST['event_at'] ?? '');
    try {
        $eventAt = $eventAtRaw ? new DateTime($eventAtRaw, $tz) : new DateTime('now', $tz);
    } catch (Exception $e) {
        $eventAt = new DateTime('now', $tz);
    }

    $stmt = $pdo->prepare("
        INSERT INTO application_correspondence
        (application_id, event_at, type, channel, subject, body, author, visibility, pin)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");
    $stmt->execute([
        $app_id,
        $eventAt->format('Y-m-d H:i:s'),
        $type,
        $channel,
        $subject,
        $bodyRaw,
        $author,
        $visibility,
        $pin
    ]);

    $corrId = (int)$pdo->lastInsertId();

    if (!empty($_FILES['attachments']) && is_array($_FILES['attachments']['name'])) {
        $finfo   = new finfo(FILEINFO_MIME_TYPE);
        $allowed = ['application/pdf' => 'pdf'];
        $baseDir = rtrim(CORR_UPLOAD_DIR, '/\\') . DIRECTORY_SEPARATOR . $app_id . DIRECTORY_SEPARATOR . $corrId;
        if (!is_dir($baseDir)) @mkdir($baseDir, 0775, true);

        $ins = $pdo->prepare("
        INSERT INTO application_correspondence_files
        (application_id, correspondence_id, original_name, file_url, file_path, mime, size)
        VALUES (?, ?, ?, ?, ?, ?, ?)
    ");

        $names = $_FILES['attachments']['name'];
        $tmps  = $_FILES['attachments']['tmp_name'];
        $errs  = $_FILES['attachments']['error'];
        $sizes = $_FILES['attachments']['size'];

        for ($i = 0; $i < count($names); $i++) {
            if ($errs[$i] !== UPLOAD_ERR_OK || $tmps[$i] === '') continue;

            $mime = $finfo->file($tmps[$i]) ?: '';
            if (!isset($allowed[$mime])) continue; // only PDFs

            // Safe filename
            $orig = preg_replace('/[^\w\.\- ]+/', '_', (string)$names[$i]);
            $slug = substr(sha1($orig . microtime(true)), 0, 10) . '.pdf';
            $dest = $baseDir . DIRECTORY_SEPARATOR . $slug;

            if (move_uploaded_file($tmps[$i], $dest)) {
                $url = rtrim(CORR_UPLOAD_URL, '/')
                    . '/' . rawurlencode((string)$app_id)
                    . '/' . rawurlencode((string)$corrId)
                    . '/' . rawurlencode($slug);

                $ins->execute([
                    $app_id, $corrId, $orig, $url, $dest, $mime, (int)$sizes[$i]
                ]);
            }
        }
    }
    // (keep the attachments block as-is above)

    $shouldNotify = !empty($_POST['notify_client']) && ($visibility === 'client');

    error_log("notify? ".($shouldNotify?'yes':'no')." to='$clientEmail' url='$progressUrl'");
    if ($shouldNotify) {
        /* $prefer = (string)($app['client_id'] ?? $app['clientid'] ?? $app_id);
        $prefer = preg_replace('/[^A-Za-z0-9_-]/', '', $prefer);
        $candidates = array_unique(array_filter([$prefer, preg_replace('/[^A-Za-z0-9_-]/', '', (string)($app['reference'] ?? ''))]));
        $clientid = null;
        foreach ($candidates as $cid) { if ($cid && is_file(contract_path($cid))) { $clientid = $cid; break; } }
        $progressUrl = $clientid ? progress_public_url($clientid, $app_id) : ''; */

        $to = $clientEmail;
        if ($progressUrl && filter_var($to, FILTER_VALIDATE_EMAIL)) {
            $corrIdForMail = $corrId; // we just inserted it
            $qr = $pdo->prepare("SELECT original_name, file_url FROM application_correspondence_files WHERE correspondence_id = ? ORDER BY id ASC");
            $qr->execute([$corrIdForMail]);
            $attRows = $qr->fetchAll(PDO::FETCH_ASSOC) ?: [];
            $atts = array_map(fn($a)=>['name'=>$a['original_name'], 'url'=>$a['file_url']], $attRows);

            $ok = send_progress_update_email(
                $to,
                $progressUrl,
                ($app['reference'] ?: $app_id),
                $cfg,
                [
                    'when'        => dt_human($eventAt->format('Y-m-d H:i:s')),
                    'type'        => $type,
                    'channel'     => $channel,
                    'subject'     => $subject ?: ucfirst($type),
                    'author'      => $author ?: '',
                    'body'        => $bodyRaw,
                    'attachments' => $atts,
                ]
            );
            // optional debug
            if (!$ok) error_log("update_correspondence: send_progress_update_email returned false (to=$to)");
        } else {
            // optional debug
            error_log("update_correspondence: not sending (to='$to', url='$progressUrl')");
        }
    }

    // Redirect to avoid resubmission and jump to the timeline section
    header("Location: ".$_SERVER['REQUEST_URI']."#correspondence");
    exit;
}
// --- Update correspondence entry ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'update_correspondence') {
    $id = (int)($_POST['id'] ?? 0);
    if ($id > 0) {
        $tz = new DateTimeZone('Australia/Hobart');

        $typeAllow      = ['incoming','outgoing','note'];
        $channelAllow   = ['email','phone','meeting','other'];
        $visibilityAllow= ['client','internal'];

        $type       = in_array($_POST['type'] ?? 'note', $typeAllow, true) ? $_POST['type'] : 'note';
        $channel    = in_array($_POST['channel'] ?? 'other', $channelAllow, true) ? $_POST['channel'] : 'other';
        $visibility = in_array($_POST['visibility'] ?? 'client', $visibilityAllow, true) ? $_POST['visibility'] : 'client';

        $subject    = trim($_POST['subject'] ?? '') ?: null;
        $author     = trim($_POST['author'] ?? '') ?: null;
        $pin        = isset($_POST['pin']) ? 1 : 0;
        $bodyRaw    = trim($_POST['body'] ?? '') ?: '(no content)';

        $eventAtRaw = trim($_POST['event_at'] ?? '');
        try { $eventAt = $eventAtRaw ? new DateTime($eventAtRaw, $tz) : new DateTime('now', $tz); }
        catch (Exception $e) { $eventAt = new DateTime('now', $tz); }

        $stmt = $pdo->prepare("
            UPDATE application_correspondence
               SET event_at=?, type=?, channel=?, subject=?, body=?, author=?, visibility=?, pin=?, updated_at=NOW()
             WHERE id=? AND application_id=?
        ");
        $stmt->execute([
            $eventAt->format('Y-m-d H:i:s'),
            $type, $channel, $subject, $bodyRaw, $author, $visibility, $pin,
            $id, $app_id
        ]);

        // accept newly added PDFs on edit as well
        if (!empty($_FILES['attachments']) && is_array($_FILES['attachments']['name'])) {
            $corrId = $id; // we're editing this row
            $finfo   = new finfo(FILEINFO_MIME_TYPE);
            $allowed = ['application/pdf' => 'pdf'];
            $baseDir = rtrim(CORR_UPLOAD_DIR, '/\\') . DIRECTORY_SEPARATOR . $app_id . DIRECTORY_SEPARATOR . $corrId;
            if (!is_dir($baseDir)) @mkdir($baseDir, 0775, true);

            $ins = $pdo->prepare("
        INSERT INTO application_correspondence_files
        (application_id, correspondence_id, original_name, file_url, file_path, mime, size)
        VALUES (?, ?, ?, ?, ?, ?, ?)
    ");

            $names = $_FILES['attachments']['name'];
            $tmps  = $_FILES['attachments']['tmp_name'];
            $errs  = $_FILES['attachments']['error'];
            $sizes = $_FILES['attachments']['size'];

            for ($i = 0; $i < count($names); $i++) {
                if ($errs[$i] !== UPLOAD_ERR_OK || $tmps[$i] === '') continue;

                $mime = $finfo->file($tmps[$i]) ?: '';
                if (!isset($allowed[$mime])) continue; // PDF only

                $orig = preg_replace('/[^\w\.\- ]+/', '_', (string)$names[$i]);
                $slug = substr(sha1($orig . microtime(true)), 0, 10) . '.pdf';
                $dest = $baseDir . DIRECTORY_SEPARATOR . $slug;

                if (move_uploaded_file($tmps[$i], $dest)) {
                    $url = rtrim(CORR_UPLOAD_URL, '/')
                        . '/' . rawurlencode((string)$app_id)
                        . '/' . rawurlencode((string)$corrId)
                        . '/' . rawurlencode($slug);

                    $ins->execute([$app_id, $corrId, $orig, $url, $dest, $mime, (int)$sizes[$i]]);
                }
            }
        }

        // (keep the attachments block as-is above)
        $shouldNotify = !empty($_POST['notify_client']) && ($visibility === 'client');

        if ($shouldNotify) {
            $prefer = (string)($app['client_id'] ?? $app['clientid'] ?? $app_id);
            $prefer = preg_replace('/[^A-Za-z0-9_-]/', '', $prefer);
            $candidates = array_unique(array_filter([$prefer, preg_replace('/[^A-Za-z0-9_-]/', '', (string)($app['reference'] ?? ''))]));
            $clientid = null;
            foreach ($candidates as $cid) { if ($cid && is_file(contract_path($cid))) { $clientid = $cid; break; } }
            $progressUrl = $clientid ? progress_public_url($clientid, $app_id) : '';

            $to = $clientEmail;
            if ($progressUrl && filter_var($to, FILTER_VALIDATE_EMAIL)) {
                $corrIdForMail = $id; // we're editing this one
                $qr = $pdo->prepare("SELECT original_name, file_url FROM application_correspondence_files WHERE correspondence_id = ? ORDER BY id ASC");
                $qr->execute([$corrIdForMail]);
                $attRows = $qr->fetchAll(PDO::FETCH_ASSOC) ?: [];
                $atts = array_map(fn($a)=>['name'=>$a['original_name'], 'url'=>$a['file_url']], $attRows);

                send_progress_update_email(
                    $to,
                    $progressUrl,
                    ($app['reference'] ?: $app_id),
                    $cfg,
                    [
                        'when'        => dt_human($eventAt->format('Y-m-d H:i:s')),
                        'type'        => $type,
                        'channel'     => $channel,
                        'subject'     => $subject ?: ucfirst($type),
                        'author'      => $author ?: '',
                        'body'        => $bodyRaw,
                        'attachments' => $atts,
                    ]
                );
            }
        }
    }

    header("Location: ".$_SERVER['REQUEST_URI']."#correspondence");
    exit;
}

// ---- AJAX: send progress link ----
if (($_GET['action'] ?? $_POST['action'] ?? '') === 'send_progress_link') {
    // CSRF already validated at top

    $email = trim($_POST['email'] ?? '');
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        json_response(['ok' => false, 'error' => 'Invalid email'], 400);
    }

    // Build or reuse the progress URL
    $prefer = (string)($app['client_id'] ?? $app['clientid'] ?? $app_id);
    $prefer = preg_replace('/[^A-Za-z0-9_-]/', '', $prefer);

    $candidates = array_unique(array_filter([
        $prefer,
        preg_replace('/[^A-Za-z0-9_-]/', '', (string)($app['reference'] ?? '')),
    ]));

    $clientid = null;
    foreach ($candidates as $cid) {
        if ($cid && is_file(contract_path($cid))) { $clientid = $cid; break; }
    }
    if (!$clientid) {
        $pathsTried = implode(' | ', array_map(fn($c)=>contract_path($c), $candidates));
        json_response(['ok' => false, 'error' => "Contract file not found. Tried: {$pathsTried}"], 404);
    }

    try {
        $url = progress_public_url($clientid, $app_id);
    } catch (Throwable $e) {
        json_response(['ok' => false, 'error' => $e->getMessage()], 500);
    }

    $jobRefOrId = $app['reference'] ?: $app_id;
    $sent = send_progress_email($email, $url, $jobRefOrId, $cfg);

    if ($sent) {
        json_response(['ok' => true, 'url' => $url]);
    } else {
        json_response(['ok' => false, 'error' => 'Failed to send email'], 500);
    }
}


// Helpers
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
function excerpt($s, $n=180){
    $s = trim(preg_replace('/\s+/', ' ', (string)$s));
    return mb_strlen($s) > $n ? mb_substr($s,0,$n-1).'…' : $s;
}
function dt_local($mysql, $tz='Australia/Hobart'){
    if (!$mysql) return '';
    $d = new DateTime($mysql, new DateTimeZone($tz));
    return $d->format('Y-m-d\TH:i');
}
function dt_human($mysql, $tz='Australia/Hobart'){
    if (!$mysql) return '';
    $d = new DateTime($mysql, new DateTimeZone($tz));
    return $d->format('D d M Y, h:ia');
}

// Build contracts/{clientid}.md path
function contract_path(string $clientid): string {
    $id = preg_replace('/[^A-Za-z0-9_-]/', '', $clientid);
    return rtrim(CONTRACTS_DIR, '/\\') . DIRECTORY_SEPARATOR . $id . '.md';
}

// Tiny front-matter puller (same idea as contracts-admin)
function extract_front_matter_fields(string $file): array {
    $out = [];
    $txt = @file_get_contents($file);
    if (!$txt) return $out;
    if (!preg_match('/^---\s*\R(.*?)\R---/s', $txt, $m)) return $out;
    $fm = $m[1];

    // admin.secret inside an admin: block, or a flat admin_secret
    if (preg_match('/^\s*admin\s*:\s*$(.*?)^(?=\S)/ms', $fm."\nX", $block)) {
        $adminBlock = $block[1];
        if (preg_match('/^\s*secret\s*:\s*["\']?([^"\']+)["\']?/mi', $adminBlock, $mm)) {
            $out['admin_secret'] = trim($mm[1]);
        }
    }
    if (empty($out['admin_secret']) && preg_match('/^\s*admin_secret\s*:\s*["\']?([^"\']+)["\']?/mi', $fm, $mm)) {
        $out['admin_secret'] = trim($mm[1]);
    }

    // client.email inside a client: block, or flat client_email / email
    if (preg_match('/^\s*client\s*:\s*$(.*?)^(?=\S)/ms', $fm."\nX", $block)) {
        $clientBlock = $block[1];
        if (preg_match('/^\s*email\s*:\s*["\']?([^"\']+)["\']?/mi', $clientBlock, $mm)) {
            $out['client_email'] = trim($mm[1]);
        }
    }
    if (empty($out['client_email'])) {
        if (preg_match('/^\s*client_email\s*:\s*["\']?([^"\']+)["\']?/mi', $fm, $mm)) {
            $out['client_email'] = trim($mm[1]);
        } elseif (preg_match('/^\s*email\s*:\s*["\']?([^"\']+)["\']?/mi', $fm, $mm)) {
            $out['client_email'] = trim($mm[1]);
        }
    }

    return $out;
}

// Build the signed public progress URL (namespaced HMAC)
function progress_public_url(string $clientid, $appId): string {
    $meta   = extract_front_matter_fields(contract_path($clientid));
    $secret = $meta['admin_secret'] ?? '';
    if ($secret === '') {
        throw new RuntimeException("Missing admin secret for client ID: {$clientid}");
    }
    $token = hash_hmac('sha256', 'progress|' . (string)$appId, $secret);
    $base  = rtrim(PROGRESS_BASE_URL, '/');
    return $base . '/progress.php?id=' . rawurlencode((string)$appId)
        . '&clientid=' . rawurlencode($clientid)
        . '&token=' . rawurlencode($token);
}


foreach ($candidates as $cid) {
    if ($cid === '') continue;
    $md = contract_path($cid);
    if (is_file($md)) {
        $usedClientId = $cid;

        $clientEmail = '';
        if ($usedClientId) {
            $meta = extract_front_matter_fields(contract_path($cid));
            if (!empty($meta['client_email']) && filter_var($meta['client_email'], FILTER_VALIDATE_EMAIL)) {
                $clientEmail = trim($meta['client_email']);
            }
        }
        if (!$clientEmail) {
            $clientEmail = trim((string)($app['client_email'] ?? ''));
        }
        if (!filter_var($clientEmail, FILTER_VALIDATE_EMAIL)) {
            $clientEmail = '';
        }

        try {
            $progressUrl = progress_public_url($cid, $app_id);
        } catch (Throwable $e) {
            $progressErr = $e->getMessage();
        }
        break;
    }
}

if (!$progressUrl && !$progressErr) {
    // Nothing matched; explain what we tried
    $tried = [];
    foreach ($candidates as $cid) { $tried[] = contract_path($cid); }
    $progressErr = "Contract file not found. Tried: " . implode(' | ', $tried);
}


$rows = $pdo->prepare("
  SELECT id, event_at, type, channel, subject, body, author, visibility, pin, created_at
    FROM application_correspondence
   WHERE application_id = ?
ORDER BY pin DESC, event_at DESC, id DESC
   LIMIT 30
");
$rows->execute([$app_id]);
$correspondence = $rows->fetchAll(PDO::FETCH_ASSOC);

// -------------------------------------------- EMAIL HELPERS -----------------------------------------
// embed a PNG data URL as CID (same helper you already have)
function email_logo_png_cid(PHPMailer $mail, string $dataUrl, string $alt = 'Modulos Design', int $width = 200): string {
    if ($dataUrl === '') return '';
    $prefix = 'data:image/png;base64,';
    if (stripos($dataUrl, $prefix) !== 0) return '';
    $bin = base64_decode(substr($dataUrl, strlen($prefix)), true);
    if ($bin === false) return '';
    $cid = 'logo_' . substr(sha1($bin), 0, 12) . '@modulos';
    $mail->addStringEmbeddedImage($bin, $cid, 'logo.png', 'base64', 'image/png');
    return '<img src="cid:' . $cid . '" alt="' . htmlspecialchars($alt, ENT_QUOTES, 'UTF-8') . '" width="' . (int)$width . '" style="display:block;border:0;outline:0;text-decoration:none;height:auto;">';
}

// email HTML body — same structure as contracts-admin but wording for “Progress”
function build_progress_email_html_template(string $logoHtml, string $safeJob, string $firstNameSafe, string $safeUrl, string $safeCompany, string $safeSignature): string {
    return <<<HTML
<div style="display:none;max-height:0;overflow:hidden;opacity:0;mso-hide:all;font-size:0;line-height:0;">
  Your application progress.
</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" bgcolor="#FFFFFF" style="width:600px;max-width:100%;background-color:#FFFFFF;border-radius:8px;overflow:hidden; font-size:14px;line-height:1.6;font-family:Arial,Helvetica,sans-serif;background-image:linear-gradient(#FFFFFF,#FFFFFF);">
    <tr>
      <td bgcolor="#D9CCC1" style="padding:20px 24px;background-color:#D9CCC1;color:#ffffff;">
        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
          <tr>
            <td>{$logoHtml}</td>
            <td align="right" style="font-weight:700;">Council Application #{$safeJob}</td>
          </tr>
        </table>
      </td>
    </tr>

    <tr>
      <td bgcolor="#f8f9fa"
          style="padding:28px 24px 8px;color:#635A4A;background-color:#f8f9fa;background-image:linear-gradient(#f8f9fa,#f8f9fa);">
        <div>Hello {$firstNameSafe},</div>
      </td>
    </tr>

    <tr>
      <td align="center" bgcolor="#f8f9fa" style="padding:20px 24px 8px;background-color:#f8f9fa;background-image:linear-gradient(#f8f9fa,#f8f9fa);">
        <!--[if mso]>
        <v:rect xmlns:v="urn:schemas-microsoft-com:vml" href="{$safeUrl}" style="height:42px;v-text-anchor:middle;width:260px;" stroked="f" fillcolor="#635A4A">
          <w:anchorlock/>
          <center style="color:#ffffff;font-family:Arial,sans-serif;font-size:16px;">View Progress</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;" target="_blank" rel="noopener">View Progress</a>
        <!--<![endif]-->
      </td>
    </tr>

    <tr>
      <td bgcolor="#f8f9fa" style="padding:8px 24px 24px;color:#635A4A;background-color:#f8f9fa;background-image:linear-gradient(#f8f9fa,#f8f9fa);">
        <div style="margin-top:18px;">
          Thank you.<br><br>
          <b>Kind Regards,</b><br><br>{$safeSignature}<br>Benjamin Harris<br>{$safeCompany}<br>0402 984 082 &nbsp;|&nbsp; drafting@modulosdesign.com.au
        </div>
      </td>
    </tr>

    <tr>
      <td bgcolor="#28261E" style="padding:12px 24px;background-color:#28261E;color:#D9CCC1;">
        This is an automated message. Please reply to this email if you have any questions.
      </td>
    </tr>
  </table>
</div>
HTML;
}


// send mail (PHPMailer, same SMTP pattern as contracts-admin)
function send_progress_email(string $email, string $progressUrl, string $jobRefOrId, array $cfg): bool {
    $mail = new PHPMailer(true);

    $safeCompany = htmlspecialchars($cfg['company_name'] ?? 'Modulos Design', ENT_QUOTES, 'UTF-8');
    $safeUrl     = htmlspecialchars($progressUrl, ENT_QUOTES, 'UTF-8');
    $safeJob     = htmlspecialchars((string)$jobRefOrId, ENT_QUOTES, 'UTF-8');

    $firstName = 'there';
    if (!empty($cfg['client_name'])) {
        $firstName = htmlspecialchars($cfg['client_name'], ENT_QUOTES, 'UTF-8');
    }

    $logoHtml     = email_logo_png_cid($mail, $cfg['dark_logo'] ?? '', $safeCompany, 200);
    $signatureImg = email_logo_png_cid($mail, $cfg['dev_signature'] ?? '', $safeCompany, 100);

    $html = build_progress_email_html_template($logoHtml, $safeJob, $firstName, $safeUrl, $safeCompany, $signatureImg);
    $alt  = "Hello {$firstName},\n\nYour application progress page is ready:\n{$progressUrl}\n\nKind Regards,\n{$safeCompany}";

    // <- set these BEFORE the try so the fallback can use them
    $fromAddress = $cfg['smtp_from']      ?? 'no-reply@modulosdesign.com.au';
    $fromName    = $cfg['smtp_from_name'] ?? 'Modulos Design';

    try {
        $mail->CharSet  = 'UTF-8';
        $mail->Encoding = 'base64';

        $smtpHost = $cfg['smtp_host'] ?? '';
        if ($smtpHost !== '') {
            $mail->isSMTP();
            $mail->SMTPDebug = SMTP::DEBUG_OFF;
            $mail->Host       = $smtpHost;
            $mail->SMTPAuth   = true;
            $mail->Username   = $cfg['smtp_username'] ?? '';
            $mail->Password   = $cfg['smtp_password'] ?? '';
            $secure = strtolower((string)($cfg['smtp_secure'] ?? 'ssl'));
            if ($secure === 'ssl') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
                $mail->Port       = (int)($cfg['smtp_port'] ?? 465);
            } else {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
                $mail->Port       = (int)($cfg['smtp_port'] ?? 587);
            }
        }

        $mail->setFrom($fromAddress, $fromName);
        if (!empty($cfg['smtp_reply_to'])) $mail->addReplyTo($cfg['smtp_reply_to']);
        $mail->addAddress($email);

        if (!empty($cfg['smtp_bcc'])) {
            foreach (explode(',', $cfg['smtp_bcc']) as $bcc) {
                $bcc = trim($bcc);
                if ($bcc !== '') $mail->addBCC($bcc);
            }
        }
        $mail->addBCC('drafting@modulosdesign.com.au');

        $mail->isHTML(true);
        $mail->Subject = "Your Application Progress Dashboard";
        $mail->Body    = $html;
        $mail->AltBody = $alt;

        $mail->send();
        return true;
    } catch (Throwable $e) {
        error_log("send_progress_email failed for {$email}: ".$e->getMessage());
        // Fallback to PHP mail()
        $headers  = "MIME-Version: 1.0\r\n";
        $headers .= "Content-type: text/html; charset=UTF-8\r\n";
        $headers .= "From: {$fromName} <{$fromAddress}>\r\n";
        return mail($email, "Your Application Progress Page", $html, $headers);
    }
}

function send_progress_update_email(
    string $email,
    string $progressUrl,
    string $jobRefOrId,
    array $cfg,
    array $update // ['when'=>..., 'type'=>..., 'channel'=>..., 'subject'=>..., 'author'=>..., 'body'=>..., 'attachments'=>[['name'=>..., 'url'=>...], ...]]
): bool {
    $mail = new PHPMailer(true);

    $safeCompany = htmlspecialchars($cfg['company_name'] ?? 'Modulos Design', ENT_QUOTES, 'UTF-8');
    $safeUrl     = htmlspecialchars($progressUrl, ENT_QUOTES, 'UTF-8');
    $safeJob     = htmlspecialchars((string)$jobRefOrId, ENT_QUOTES, 'UTF-8');

    $firstName = htmlspecialchars($cfg['client_name'] ?? 'there', ENT_QUOTES, 'UTF-8');

    $logoHtml     = email_logo_png_cid($mail, $cfg['dark_logo'] ?? '', $safeCompany, 200);
    $signatureImg = email_logo_png_cid($mail, $cfg['dev_signature'] ?? '', $safeCompany, 100);

    $when   = htmlspecialchars($update['when'] ?? '', ENT_QUOTES, 'UTF-8');
    $subj   = htmlspecialchars($update['subject'] ?? ucfirst($update['type'] ?? 'Update'), ENT_QUOTES, 'UTF-8');
    $author = htmlspecialchars($update['author'] ?? '', ENT_QUOTES, 'UTF-8');
    $body   = nl2br(htmlspecialchars(mb_strimwidth((string)($update['body'] ?? ''), 0, 600, '…'), ENT_QUOTES, 'UTF-8'));

    // attachments list (as links)
    $attHtml = '';
    if (!empty($update['attachments'])) {
        $attHtml .= '<ul style="margin:8px 0 0 16px;padding:0;">';
        foreach ($update['attachments'] as $a) {
            $attHtml .= '<li><a href="https://modulosdesign.com.au' . htmlspecialchars($a['url'], ENT_QUOTES, 'UTF-8') . '" target="_blank" rel="noopener">'
                . htmlspecialchars($a['name'], ENT_QUOTES, 'UTF-8')
                . '</a></li>';
        }
        $attHtml .= '</ul>';
    }

    $html = build_progress_email_html_template(
        $logoHtml,
        $safeJob,
        $firstName,
        $safeUrl,
        $safeCompany,
        $signatureImg
    );

    // inject an “update” block right above the CTA (cheap & cheerful; keeps your template)
    $updateBlock =
        '<tr><td bgcolor="#f8f9fa" style="padding:14px 24px;color:#635A4A;">'
        . '<div style="font-weight:700;margin-bottom:6px;">New update posted</div>'
        . '<div><b>When:</b> ' . $when . '</div>'
        . '<div><b>Subject:</b> ' . $subj . '</div>'
        . ($author ? '<div><b>Author:</b> ' . $author . '</div>' : '')
        . '<div style="margin-top:10px;border-left:3px solid #D9CCC1;padding-left:10px;">' . $body . '</div>'
        . ($attHtml ? '<div style="margin-top:10px;"><b>Attachments:</b>' . $attHtml . '</div>' : '')
        . '</td></tr>';

    $html = str_replace(
        '<tr>'."\n".'      <td align="center"',
        $updateBlock . "\n".'<tr>'."\n".'      <td align="center"',
        $html
    );

    $alt = "New update on your application #{$jobRefOrId}\n"
        . ($when ? "When: {$when}\n" : '')
        . "Subject: {$subj}\n\n"
        . strip_tags((string)$update['body']) . "\n\n"
        . "View your progress: {$progressUrl}";

    $fromAddress = $cfg['smtp_from']      ?? 'no-reply@modulosdesign.com.au';
    $fromName    = $cfg['smtp_from_name'] ?? 'Modulos Design';

    try {
        $mail->CharSet  = 'UTF-8';
        $mail->Encoding = 'base64';

        if (!empty($cfg['smtp_host'])) {
            $mail->isSMTP();
            $mail->SMTPDebug = SMTP::DEBUG_OFF;
            $mail->Host       = $cfg['smtp_host'];
            $mail->SMTPAuth   = true;
            $mail->Username   = $cfg['smtp_username'] ?? '';
            $mail->Password   = $cfg['smtp_password'] ?? '';
            $secure = strtolower((string)($cfg['smtp_secure'] ?? 'ssl'));
            if ($secure === 'ssl') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
                $mail->Port       = (int)($cfg['smtp_port'] ?? 465);
            } else {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
                $mail->Port       = (int)($cfg['smtp_port'] ?? 587);
            }
        }

        $mail->setFrom($fromAddress, $fromName);
        if (!empty($cfg['smtp_reply_to'])) $mail->addReplyTo($cfg['smtp_reply_to']);
        $mail->addAddress($email);
        if (!empty($cfg['smtp_bcc'])) {
            foreach (explode(',', $cfg['smtp_bcc']) as $bcc) {
                $bcc = trim($bcc); if ($bcc !== '') $mail->addBCC($bcc);
            }
        }
        $mail->addBCC('drafting@modulosdesign.com.au');

        $mail->isHTML(true);
        $mail->Subject = "Update posted – Application #{$jobRefOrId}";
        $mail->Body    = $html;
        $mail->AltBody = $alt;

        $mail->send();
        return true;
    } catch (Throwable $e) {
        error_log("send_progress_update_email failed: ".$e->getMessage());
        return false;
    }
}


// Load attachments for the visible correspondence list
$attByCorr = [];
if (!empty($correspondence)) {
    $ids = array_column($correspondence, 'id');
    $ph  = implode(',', array_fill(0, count($ids), '?'));
    $qr  = $pdo->prepare("
        SELECT id, correspondence_id, original_name, file_url
        FROM application_correspondence_files
        WHERE correspondence_id IN ($ph)
        ORDER BY id ASC
    ");
    $qr->execute($ids);
    foreach ($qr->fetchAll(PDO::FETCH_ASSOC) as $a) {
        $attByCorr[(int)$a['correspondence_id']][] = $a;
    }
}


?>
<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Edit Timeline – <?= htmlspecialchars($app['reference']) ?></title>

        <link rel="shortcut icon" href="../internal/images/blueprint.ico" type="image/x-icon">

        <meta name="robots" content="noindex">
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-LN+7fdVzj6u52u30Kp6M/trliBMCMKTyK833zpbD+pXdCLuTusPj697FH4R/5mcr" crossorigin="anonymous">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.bundle.min.js" integrity="sha384-ndDqU0Gzau9qJ1lfW4pNLlhNTkCfHzAVBReH9diLvGRem5+R9g2FzA8ZGN954O5Q" crossorigin="anonymous"></script>
        <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">
        <style>
            .card-sm .card-body { padding: .75rem .9rem; }
            .card-sm .bi { font-size: 1rem; }
            .dropzone-sm {
                border: 1px dashed #bbb;
                background: #fafafa;
                border-radius: .25rem;
                padding: .5rem .75rem;
                font-size: .875rem;
                cursor: pointer;
                user-select: none;
            }
            .dropzone-sm.dragover { background: #f1f1f1; border-color: #666; }
            .dz-list > div { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

        </style>
    </head>

    <body class="bg-light">
        <nav class="navbar bg-brown-dark brown-light border-bottom border-body d-print-none">
            <div class="container-fluid">
                <span class="navbar-brand brown-light">
                    <img src="../internal/images/blueprint-logo-light.png" alt="Logo" width="30" height="24" class="d-inline-block align-text-top">
                    Modulos Design
                </span>
                <div class="ms-auto d-flex gap-2">
                    <a href="../internal/dashboard.php" class="btn btn-sm btn-outline-light"><i class="bi bi-grid-fill"></i> Dashboard</a>
                    <a href="../internal/client-brief.php?drg=<?= $app_id ?>" class="btn btn-sm btn-outline-light"><i class="bi bi-person-fill"></i> Client Brief</a>
                    <a href="admin_dashboard.php" class="btn btn-sm btn-outline-light"><i class="bi bi-list-ul"></i> All Applications</a>
                </div>
            </div>
        </nav>
        <div class="container my-5">
            <h2>Edit Timeline for Job: <?= htmlspecialchars($app['reference']) ?></h2>
            <form method="POST" action="save_stages.php" enctype="multipart/form-data">
                <input type="hidden" name="application_id" value="<?= $app_id ?>">
                <div class="mb-3 row">
                    <label class="col-sm-3 col-form-label">Submission Date</label>
                    <div class="col-sm-4">
                        <input type="date" class="form-control form-control-sm rounded-0" name="submission_date" id="submission_date" value="<?= htmlspecialchars($app['submission_date'] ?? '') ?>">
                    </div>
                </div>
                <div class="mb-3 row">
                    <label class="col-sm-3 col-form-label">Planning Required By</label>
                    <div class="col-sm-4">
                        <input type="date" class="form-control form-control-sm rounded-0" name="required_by" id="required_by" value="<?= htmlspecialchars($app['required_by'] ?? '') ?>">
                    </div>
                </div>
            	<div class="mb-3 row">
  					<label class="col-sm-3 col-form-label">Statutory clock</label>
  					<div class="col-sm-9 d-flex align-items-center gap-3">
    					<div class="form-check">
      						<input class="form-check-input rounded-0" type="checkbox" id="clock_paused" name="clock_paused" value="1"
             				<?= !empty($app['clock_paused']) ? 'checked' : '' ?>>
      						<label class="form-check-label" for="clock_paused">Pause clock (RFI)</label>
    					</div>
    					<input type="text" class="form-control form-control-sm rounded-0" style="max-width:420px" name="clock_pause_reason" placeholder="Reason, e.g. Council RFI received" value="<?= htmlspecialchars($app['clock_pause_reason'] ?? '') ?>">
  					</div>
				</div>
                <hr>
                <h5>Milestones</h5>
                <div class="table-responsive">
                    <table class="table table-sm table-bordered align-middle">
                        <thead>
                            <tr>
                                <th>#</th>
                                <th>Stage Name</th>
                                <th>Status</th>
                                <th>Date</th>
                                <th>Notes</th>
                                <th>PDF</th>
                            </tr>
                        </thead>
                        <tbody id="stagesBody">
                            <?php
    $rowsOut = [];
            // Materialize existing rows in order
            ksort($existing);
            $pos = 0;
            foreach ($existing as $i => $row) {
                $rowsOut[] = [
                    'id'      => $row['id'] ?? '',
                    'pos'     => $pos++,
                    'title'   => $row['title'] ?? ('Stage ' . ($i+1)),
                    'status'  => $row['status'] ?? 'pending',
                    'date'    => $row['stage_date'] ?? '',
                    'notes'   => $row['description'] ?? '',
                    'pdf'     => $row['pdf_path'] ?? '',
                ];
            }
            // Pad with defaults if needed
            for ($i = count($rowsOut); $i < max(count($rowsOut), count($defaultStages)); $i++) {
                $rowsOut[] = [
                    'id' => '',
                    'pos' => $i,
                    'title' => $defaultStages[$i] ?? ('Stage ' . ($i+1)),
                    'status' => 'pending',
                    'date' => '',
                    'notes' => '',
                    'pdf' => '',
                ];
            }

            // Render
            foreach ($rowsOut as $r):
                            ?>
                            <tr data-row="<?= (int)$r['pos'] ?>">
                                <td><?= (int)($r['pos']+1) ?></td>
                                <td>
                                    <input type="hidden" name="stages[<?= (int)$r['pos'] ?>][id]" value="<?= h($r['id']) ?>">
                                    <input type="hidden" name="stages[<?= (int)$r['pos'] ?>][position]" value="<?= (int)$r['pos'] ?>">
                                    <input type="text" class="form-control form-control-sm rounded-0" name="stages[<?= (int)$r['pos'] ?>][title]" value="<?= h($r['title']) ?>">
                                </td>
                                <td>
                                    <select name="stages[<?= (int)$r['pos'] ?>][status]" class="form-select form-select-sm rounded-0">
                                        <option value="pending"  <?= $r['status']==='pending'  ? 'selected' : '' ?>>Pending</option>
                                        <option value="current"  <?= $r['status']==='current'  ? 'selected' : '' ?>>Current</option>
                                        <option value="complete" <?= $r['status']==='complete' ? 'selected' : '' ?>>Complete</option>
                                        <option value="paused"   <?= $r['status']==='paused'   ? 'selected' : '' ?>>Paused (RFI)</option>
                                    </select>
                                </td>
                                <td>
                                    <input
                                           type="date"
                                           id="stage_date_<?= (int)$r['pos'] ?>"
                                           name="stages[<?= (int)$r['pos'] ?>][date]"
                                           class="form-control form-control-sm rounded-0"
                                           value="<?= h($r['date']) ?>"
                                           >
                                </td>
                                <td><textarea name="stages[<?= (int)$r['pos'] ?>][notes]" class="form-control form-control-sm rounded-0" rows="1"><?= h($r['notes']) ?></textarea></td>
                                <td class="small">
                                    <?php if ($r['pdf']): ?>
                                    <a href="<?= h($r['pdf']) ?>" target="_blank" class="d-block mb-1">Current PDF</a>
                                    <label class="form-check"><input class="form-check-input rounded-0" type="checkbox" name="stages[<?= (int)$r['pos'] ?>][remove_pdf]" value="1"><span class="form-check-label">Remove</span></label>
                                    <?php endif; ?>
                                    <input type="file" name="stages[<?= (int)$r['pos'] ?>][pdf]" class="form-control form-control-sm rounded-0">
                                </td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>

                </div>
                <button type="button" class="btn btn-sm btn-outline-primary rounded-0" id="btnAddStage"><i class="bi bi-plus-lg"></i> Add stage</button>
                <button type="submit" class="btn btn-sm btn-outline-secondary rounded-0">Save Timeline</button>
                <a href="admin_dashboard.php" class="btn btn-sm btn-secondary rounded-0">Back</a>
            </form>

            <div class="row mt-2">
                <div class="col-6">
                    <div class="d-flex gap-2">
                        <button type="button" class="btn btn-sm btn-outline-primary rounded-0" id="btnPrefill">Prefill (don’t overwrite)</button>
                        <button type="button" class="btn btn-sm btn-outline-danger rounded-0" id="btnPrefillOverwrite">Recalculate (overwrite)</button>
                    </div>
                </div>
                <div class="col-6">
                    <div class="text-end">
                        <?php if ($progressUrl): ?>
                        <button class="btn rounded-0 btn-sm btn-outline-dark" type="button" onclick="navigator.clipboard.writeText('<?= htmlspecialchars($progressUrl, ENT_QUOTES) ?>')">
                            Copy progress link
                        </button>
                        <a class="btn rounded-0 btn-sm btn-outline-secondary" href="<?= htmlspecialchars($progressUrl) ?>" target="_blank" rel="noopener">
                            Open progress
                        </a>
                        <button class="btn rounded-0 btn-sm bg-brown-three brown-five" type="button" data-bs-toggle="modal" data-bs-target="#sendProgressModal">
                            Email link
                        </button>
                        <?php else: ?>
                        <button class="btn rounded-0 btn-sm btn-outline-dark" type="button" disabled>Copy progress link</button>
                        <button class="btn rounded-0 btn-sm btn-outline-secondary" type="button" disabled>Open progress</button>
                        <button class="btn rounded-0 btn-sm bg-brown-three brown-five" type="button" disabled>Email link</button>
                        <?php if ($progressErr): ?>
                        <div class="small text-danger mt-1"><?= htmlspecialchars($progressErr) ?></div>
                        <?php endif; ?>
                        <?php endif; ?>
                    </div>
                </div>
            </div>

            <hr class="my-4">
            <div id="correspondence" class="row">
                <div class="col-12 col-xl-5 mb-4">
                    <div class="card border-0 shadow-sm">
                        <div class="card-header bg-white">
                            <strong>Add correspondence / note</strong>
                        </div>
                        <div class="card-body">
                            <form method="post" class="row g-3" enctype="multipart/form-data">
                                <input type="hidden" name="csrf" value="<?= $csrf ?>">
                                <input type="hidden" name="action" value="add_correspondence">

                                <div class="col-6">
                                    <label class="form-label">When</label>
                                    <input type="datetime-local" name="event_at" class="form-control form-control-sm"
                                           value="<?= htmlspecialchars((new DateTime('now', new DateTimeZone('Australia/Hobart')))->format('Y-m-d\TH:i')) ?>">
                                </div>
                                <div class="col-6">
                                    <label class="form-label">Visibility</label>
                                    <select name="visibility" class="form-select form-select-sm">
                                        <option value="client">Client-visible</option>
                                        <option value="internal">Internal</option>
                                    </select>
                                </div>

                                <div class="col-4">
                                    <label class="form-label">Type</label>
                                    <select name="type" class="form-select form-select-sm">
                                        <option value="incoming">Incoming</option>
                                        <option value="outgoing">Outgoing</option>
                                        <option value="note" selected>Note</option>
                                    </select>
                                </div>
                                <div class="col-4">
                                    <label class="form-label">Channel</label>
                                    <select name="channel" class="form-select form-select-sm">
                                        <option value="email">Email</option>
                                        <option value="phone">Phone</option>
                                        <option value="meeting">Meeting</option>
                                        <option value="other" selected>Other</option>
                                    </select>
                                </div>
                                <div class="col-4 d-flex align-items-end">
                                    <div class="form-check">
                                        <input class="form-check-input" type="checkbox" name="pin" id="pin">
                                        <label class="form-check-label" for="pin">Pin to top</label>
                                    </div>
                                </div>

                                <div class="col-6">
                                    <label class="form-label">Subject</label>
                                    <input type="text" name="subject" id="corrSubject" class="form-control form-control-sm" placeholder="Optional">
                                </div>
                                <div class="col-6">
                                    <label class="form-label">Author</label>
                                    <input type="text" name="author" id="corrAuthor" class="form-control form-control-sm" placeholder="e.g. Council Officer">
                                </div>

                                <div class="col-12">
                                    <label class="form-label">Paste email / note</label>
                                    <textarea name="body" id="corrBody" rows="6" class="form-control form-control-sm" placeholder="Paste email text here..."></textarea>
                                    <div class="form-text">
                                        Tip: click <a href="#" id="tryParse">Try auto-parse</a> to fill Subject/When from headers (Subject:, Date:, From:).
                                    </div>
                                </div>

                                <div class="col-12">
                                    <label class="form-label">Attach PDF(s)</label>
                                    <div id="corrDropZone" class="dropzone-sm">
                                        <input id="corrFiles" type="file" name="attachments[]" accept="application/pdf" multiple hidden>
                                        <div class="dz-instructions">
                                            Drag & drop PDF here, or <u>click to browse</u>.
                                        </div>
                                        <div id="corrFileList" class="dz-list small text-muted"></div>
                                    </div>
                                    <div class="form-text">PDF only.</div>
                                </div>

                                <div class="col-12">
                                    <div class="form-check">
                                        <input class="form-check-input" type="checkbox" name="notify_client" id="notify_client" value="1">
                                        <label class="form-check-label" for="notify_client">
                                            Email client
                                        </label>
                                    </div>
                                    <div class="form-text">
                                        Sent if Client-visible
                                        <?= $clientEmail ? ' – <b>'.h($clientEmail).'</b>.' : '' ?>
                                    </div>
                                </div>

                                <div class="col-12 text-end">
                                    <button type="submit" class="btn btn-sm btn-secondary rounded-0">Save</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
                <div class="col-12 col-xl-7">
                    <div class="d-flex justify-content-between align-items-center mb-2">
                        <h5 class="mb-0">Recent correspondence</h5>
                        <span class="text-muted small"><?= count($correspondence) ?> shown</span>
                    </div>

                    <div class="row row-cols-1 gy-2">
                        <?php if (empty($correspondence)): ?>
                        <div class="text-muted">No correspondence yet.</div>
                        <?php else:
                        // icon maps (define once)
                        $badgeMap = [
                            'email_incoming' => 'bi-envelope-arrow-up',
                            'email_outgoing' => 'bi-send-check',
                            'phone_incoming' => 'bi-telephone-inbound',
                            'phone_outgoing' => 'bi-telephone-outbound',
                            'note'           => 'bi-journal-text',
                        ];
                        $fallbackByChannel = [
                            'email'   => 'bi-envelope',
                            'phone'   => 'bi-telephone',
                            'meeting' => 'bi-people',
                            'other'   => 'bi-chat-dots',
                        ];

                        foreach ($correspondence as $c):
                        // per-row values
                        $typeVal    = strtolower(trim($c['type'] ?? 'note'));        // incoming|outgoing|note
                        $channelVal = strtolower(trim($c['channel'] ?? 'other'));    // email|phone|meeting|other
                        $key        = ($typeVal === 'note') ? 'note' : "{$channelVal}_{$typeVal}";
                        $icon       = $badgeMap[$key] ?? ($fallbackByChannel[$channelVal] ?? 'bi-journal-text');

                        $badge = $c['visibility']==='internal' ? '<span class="badge text-bg-secondary ms-2">Internal</span>' : '';
                        $pin   = $c['pin'] ? '<i class="bi bi-pin-angle-fill text-warning ms-1" title="Pinned"></i>' : '';
                        ?>
                        <div class="col">
                            <div class="card card-sm shadow-sm border-0">
                                <div class="card-body p-3">
                                    <div class="d-flex justify-content-between">
                                        <div class="d-flex align-items-center gap-2">
                                            <i class="bi <?= $icon ?> text-muted"></i>
                                            <strong><?= h($c['subject'] ?: ucfirst($c['type'])) ?></strong>
                                            <?= $badge ?> <?= $pin ?>
                                        </div>
                                        <small class="text-muted"><?= dt_human($c['event_at']) ?></small>
                                    </div>
                                    <div class="small text-muted mt-1"><?= h(excerpt($c['body'])) ?></div>
                                    <div class="d-flex gap-2 mt-2">
                                        <button
                                                class="btn btn-sm btn-outline-secondary rounded-0"
                                                data-bs-toggle="modal" data-bs-target="#editCorrModal"
                                                data-id="<?= (int)$c['id'] ?>"
                                                data-event="<?= h(dt_local($c['event_at'])) ?>"
                                                data-type="<?= h($c['type']) ?>"
                                                data-channel="<?= h($c['channel']) ?>"
                                                data-subject="<?= h($c['subject']) ?>"
                                                data-author="<?= h($c['author']) ?>"
                                                data-visibility="<?= h($c['visibility']) ?>"
                                                data-pin="<?= (int)$c['pin'] ?>"
                                                data-body="<?= h($c['body']) ?>"
                                                >Edit</button>
                                    </div>
                                    <?php
    $cid = (int)$c['id'];
                                               if (!empty($attByCorr[$cid])):
                                    ?>
                                    <div class="mt-2">
                                        <?php foreach ($attByCorr[$cid] as $a): ?>
                                        <a class="btn btn-sm btn-outline-secondary rounded-0 me-1"
                                           href="<?= h($a['file_url']) ?>" target="_blank" rel="noopener">
                                            <i class="bi bi-file-earmark-pdf"></i> <?= h($a['original_name']) ?>
                                        </a>
                                        <?php endforeach; ?>
                                    </div>
                                    <?php endif; ?>
                                </div>
                            </div>
                        </div>
                        <?php endforeach; endif; ?>
                    </div>

                </div>
            </div>
        </div>
        <div class="modal fade" id="editCorrModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog modal-lg modal-dialog-scrollable">
                <form method="post" class="modal-content" enctype="multipart/form-data">
                    <input type="hidden" name="csrf" value="<?= $csrf ?>">
                    <input type="hidden" name="action" value="update_correspondence">
                    <input type="hidden" name="id" id="ec_id">

                    <div class="modal-header">
                        <h5 class="modal-title">Edit correspondence</h5>
                        <button type="button" class="btn btn-sm btn-close rounded-0" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>

                    <div class="modal-body">
                        <div class="row g-3">
                            <div class="col-6">
                                <label class="form-label">When</label>
                                <input type="datetime-local" class="form-control form-control-sm rounded-0" name="event_at" id="ec_event">
                            </div>
                            <div class="col-6">
                                <label class="form-label">Visibility</label>
                                <select name="visibility" id="ec_visibility" class="form-select form-select-sm rounded-0">
                                    <option value="client">Client-visible</option>
                                    <option value="internal">Internal</option>
                                </select>
                            </div>

                            <div class="col-4">
                                <label class="form-label">Type</label>
                                <select name="type" id="ec_type" class="form-select form-select-sm rounded-0">
                                    <option value="incoming">Incoming</option>
                                    <option value="outgoing">Outgoing</option>
                                    <option value="note">Note</option>
                                </select>
                            </div>
                            <div class="col-4">
                                <label class="form-label">Channel</label>
                                <select name="channel" id="ec_channel" class="form-select form-select-sm rounded-0">
                                    <option value="email">Email</option>
                                    <option value="phone">Phone</option>
                                    <option value="meeting">Meeting</option>
                                    <option value="other">Other</option>
                                </select>
                            </div>
                            <div class="col-4 d-flex align-items-end">
                                <div class="form-check">
                                    <input class="form-check-input rounded-0" type="checkbox" name="pin" id="ec_pin">
                                    <label class="form-check-label" for="ec_pin">Pin to top</label>
                                </div>

                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="notify_client" id="ec_notify_client" value="1">
                                    <label class="form-check-label" for="ec_notify_client">Email client</label>
                                    <div class="form-text">
                                        Sent if Client-visible
                                        <?= $clientEmail ? ' – <b>'.h($clientEmail).'</b>.' : '' ?>
                                    </div>
                                </div>
                            </div>

                            <div class="col-6">
                                <label class="form-label">Subject</label>
                                <input type="text" name="subject" id="ec_subject" class="form-control form-control-sm rounded-0">
                            </div>
                            <div class="col-6">
                                <label class="form-label">Author</label>
                                <input type="text" name="author" id="ec_author" class="form-control form-control-sm rounded-0">
                            </div>

                            <div class="col-12">
                                <label class="form-label">Body</label>
                                <textarea name="body" id="ec_body" rows="8" class="form-control form-control-sm rounded-0"></textarea>
                            </div>

                            <div class="col-12">
                                <label class="form-label">Attach PDF(s)</label>
                                <div id="ec_corrDropZone" class="dropzone-sm">
                                    <input id="ec_corrFiles" type="file" name="attachments[]" accept="application/pdf" multiple hidden>
                                    <div class="dz-instructions">Drag & drop PDF here, or <u>click to browse</u>.</div>
                                    <div id="ec_corrFileList" class="dz-list small text-muted"></div>
                                </div>
                                <div class="form-text">PDF only.</div>
                            </div>
                        </div>
                    </div>

                    <div class="modal-footer">
                        <button type="button" class="btn btn-sm btn-light rounded-0" data-bs-dismiss="modal">Cancel</button>
                        <button type="submit" class="btn btn-sm btn-primary rounded-0">Save changes</button>
                    </div>
                </form>
            </div>
        </div>

        <!-- Send Progress Modal -->
        <div class="modal fade" id="sendProgressModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">Email Progress Link</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="mb-3">
                            <label class="form-label">Send to email</label>
                            <input id="progressEmail" type="email" class="form-control" placeholder="client@example.com" value="<?= htmlspecialchars($clientEmail) ?>">
                        </div>
                        <div class="alert alert-secondary">
                            The email includes a link to this application’s public progress page.
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn rounded-0 btn-sm bg-brown-five brown-three" data-bs-dismiss="modal">Close</button>
                        <button type="button" class="btn rounded-0 btn-sm bg-brown-three brown-five" id="confirmSendProgressBtn">Send</button>
                    </div>
                </div>
            </div>
        </div>
        <script>
            window.CSRF = "<?= $csrf ?>";
            const editModal = document.getElementById('editCorrModal');
            editModal?.addEventListener('show.bs.modal', function (ev) {
            const btn = ev.relatedTarget;
            const get = (k) => btn.getAttribute('data-' + k) || '';

            document.getElementById('ec_id').value        = get('id');
            document.getElementById('ec_event').value     = get('event');
            document.getElementById('ec_subject').value   = get('subject');
            document.getElementById('ec_author').value    = get('author');
            document.getElementById('ec_body').value      = get('body');

            document.getElementById('ec_type').value      = get('type') || 'note';
            document.getElementById('ec_channel').value   = get('channel') || 'other';
            document.getElementById('ec_visibility').value= get('visibility') || 'client';
            document.getElementById('ec_pin').checked     = get('pin') === '1';
            });

            (function(){
            const STG = {
            SUBMIT: 0,
                ACK: 1,
                    FEES: 2,
                        VALID: 3,
                            AD_START: 4,
                                AD_END: 5,
                                    DECISION: 6
            };

            const subEl = document.getElementById('submission_date');
            const reqEl = document.getElementById('required_by');

            function parseDate(str){ return str ? new Date(str + 'T00:00:00') : null; }
            function fmt(d){ if(!d) return ''; const m=('0'+(d.getMonth()+1)).slice(-2); const day=('0'+d.getDate()).slice(-2); return `${d.getFullYear()}-${m}-${day}`; }
            function addDays(d, n){ const x = new Date(d); x.setDate(x.getDate()+n); return x; }
            function setStageDate(idx, dateStr, overwrite){
                const el = document.getElementById('stage_date_'+idx);
                if(!el) return;
                if(!overwrite && el.value) return; // keep manual value
                el.value = dateStr || '';
            }

            function prefill(overwrite=false){
                const sub = parseDate(subEl.value);
                const req = parseDate(reqEl.value);

                let submission = sub;
                let decision = req;

                // If only required_by is set, back-calc submission
                if (!submission && decision) submission = addDays(decision, -42);
                // If only submission is set, forward-calc decision
                if (submission && !decision) decision = addDays(submission, 42);

                // Guard: nothing to do
                if (!submission && !decision) return;

                // Intermediates – simple defaults (editable by you)
                // You can adjust these offsets anytime; they’re just sensible pre-fills.
                const ack       = submission ? addDays(submission, 2) : null;
                const fees      = submission ? addDays(submission, 3) : null;
                const valid     = submission ? addDays(submission, 5) : null; // when the 42-day clock typically starts
                const adStart   = valid     ? addDays(valid, 1)       : (submission ? addDays(submission, 6) : null);
                const adEnd     = adStart   ? addDays(adStart, 14)    : null;

                setStageDate(STG.SUBMIT,   fmt(submission), overwrite);
                setStageDate(STG.ACK,      fmt(ack),        overwrite);
                setStageDate(STG.FEES,     fmt(fees),       overwrite);
                setStageDate(STG.VALID,    fmt(valid),      overwrite);
                setStageDate(STG.AD_START, fmt(adStart),    overwrite);
                setStageDate(STG.AD_END,   fmt(adEnd),      overwrite);
                setStageDate(STG.DECISION, fmt(decision),   overwrite);
            }

            // Auto-prefill (non-destructive) when either anchor date changes
            subEl?.addEventListener('change', ()=>prefill(false));
            reqEl?.addEventListener('change', ()=>prefill(false));

            // Buttons
            document.getElementById('btnPrefill')?.addEventListener('click', ()=>prefill(false));
            document.getElementById('btnPrefillOverwrite')?.addEventListener('click', ()=>prefill(true));

            // First load: try a gentle prefill
            prefill(false);
            })();
            document.getElementById('confirmSendProgressBtn')?.addEventListener('click', async () => {
            const email = (document.getElementById('progressEmail')?.value || '').trim();
            if (!email) { alert('Please enter an email'); return; }
            const fd = new FormData();
            fd.append('action', 'send_progress_link');
            fd.append('email', email);
            fd.append('csrf', window.CSRF || '');
            const res = await fetch('?id=<?= (int)$app_id ?>', { method: 'POST', body: fd });
            let js = {};
            try { js = await res.json(); }
            catch(e) {
                const txt = await res.text();
                alert('Server error:\n' + txt); // temporary debugging aid
                return;
            }
            if (js.ok) {
                bootstrap.Modal.getInstance(document.getElementById('sendProgressModal'))?.hide();
                //alert('Email sent.');
            } else {
                alert(js.error || 'Failed to send!');
            }
            });

                (function(){
                const dz = document.getElementById('corrDropZone');
                const fi = document.getElementById('corrFiles');
                const list = document.getElementById('corrFileList');
                if (!dz || !fi || !list) return;

                function refreshList(files) {
                list.innerHTML = '';
                if (!files || !files.length) return;
                for (const f of files) {
                const ok = (f.type === 'application/pdf') || /\.pdf$/i.test(f.name);
                const row = document.createElement('div');
                row.textContent = (ok ? '📄 ' : '⚠️ ') + f.name;
                list.appendChild(row);
            }
            }

            dz.addEventListener('click', () => fi.click());
            dz.addEventListener('dragover', (e) => { e.preventDefault(); dz.classList.add('dragover'); });
            dz.addEventListener('dragleave', () => dz.classList.remove('dragover'));
            dz.addEventListener('drop', (e) => {
                e.preventDefault(); dz.classList.remove('dragover');
                const files = [...(e.dataTransfer?.files || [])].filter(f =>
                                   f && ((f.type === 'application/pdf') || /\.pdf$/i.test(f.name))
                                  );
                                   const dt = new DataTransfer();
                                   for (const f of files) dt.items.add(f);
                                   fi.files = dt.files;
                                   refreshList(fi.files);
                                   });
                                   fi.addEventListener('change', () => refreshList(fi.files));
                                   })();


                                   function wireDropzone(zoneId, inputId, listId) {
                                   const dz = document.getElementById(zoneId);
                                   const fi = document.getElementById(inputId);
                                   const list = document.getElementById(listId);
                                   if (!dz || !fi || !list) return;

                                   const refreshList = (files) => {
                                   list.innerHTML = '';
                                   if (!files || !files.length) return;
                                   for (const f of files) {
                                   const ok = (f.type === 'application/pdf') || /\.pdf$/i.test(f.name);
                                   const row = document.createElement('div');
                                   row.textContent = (ok ? '📄 ' : '⚠️ ') + f.name;
                               list.appendChild(row);
                               }
                               };

                               dz.addEventListener('click', () => fi.click());
                               dz.addEventListener('dragover', (e) => { e.preventDefault(); dz.classList.add('dragover'); });
                               dz.addEventListener('dragleave', () => dz.classList.remove('dragover'));
                               dz.addEventListener('drop', (e) => {
                               e.preventDefault(); dz.classList.remove('dragover');
                               const files = [...(e.dataTransfer?.files || [])].filter(f =>
                                                                                       f && ((f.type === 'application/pdf') || /\.pdf$/i.test(f.name))
                                                                                      );
                const dt = new DataTransfer();
                for (const f of files) dt.items.add(f);
                fi.files = dt.files;
                refreshList(fi.files);
            });
            fi.addEventListener('change', () => refreshList(fi.files));
            }

            // add form
            wireDropzone('corrDropZone','corrFiles','corrFileList');
            // edit modal
            wireDropzone('ec_corrDropZone','ec_corrFiles','ec_corrFileList');

            document.getElementById('tryParse')?.addEventListener('click', function(e){
            e.preventDefault();
            const body = document.getElementById('corrBody')?.value || '';
            const subj = /(?:^|\n)Subject:\s*(.+)/i.exec(body);
            const from = /(?:^|\n)From:\s*(.+)/i.exec(body);
            const date = /(?:^|\n)Date:\s*(.+)/i.exec(body);

            if (subj) document.getElementById('corrSubject').value = subj[1].trim();
            if (from) document.getElementById('corrAuthor').value  = from[1].trim();

            if (date) {
            const guess = new Date(date[1]);
            if (!isNaN(guess.getTime())) {
            const pad = n => String(n).padStart(2,'0');
            const v = guess.getFullYear() + '-' + pad(guess.getMonth()+1) + '-' + pad(guess.getDate())
                + 'T' + pad(guess.getHours()) + ':' + pad(guess.getMinutes());
            document.querySelector('input[name="event_at"]').value = v;
            }
            }
            });

            const visAdd = document.querySelector('select[name="visibility"]');
            const chkAdd = document.getElementById('notify_client');
            function syncNotifyDisabled(sel, chk){
            if (!sel || !chk) return;
            const internal = sel.value === 'internal';
            chk.disabled = internal;
            if (internal) chk.checked = false;
            }
            visAdd?.addEventListener('change', ()=>syncNotifyDisabled(visAdd, chkAdd));
            syncNotifyDisabled(visAdd, chkAdd);

            const visEdit = document.getElementById('ec_visibility');
            const chkEdit = document.getElementById('ec_notify_client');
            visEdit?.addEventListener('change', ()=>syncNotifyDisabled(visEdit, chkEdit));
            editModal?.addEventListener('show.bs.modal', ()=>syncNotifyDisabled(visEdit, chkEdit));
        </script>
        <script type="text/template" id="stageRowTemplate">
<tr data-row="__INDEX__">
  <td>__HUMAN__</td>
  <td>
    <input type="hidden" name="stages[__INDEX__][id]" value="">
    <input type="hidden" name="stages[__INDEX__][position]" value="__INDEX__">
    <input type="text" class="form-control form-control-sm rounded-0" name="stages[__INDEX__][title]" value="Stage __HUMAN__">
            </td>
  <td>
    <select name="stages[__INDEX__][status]" class="form-select form-select-sm rounded-0">
      <option value="pending">Pending</option>
      <option value="current">Current</option>
      <option value="complete">Complete</option>
      <option value="paused">Paused (RFI)</option>
            </select>
            </td>
  <td><input type="date" id="stage_date___INDEX__" name="stages[__INDEX__][date]" class="form-control form-control-sm rounded-0"></td>
  <td><textarea name="stages[__INDEX__][notes]" class="form-control form-control-sm rounded-0" rows="1"></textarea></td>
  <td class="small"><input type="file" name="stages[__INDEX__][pdf]" class="form-control form-control-sm rounded-0"></td>
            </tr>
        </script>

        <script>
            document.getElementById('btnAddStage')?.addEventListener('click', () => {
            const tbody = document.getElementById('stagesBody');
            const tpl = document.getElementById('stageRowTemplate').textContent;
            const nextIndex = [...tbody.querySelectorAll('tr')].length;
            const html = tpl
                .replaceAll('__INDEX__', nextIndex)
                .replaceAll('__HUMAN__', nextIndex + 1);
            const temp = document.createElement('tbody');
            temp.innerHTML = html.trim();
            tbody.appendChild(temp.firstElementChild);
            });
        </script>

    </body>
</html>