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

date_default_timezone_set("Australia/Hobart");

// Adjust path if your contracts live elsewhere.
if (!defined('CONTRACTS_DIR')) {
    define('CONTRACTS_DIR', realpath(__DIR__ . '/contracts'));
}

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

/** Very small front-matter puller; same idea as contracts admin */
function extract_front_matter_fields_progress(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 or 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]);
    }
    return $out;
}

/** Build the exact token we expect for the public progress page */
function progress_expected_token(string $clientid, $appId): ?string {
    $path = contract_path_for_client($clientid);
    $fm   = extract_front_matter_fields_progress($path);
    $secret = $fm['admin_secret'] ?? '';
    if ($secret === '') return null;
    return hash_hmac('sha256', 'progress|' . (string)$appId, $secret);
}


$cfg = require __DIR__ . '/config.php';

$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) {
    error_log('Database connection failed: ' . $e->getMessage());
    http_response_code(500);
    exit('Service unavailable');
}

$app_id_raw = $_GET['id'] ?? '';
$token      = $_GET['token'] ?? '';

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

// Verify token (optional: match your token logic)
$stmt = $pdo->prepare("SELECT client_email, reference, created_at, submission_date, required_by FROM applications WHERE id = ?");
$stmt->execute([$app_id]);
$app = $stmt->fetch(PDO::FETCH_ASSOC);

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

// Fetch stages
$stmt = $pdo->prepare("SELECT * FROM application_stages WHERE application_id = ? ORDER BY position ASC");
$stmt->execute([$app_id]);
$stages = $stmt->fetchAll(PDO::FETCH_ASSOC);

$totalStages = 7;
$currentStage = count(array_filter($stages, function ($s) {
    return strtolower(trim($s['status'] ?? '')) === 'complete';
}));
$progress = round(($currentStage / $totalStages) * 100);

$decisionDate = null;

// 1) Look for an explicit 'Council Decision Due' stage date
$decisionStage = null;
foreach ($stages as $s) {
    if (stripos($s['title'] ?? '', 'decision') !== false && !empty($s['stage_date'])) {
        $decisionStage = $s;
        break;
    }
}

if ($decisionStage) {
    $decisionDate = new DateTime($decisionStage['stage_date'], new DateTimeZone('Australia/Hobart'));
} elseif (!empty($app['required_by'])) {
    $decisionDate = new DateTime($app['required_by'], new DateTimeZone('Australia/Hobart'));
} elseif (!empty($app['submission_date'])) {
    $decisionDate = (new DateTime($app['submission_date'], new DateTimeZone('Australia/Hobart')))->modify('+42 days');
}

// set a friendly “end of business day” time so the countdown isn’t midnight-awkward
if ($decisionDate) { $decisionDate->setTime(17, 0, 0); }
$decisionIso = $decisionDate ? $decisionDate->format('c') : '';

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

    $typeAllow      = ['incoming','outgoing','note'];
    $channelAllow   = ['email','phone','portal','letter','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
    ]);

    // Redirect to avoid resubmission and jump to the timeline section
    header("Location: ".$_SERVER['REQUEST_URI']."#correspondence");
    exit;
}

// Fetch timeline (newest first; pinned first)
$stmt = $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 200
");
$stmt->execute([$app_id]);
$correspondence = $stmt->fetchAll(PDO::FETCH_ASSOC);

/* NEW: attachment counts (and optional details) */
$fileCounts = [];
$filesByCorr = []; // if you also want to list the files

if (!empty($correspondence)) {
    $ids = array_column($correspondence, 'id');
    $ph  = implode(',', array_fill(0, count($ids), '?'));

    // Count files per correspondence
    $qc = $pdo->prepare("
        SELECT correspondence_id, COUNT(*) AS n
        FROM application_correspondence_files
        WHERE correspondence_id IN ($ph)
        GROUP BY correspondence_id
    ");
    $qc->execute($ids);
    foreach ($qc->fetchAll(PDO::FETCH_ASSOC) as $r) {
        $fileCounts[(int)$r['correspondence_id']] = (int)$r['n'];
    }

    // OPTIONAL: load file details if you want links
    $qd = $pdo->prepare("
        SELECT correspondence_id, original_name, file_url
        FROM application_correspondence_files
        WHERE correspondence_id IN ($ph)
        ORDER BY id ASC
    ");
    $qd->execute($ids);
    foreach ($qd->fetchAll(PDO::FETCH_ASSOC) as $f) {
        $cid = (int)$f['correspondence_id'];
        if (!isset($filesByCorr[$cid])) $filesByCorr[$cid] = [];
        $filesByCorr[$cid][] = $f;
    }
}


// ------------------ HELPERS ------------------
function render_body_html(string $text): string {
    // escape first
    $s = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
    // linkify http(s)
    $s = preg_replace('~(https?://[^\s<]+)~i', '<a href="$1" target="_blank" rel="noopener">$1</a>', $s);
    // newlines to <br>
    return nl2br($s);
}

// --- Require signed token from Contracts Admin link ---
$clientid = $_GET['clientid'] ?? '';
$token    = $_GET['token']    ?? '';

if (!preg_match('/^[A-Za-z0-9_-]+$/', $clientid)) {
    http_response_code(400);
    exit('Bad link (clientid).');
}
if ($token === '') {
    http_response_code(403);
    exit('Missing token.');
}

// Build expected token from the .md front matter secret
$expected = progress_expected_token($clientid, $app_id);
if (!$expected || !hash_equals($expected, $token)) {
    http_response_code(403);
    exit('Invalid or expired link.');
}

?>

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title><?= htmlspecialchars($app['reference']) ?> – Application Progress</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.13.1/font/bootstrap-icons.min.css">
        <link href="progress.css" rel="stylesheet">
		<style>
		.popover-attachments { max-width: 360px; }
		.popover-attachments .popover-body { padding: .5rem .75rem; }
		</style>
    </head>
    <body>
        <!--
<nav class="navbar bg-dark border-bottom border-body d-print-none" data-bs-theme="dark">
<div class="container">
<a class="navbar-brand text-white" href="#">
<img src="../internal/images/blueprint-logo-light.png" width="30" height="24" class="d-inline-block align-text-top" alt="Modulos">
Modulos Design
</a>
</div>
</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-6 text-start">
                        <!-- CUSTOMER DETAILS HERE -->
                    </div>
                    <div class="col-12 col-md-6 text-end pt-2">
        				<h3 class="fw-bold mb-1 text-dark">Development Application</h3>
                        <h3 class="fw-bold mb-1 text-dark">Application No: <?= htmlspecialchars($app['reference']) ?></h3>
                        <h5 class="mb-0 text-muted">Started: <?= date("d M Y", strtotime($app['created_at'])) ?></h5>
                    </div>
                </div>

                <hr class="my-4">

                <div class="row my-4">
                    <div class="col-12 align-self-center">
                        <div class="steps">
                            <?php
    $labels = ['Submit','Acknowledge','Paid','Confirmed','Advertise','Complete','Decision'];
            $N = count($labels);

            // Build status + date arrays by position
            $statusByIndex = array_fill(0, $N, 'pending');
            $dateByIndex   = array_fill(0, $N, null);

            foreach ($stages as $row) {
                $idx = (int)($row['position'] ?? -1);
                if ($idx < 0 || $idx >= $N) continue;

                $st = strtolower(trim($row['status'] ?? 'pending'));
                if (!in_array($st, ['complete','current','pending'], true)) $st = 'pending';
                $statusByIndex[$idx] = $st;

                $dateByIndex[$idx] = $row['stage_date'] ?: ($row['updated_at'] ?: ($row['created_at'] ?? null));
            }

            // If no explicit "current", highlight the *last complete* stage
            $hasCurrent = false;
            foreach ($statusByIndex as $st) { if (strpos($st, 'current') !== false) { $hasCurrent = true; break; } }
            if (!$hasCurrent) {
                $lastComplete = -1;
                for ($i = 0; $i < $N; $i++) if ($statusByIndex[$i] === 'complete') $lastComplete = $i;
                if ($lastComplete >= 0) {
                    $statusByIndex[$lastComplete] = 'current'; // keep green, add highlight
                } else {
                    $statusByIndex[0] = trim($statusByIndex[0] . ' current'); // nothing complete yet
                }
            }

            $fmt = function (?string $s): string {
                if (!$s) return '';
                $t = strtotime($s);
                return $t ? date('d M Y', $t) : '';
            };
                            ?>

                            <!-- Top row: arrows + inline (mobile-only) dates -->
                            <ul class="step-menu">
                                <?php for ($i = 0; $i < $N; $i++):
                                $class    = htmlspecialchars($statusByIndex[$i]);
                                $dateText = $fmt($dateByIndex[$i]);
                                $isComplete = (strpos($class, 'complete') !== false);
                                $prefix   = (!$isComplete && $dateText) ? 'Due ' : '';
                                ?>
                                <li class="<?= $class ?>">
                                    <?= htmlspecialchars($labels[$i]) ?>
                                    <?php if ($dateText): ?>
                                    <div class="date-inline small mt-1 d-xxl-none"><?= htmlspecialchars($prefix . $dateText) ?></div>
                                    <?php endif; ?>
                                </li>
                                <?php endfor; ?>
                            </ul>

                            <!-- Bottom row: desktop-only date line, aligned with arrows -->
                            <ul class="step-dates d-none d-xxl-flex">
                                <?php for ($i = 0; $i < $N; $i++):
                                $rawClass   = trim((string)($statusByIndex[$i] ?? ''));
                                $tokens     = preg_split('/\s+/', $rawClass, -1, PREG_SPLIT_NO_EMPTY);
                                $isComplete = in_array('complete', $tokens, true);
                                $isCurrent  = in_array('current',  $tokens, true);

                                $dateText = $fmt($dateByIndex[$i]);
                                $prefix   = (!$isComplete && !$isCurrent && $dateText) ? 'Due ' : '';
                                ?>
                                <li class="<?= htmlspecialchars($rawClass, ENT_QUOTES, 'UTF-8') ?>">
                                    <?= $dateText ? htmlspecialchars($prefix . $dateText, ENT_QUOTES, 'UTF-8') : '&nbsp;' ?>
                                </li>
                                <?php endfor; ?>
                            </ul>
                        </div>
                    </div>
                </div>

                <div class="row py-3">
                    <div class="col-12">
                        <?php if (!empty($decisionIso)): ?>
                        <div class="countdown" data-target-date="<?php echo $decisionIso; ?>"></div>
                        <?php endif; ?>
                    </div>
                </div>

                <div class="row">
                    <?php if (empty($stages)): ?>
                    <div class="col-12">
                        <div class="alert alert-warning">This application has not started yet.</div>
                    </div>
                    <?php endif; ?>
                </div>

                <hr class="my-4">
                <div class="row">
                    <div class="col-12 text-center">
                        <h4>Timeline of Correspondence</h4>
                    </div>
                </div>
                <div class="row py-3">
                    <div class="col">
                        <div class="timeline">
                            <?php
                            $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'
                            ];

                            $typeLabel = ['incoming'=>'Incoming','outgoing'=>'Outgoing','note'=>'Note'];
                            $chLabel   = ['email'=>'Email','phone'=>'Phone','meeting'=>'Meeting','other'=>'Other'];

                            foreach ($correspondence as $row):
                            $id = (int)$row['id'];
                            $typeVal    = strtolower(trim($row['type'] ?? 'note'));
                            $channelVal = strtolower(trim($row['channel'] ?? 'other'));
                            $key        = ($typeVal === 'note') ? 'note' : "{$channelVal}_{$typeVal}";
                            $icon       = $badgeMap[$key] ?? ($fallbackByChannel[$channelVal] ?? 'bi-journal-text');

                            $when      = (new DateTime($row['event_at'], new DateTimeZone('Australia/Hobart')))->format('d M Y, h:ia');
                            $visBadge  = $row['visibility']==='internal' ? '<span class="badge rounded-pill text-bg-secondary ms-2">Internal</span>' : '';
                            $typeClass = 'type-'.preg_replace('/[^a-z]/','', $typeVal);

                            $numFiles = $fileCounts[$id] ?? 0;                    // <- NEW
                            $hasFiles = $numFiles > 0;                            // <- NEW
                            ?>
                            <div class="timeline-item <?= $row['pin'] ? 'pinned' : '' ?>">
                                <div class="timeline-badge"><i class="bi <?= $icon ?>"></i></div>
                                <div class="timeline-panel <?= $typeClass ?>">
                                    <div class="timeline-heading d-flex justify-content-between align-items-start">
                                        <div>
                                            <h6 class="mb-1">
                                                <?= $when ?> • <?= $typeLabel[$typeVal] ?? ucfirst($typeVal) ?>
                                                via <?= $chLabel[$channelVal] ?? ucfirst($channelVal) ?>
                                                <?= $visBadge ?>
                                                <?php if ($row['pin']): ?>
                                                <i class="bi bi-pin-angle-fill text-warning ms-1" title="Pinned"></i>
                                                <?php endif; ?>

                                                
                                                <?php if (!empty($filesByCorr[$id])): ?>
                                                <span class="ms-2 att-pop"
                                                      role="button"
                                                      tabindex="0"
                                                      data-bs-toggle="popover"
                                                      data-bs-trigger="hover focus"
                                                      data-bs-placement="top"
                                                      data-bs-custom-class="popover-attachments"
                                                      data-content-id="att-popover-<?= $id ?>"
                                                      title="Attachments (<?= (int)$numFiles ?>)">
                                                    <i class="bi bi-paperclip"></i>
                                                </span>
                                                
                                                
                                                <?php endif; ?>
                                                

                                            </h6>
                                            <small class="text-muted">
                                                <?= htmlspecialchars($row['subject'] ?: ucfirst($typeVal)) ?>
                                                <?= $row['author'] ? ' • by: '.htmlspecialchars($row['author']) : '' ?>
                                            </small>
                                        </div>
                                    </div>

                                    <div class="timeline-body mt-2 small">
                                        <?= render_body_html($row['body']) ?>
                                    </div>
                                </div>
                            </div>
                            <?php endforeach; ?>


                            <?php if (empty($correspondence)): ?>
                            <div class="text-muted">No correspondence recorded yet.</div>
                            <?php endif; ?>

                        </div>
                    </div>
                </div>
            </div>

        </main>
        <script>
            const countdownEls = document.querySelectorAll(".countdown")
            countdownEls.forEach(countdownEl => createCountdown(countdownEl))

            function createCountdown(countdownEl){
                const target = new Date(new Date(countdownEl.dataset.targetDate).toLocaleString('en', ))
                const parts = {
                    days: {text: ["days","day"], dots: 30},
                    hours: {text: ["hours","hour"], dots: 24},
                    minutes: {text: ["minutes","minute"], dots: 60},
                    seconds: {text: ["seconds","second"], dots: 60},
                }

                Object.entries(parts).forEach(([key, value])=>{
                    const partEl = document.createElement("div");
                    partEl.classList.add("part", key);
                    partEl.style.setProperty("--dots", value.dots);
                    value.element = partEl;

                    const remainingEl = document.createElement("div");
                    remainingEl.classList.add("remaining");
                    remainingEl.innerHTML = `<span class="number"></span><span class="text"></span>`
                    partEl.append(remainingEl);
                    for(let i = 0; i < value.dots; i++){
                        const dotContainerEl = document.createElement("div");
                        dotContainerEl.style.setProperty("--dot-idx", i);
                        dotContainerEl.classList.add("dot-container")
                        const dotEl = document.createElement("div");
                        dotEl.classList.add("dot")
                        dotContainerEl.append(dotEl);
                        partEl.append(dotContainerEl);
                    }
                    countdownEl.append(partEl);
                })
                getRemainingTime(target, parts)
            }

            function getRemainingTime(target, parts, first=true){
                const now = new Date()
                const remaining = {}
                let seconds = Math.floor((target - (now))/1000);
                let minutes = Math.floor(seconds/60);
                let hours = Math.floor(minutes/60);
                let days = Math.floor(hours/24);
                hours = hours-(days*24);
                minutes = minutes-(days*24*60)-(hours*60);
                seconds = seconds-(days*24*60*60)-(hours*60*60)-(minutes*60);
                Object.entries({days, hours, minutes, seconds}).forEach(([key, value])=>{
                    const remaining = parts[key].element.querySelector(".number");
                    const text = parts[key].element.querySelector(".text");
                    remaining.innerText = value;
                    text.innerText = parts[key].text[Number(value==1)]
                    const dots = parts[key].element.querySelectorAll(".dot")
                    dots.forEach((dot, idx)=>{
                        dot.dataset.active = idx <= value;
                        dot.dataset.lastactive = idx == value;
                    })
                })
                if(now <= target){
                    window.requestAnimationFrame(()=>{
                        getRemainingTime(target, parts, false)
                    });
                }
            }

            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())) {
            // to local datetime-local string
            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());
            const el = document.querySelector('input[name="event_at"]');
            if (el) el.value = v;
            }
            }
            });

            document.addEventListener('DOMContentLoaded', () => {
            document.querySelectorAll('[data-bs-toggle="popover"][data-content-id]').forEach(el => {
            const id = el.getAttribute('data-content-id');
            const tpl = document.getElementById(id);
            const content = tpl ? tpl.innerHTML : '';
            new bootstrap.Popover(el, {
                html: true,
                content,
                container: 'body',
                sanitize: true,         // keep Bootstrap’s sanitizer on
                trigger: 'hover focus'  // hover on desktop, tap/focus on mobile
            });
            });
            });
        </script>
    </body>
</html>