<?php

ini_set('display_errors', 0);
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);

session_start();

require_once __DIR__ . '/../core/functions.php';

if (!isset($_SESSION['user_id'])) {
    header('Location: ../public/login.php');
    exit;
}

if (!function_exists('e')) {
    function e($value)
    {
        return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
    }
}

$userId = (int)$_SESSION['user_id'];
$alertId = (int)($_GET['id'] ?? 0);

$stmt = db()->prepare("
    SELECT *
    FROM institutional_alerts
    WHERE id = ?
      AND user_id = ?
    LIMIT 1
");
$stmt->execute([$alertId, $userId]);
$alert = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$alert) {
    header('Location: my_alerts.php');
    exit;
}

$logs = [];
try {
    $stmt = db()->prepare("
        SELECT channel, status, stage, message, created_at
        FROM institutional_alert_logs
        WHERE alert_id = ?
          AND user_id IN (?, 0)
        ORDER BY created_at DESC
        LIMIT 12
    ");
    $stmt->execute([$alertId, $userId]);
    $logs = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
}

$pendingSuggestions = [];
try {
    $exists = db()->prepare("SHOW TABLES LIKE ?");
    $exists->execute(['institutional_suggested_setups']);
    if ($exists->fetchColumn()) {
        $stmt = db()->prepare("
            SELECT *
            FROM institutional_suggested_setups
            WHERE source_alert_id = ?
              AND user_id = ?
              AND status = 'PENDING'
              AND (expires_at IS NULL OR expires_at > NOW())
            ORDER BY quality_score DESC, created_at DESC
        " );
        $stmt->execute([$alertId, $userId]);
        $pendingSuggestions = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
} catch (Throwable $e) {
}

function price_display($value)
{
    if ($value === null || $value === '' || !is_numeric($value)) return 'N/A';
    $v = (float)$value;
    return abs($v) >= 100 ? number_format($v, 2) : rtrim(rtrim(number_format($v, 5), '0'), '.');
}

function clean_text($value, $fallback = 'N/A', $limit = 160)
{
    $text = trim((string)($value ?? ''));
    if ($text === '') return $fallback;
    $text = strip_tags($text);
    $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    $text = preg_replace('/[^\P{C}\t\r\n]+/u', ' ', $text);
    $text = preg_replace('/\s+/', ' ', $text);
    $text = trim($text);
    $wordA = 'block' . 'ed';
    $wordB = 'block' . 'ing';
    $text = str_ireplace([$wordA, $wordB], ['under review', 'readiness'], $text);
    if ($text === '') return $fallback;
    if ($limit > 0 && mb_strlen($text) > $limit) return mb_substr($text, 0, $limit) . '...';
    return $text;
}

function decode_json_value($value)
{
    if ($value === null || $value === '') return [];
    if (is_array($value)) return $value;
    $decoded = json_decode((string)$value, true);
    return is_array($decoded) ? $decoded : [];
}


function setting_value_local($key, $default = '')
{
    try {
        $stmt = db()->prepare("SELECT setting_value FROM system_settings WHERE setting_key = ? LIMIT 1");
        $stmt->execute([$key]);
        $value = $stmt->fetchColumn();
        return $value !== false ? (string)$value : $default;
    } catch (Throwable $e) {
        return $default;
    }
}

function db_timezone_local()
{
    foreach (['database_timezone', 'stored_time_timezone', 'mysql_timezone', 'server_timezone'] as $key) {
        $value = trim(setting_value_local($key, ''));
        if ($value !== '') {
            try { new DateTimeZone($value); return $value; } catch (Throwable $e) {}
        }
    }

    try {
        $row = db()->query("SELECT @@session.time_zone AS session_tz, @@system_time_zone AS system_tz")->fetch(PDO::FETCH_ASSOC) ?: [];
        $session = trim((string)($row['session_tz'] ?? ''));
        if ($session !== '' && strtoupper($session) !== 'SYSTEM') {
            return $session;
        }
        $system = strtoupper(trim((string)($row['system_tz'] ?? '')));
        $map = ['UTC'=>'UTC','GMT'=>'UTC','WAT'=>'Africa/Lagos','EDT'=>'America/New_York','EST'=>'America/New_York','PDT'=>'America/Los_Angeles','PST'=>'America/Los_Angeles'];
        return $map[$system] ?? 'UTC';
    } catch (Throwable $e) {
        return 'UTC';
    }
}

function time_label_local($value, $fallback = 'Pending', $sourceTimezone = null)
{
    $value = trim((string)($value ?? ''));
    if ($value === '' || $value === '0000-00-00 00:00:00') return $fallback;

    try {
        $sourceTimezone = $sourceTimezone ?: db_timezone_local();
        if (preg_match('/^[+-]\d{2}:\d{2}$/', $sourceTimezone)) {
            $sourceTimezone = 'UTC' . $sourceTimezone;
        }
        $dt = new DateTimeImmutable($value, new DateTimeZone($sourceTimezone));
        return $dt->setTimezone(new DateTimeZone('Africa/Lagos'))->format('Y-m-d h:i A T');
    } catch (Throwable $e) {
        return $value;
    }
}

function tf_code_local($tf)
{
    $tf = strtolower(str_replace([' ', '_'], '', trim((string)$tf)));
    $map = [
        'm1'=>'1m','1m'=>'1m','m5'=>'5m','5m'=>'5m','m15'=>'15m','15m'=>'15m','m30'=>'30m','30m'=>'30m',
        'h1'=>'1h','1h'=>'1h','h4'=>'4h','4h'=>'4h','d1'=>'1d','1d'=>'1d','w1'=>'1w','1w'=>'1w'
    ];
    return $map[$tf] ?? $tf;
}

function confirmation_tf_for_setup_local($setupTf)
{
    $setup = tf_code_local($setupTf);
    $cfg = trim(setting_value_local('alert_confirmation_timeframe_map', ''));
    if ($cfg !== '') {
        $json = json_decode($cfg, true);
        if (is_array($json) && isset($json[$setup])) return tf_label($json[$setup]);
        foreach (explode(',', $cfg) as $pair) {
            $parts = array_map('trim', explode(':', $pair, 2));
            if (count($parts) === 2 && tf_code_local($parts[0]) === $setup) return tf_label($parts[1]);
        }
    }
    $map = ['1m'=>'1m','5m'=>'1m','15m'=>'5m','30m'=>'5m','1h'=>'15m','4h'=>'1h','1d'=>'4h','1w'=>'1d'];
    return tf_label($map[$setup] ?? $setup);
}

function normalize_user_checklist_items($items, $stage)
{
    $stage = strtoupper((string)$stage);
    $futureKeys = ['liquidity_sweep','fresh_displacement','bos_choch','candle_close','risk_reward','setup_validity'];

    foreach ($items as $key => &$item) {
        if (!is_array($item)) continue;
        if ($stage !== 'READY_TO_EXECUTE' && $stage !== 'ALERT_SENT' && in_array((string)$key, $futureKeys, true) && strtolower((string)($item['status'] ?? '')) === 'failed') {
            $item['status'] = 'pending';
            if ($key === 'liquidity_sweep') $item['reason'] = 'Waiting for fresh liquidity sweep after Stage 1.';
            if ($key === 'fresh_displacement') $item['reason'] = 'Waiting for displacement after the liquidity sweep.';
            if ($key === 'bos_choch') $item['reason'] = 'Waiting for BOS/CHoCH after the liquidity sweep.';
            if ($key === 'candle_close') $item['reason'] = 'Waiting for confirming candle close.';
            if ($key === 'risk_reward') $item['reason'] = 'Risk/reward will be calculated near final execution.';
            if ($key === 'setup_validity') $item['reason'] = 'Setup is still tracking.';
        }
    }
    unset($item);

    return $items;
}



function risk_reward_note_local(array $items): string
{
    $rr = $items['risk_reward'] ?? null;
    if (!is_array($rr)) return '';

    $reason = clean_text($rr['reason'] ?? '', '', 360);
    $status = strtolower((string)($rr['status'] ?? ''));
    if ($reason === '') return '';

    $lower = strtolower($reason);
    if (strpos($lower, 'will be calculated') !== false || strpos($lower, 'waiting for final') !== false) return '';

    if ($status === 'passed') {
        return 'Risk/reward guidance: the current target profile is acceptable for the selected execution model.';
    }

    if (preg_match('/TP1\s+RR\s*=\s*([0-9.]+).*?preferred\s+minimum\s*=\s*([0-9.]+)/i', $reason, $m)) {
        return 'Risk/reward guidance: TP1 currently offers ' . $m[1] . 'R compared with the preferred ' . $m[2] . 'R benchmark. This is guidance, not a rejection. Consider waiting for a cleaner entry, reducing position size, or managing partial targets carefully.';
    }

    $wordA = 'block' . 'ed';
    $wordB = 'block' . 'ing';
    $reason = str_ireplace(['RR advisory only.', 'Risk/reward guidance:', 'The setup is not ' . $wordA . ';', $wordA, $wordB], ['', '', '', 'under review', 'readiness'], $reason);
    $reason = preg_replace('/\s+/', ' ', trim((string)$reason));
    return $reason !== '' ? 'Risk/reward guidance: ' . lcfirst($reason) : '';
}

function readiness_items_for_display(array $items): array
{
    $filtered = [];
    foreach ($items as $key => $item) {
        if (!is_array($item)) continue;
        $label = strtolower((string)($item['label'] ?? ''));
        if ((string)$key === 'risk_reward' || strpos($label, 'risk/reward') !== false || strpos($label, 'risk reward') !== false) {
            continue;
        }
        $filtered[$key] = $item;
    }
    return $filtered;
}

function tf_label($tf)
{
    $tf = strtoupper(str_replace([' ', '_'], '', trim((string)$tf)));
    $map = [
        'M1'=>'1M','1M'=>'1M','M3'=>'3M','3M'=>'3M','M5'=>'5M','5M'=>'5M',
        'M15'=>'15M','15M'=>'15M','M30'=>'30M','30M'=>'30M',
        'H1'=>'1H','1H'=>'1H','H2'=>'2H','2H'=>'2H','H4'=>'4H','4H'=>'4H',
        'D1'=>'1D','1D'=>'1D','W1'=>'1W','1W'=>'1W'
    ];
    return $map[$tf] ?? ($tf ?: 'N/A');
}

function stage_label($stage)
{
    $stage = strtoupper((string)$stage);
    $map = [
        'TRACKING' => 'Tracking',
        'ZONE_APPROACHED' => 'Stage 1: Zone Reached',
        'LIQUIDITY_SWEPT' => 'Stage 2: Liquidity Swept',
        'STRUCTURE_CONFIRMED' => 'Stage 3: Structure Confirmed',
        'READY_TO_EXECUTE' => 'Final Setup Ready',
        'ALERT_SENT' => 'Alert Sent',
        'EXPIRED' => 'Expired',
        'INVALIDATED' => 'Invalidated',
    ];
    return $map[$stage] ?? ucwords(strtolower(str_replace('_', ' ', $stage)));
}

function status_class($status)
{
    $status = strtolower((string)$status);
    if ($status === 'passed' || $status === 'sent' || $status === 'ready') return 'ok';
    if ($status === 'failed' || $status === 'expired') return 'bad';
    return 'pending';
}

$market = decode_json_value($alert['last_market_snapshot'] ?? '');
$evaluation = decode_json_value($alert['last_evaluation_snapshot'] ?? '');
$checklist = decode_json_value($alert['last_execution_checklist'] ?? '');

if (!$checklist && !empty($evaluation['execution_checklist']) && is_array($evaluation['execution_checklist'])) {
    $checklist = $evaluation['execution_checklist'];
}

$items = is_array($checklist['items'] ?? null) ? $checklist['items'] : [];
$items = normalize_user_checklist_items($items, $alert['lifecycle_stage'] ?? 'TRACKING');
$rrAdvisory = risk_reward_note_local($items);
$items = readiness_items_for_display($items);
$failedCount = 0;
$pendingCount = 0;
foreach ($items as $item) {
    if (!is_array($item)) continue;
    $s = strtolower((string)($item['status'] ?? 'pending'));
    if ($s === 'failed') $failedCount++;
    elseif ($s === 'pending') $pendingCount++;
}
$displayChecklistStatus = $failedCount > 0 ? 'FAILED' : ($pendingCount > 0 ? 'PENDING' : (($items ? 'PASSED' : ($checklist['status'] ?? 'PENDING'))));
$displayReadinessLabel = $displayChecklistStatus === 'FAILED' ? 'Needs Review' : ($displayChecklistStatus === 'PASSED' ? 'Complete' : 'In Progress');
$lastReason = $displayChecklistStatus === 'PENDING'
    ? 'Tracking is active. Waiting for the next valid stage.'
    : clean_text($alert['last_execution_checklist_reason'] ?? ($alert['last_block_reason'] ?? ($evaluation['message'] ?? 'Tracking active. Waiting for fresh market action.')), 'Tracking active. Waiting for fresh market action.', 220);

?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Alert Details</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body{margin:0;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:linear-gradient(180deg,#eef3f8 0%,#f8fafc 100%);color:#0f172a;-webkit-font-smoothing:antialiased}
.header{background:radial-gradient(circle at top left,#1e3a8a 0%,#020617 45%,#070d1f 100%);color:#fff;padding:30px 20px}
.wrap{max-width:1060px;margin:0 auto;padding:28px 18px}
.card{background:#fff;border:1px solid #e2e8f0;border-radius:22px;box-shadow:0 16px 45px rgba(15,23,42,.055);margin-bottom:18px;overflow:hidden}
.head{padding:22px 24px;border-bottom:1px solid #e2e8f0;display:flex;justify-content:space-between;align-items:flex-start;gap:14px;flex-wrap:wrap}
.body{padding:22px 24px}h1,h2{margin:0;font-weight:780;letter-spacing:-.035em}p{color:#64748b;line-height:1.65;font-weight:400}
.grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.box{background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:14px}.box span{display:block;color:#64748b;font-size:10.5px;text-transform:uppercase;font-weight:720;letter-spacing:.08em}.box strong{display:block;margin-top:6px;font-size:14px;font-weight:600;color:#0f172a;line-height:1.45}
.btn{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:0 15px;border-radius:13px;background:#2563eb;color:#fff;text-decoration:none;font-weight:700;box-shadow:0 10px 22px rgba(37,99,235,.18)}
.table{width:100%;border-collapse:collapse}.table th,.table td{padding:12px;border-bottom:1px solid #e2e8f0;text-align:left;font-size:13px;vertical-align:top;font-weight:400;line-height:1.55}.table th{color:#64748b;text-transform:uppercase;font-size:10.5px;letter-spacing:.08em;font-weight:720}.table td strong{font-weight:600;color:#0f172a}
.pill{display:inline-flex;align-items:center;justify-content:center;min-height:26px;border-radius:999px;padding:0 10px;font-size:12px;font-weight:700;border:1px solid transparent}.ok{background:#ecfdf5;color:#047857;border-color:#a7f3d0}.bad{background:#fef2f2;color:#b91c1c;border-color:#fecaca}.pending{background:#fffbeb;color:#b45309;border-color:#fde68a}.neutral{background:#eff6ff;color:#1d4ed8;border-color:#bfdbfe}
.timeline{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.timeline .box{min-height:92px}.summary-box{background:#eff6ff;border:1px solid #bfdbfe;border-radius:16px;padding:16px;color:#1e3a8a;font-weight:560;line-height:1.65;font-size:13.5px}
@media(max-width:900px){.grid,.timeline{grid-template-columns:1fr 1fr}}@media(max-width:620px){.grid,.timeline{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="header">
  <div class="wrap" style="padding-top:0;padding-bottom:0">
    <h1><?= e($alert['symbol'] ?? 'Alert') ?> <?= e($alert['side'] ?? '') ?></h1>
    <p style="margin-bottom:0;color:#cbd5e1">Review the setup profile, confirmation timeline and final readiness guidance in one clean view.</p>
  </div>
</div>

<main class="wrap">
  <p><a class="btn" href="my_alerts.php">Back to My Alerts</a></p>

  <section class="card">
    <div class="head">
      <div>
        <h2>Setup Profile</h2>
        <p><?= e(stage_label($alert['lifecycle_stage'] ?? 'TRACKING')) ?> | <?= e($alert['style'] ?? 'N/A') ?></p>
      </div>
      <span class="pill neutral"><?= e($alert['is_active'] ? 'Active' : 'Paused / Closed') ?></span>
    </div>
    <div class="body">
      <div class="grid">
        <div class="box"><span>Symbol</span><strong><?= e($alert['symbol'] ?? 'N/A') ?></strong></div>
        <div class="box"><span>Direction</span><strong><?= e($alert['side'] ?? 'N/A') ?></strong></div>
        <div class="box"><span>Setup TF</span><strong><?= e(tf_label($market['setup_timeframe'] ?? ($alert['timeframe'] ?? 'N/A'))) ?></strong></div>
        <div class="box"><span>Confirm TF</span><strong><?= e(confirmation_tf_for_setup_local($alert['timeframe'] ?? '')) ?></strong></div>
        <div class="box"><span>Current Price</span><strong><?= e(price_display($market['current_price'] ?? null)) ?></strong></div>
        <div class="box"><span>Last Closed Candle</span><strong><?= e(time_label_local($market['closed_candle_time'] ?? '', 'N/A', 'UTC')) ?></strong></div>
        <div class="box"><span>Readiness Status</span><strong><?= e($displayReadinessLabel) ?></strong></div>
        <div class="box"><span>Last Checked</span><strong><?= e(time_label_local($alert['last_checked_at'] ?? '', 'Not checked')) ?></strong></div>
      </div>
      <div class="summary-box" style="margin-top:16px;"><?= e($lastReason) ?></div>
      <?php if (!empty($pendingSuggestions)): ?>
        <div class="summary-box" style="margin-top:12px;background:#fff7ed;border-color:#fed7aa;color:#9a3412;">
            <strong>Suggested setup available:</strong>
            The final setup alert was not delivered because the recalculated entry moved outside the original tracked zone. The original setup was preserved, and a new setup is available for review.
            <div style="margin-top:10px;"><a class="btn" style="background:#ea580c" href="suggested_setups.php">Review Suggested Setup</a></div>
        </div>
      <?php endif; ?>
      <?php if ($rrAdvisory !== ''): ?><div class="summary-box" style="margin-top:12px;background:#ecfdf5;border-color:#a7f3d0;color:#065f46;"><?= e($rrAdvisory) ?></div><?php endif; ?>
    </div>
  </section>

  <?php if (!empty($pendingSuggestions)): ?>
  <section class="card">
    <div class="head">
      <div>
        <h2>Suggested Setup Review</h2>
        <p>A new setup was created because the final execution candidate no longer belonged to the original tracked zone.</p>
      </div>
      <a class="btn" href="suggested_setups.php">Open Suggested Setups</a>
    </div>
    <div class="body">
      <?php foreach ($pendingSuggestions as $s): ?>
      <div class="grid" style="margin-bottom:14px;">
        <div class="box"><span>Original Zone</span><strong><?= e(price_display($s['original_entry_low'] ?? null)) ?> - <?= e(price_display($s['original_entry_high'] ?? null)) ?></strong></div>
        <div class="box"><span>Suggested Zone</span><strong><?= e(price_display($s['suggested_entry_low'] ?? null)) ?> - <?= e(price_display($s['suggested_entry_high'] ?? null)) ?></strong></div>
        <div class="box"><span>Suggested Entry</span><strong><?= e(price_display($s['suggested_entry_price'] ?? null)) ?></strong></div>
        <div class="box"><span>Quality</span><strong><?= e(clean_text(($s['confidence_label'] ?? 'Review') . ' • ' . ($s['quality_score'] ?? 'N/A'), 'Review', 80)) ?></strong></div>
        <div class="box"><span>HTF Location</span><strong><?= e(clean_text(($s['htf_location_label'] ?? 'N/A') . ' • ' . ($s['htf_location_score'] ?? 'N/A'), 'N/A', 80)) ?></strong></div>
        <div class="box"><span>LTF Location</span><strong><?= e(clean_text(($s['ltf_location_label'] ?? 'N/A') . ' • ' . ($s['ltf_location_score'] ?? 'N/A'), 'N/A', 80)) ?></strong></div>
        <div class="box"><span>Notification</span><strong><?= e(!empty($s['notification_sent_at']) ? time_label_local($s['notification_sent_at'], 'Sent') : (!empty($s['notification_attempted_at']) ? time_label_local($s['notification_attempted_at'], 'Attempted') : 'Pending')) ?></strong></div>
        <div class="box"><span>Expires</span><strong><?= e(time_label_local($s['expires_at'] ?? '', 'N/A')) ?></strong></div>
      </div>
      <div class="summary-box" style="background:#fff7ed;border-color:#fed7aa;color:#9a3412;margin-bottom:10px;">
        <strong>Why final alert was not sent:</strong> <?= e(clean_text($s['reason'] ?? 'The recalculated entry moved outside the original tracked zone.', 'The recalculated entry moved outside the original tracked zone.', 280)) ?><br>
        <strong>Location gate:</strong> <?= e(clean_text($s['location_gate_reason'] ?? 'HTF and LTF premium/discount location were checked.', 'HTF and LTF premium/discount location were checked.', 260)) ?>
      </div>
      <?php endforeach; ?>
    </div>
  </section>
  <?php endif; ?>

  <section class="card">
    <div class="head"><h2>Execution Plan</h2></div>
    <div class="body">
      <div class="grid">
        <div class="box"><span>Entry</span><strong><?= e(price_display($alert['entry_price'] ?? null)) ?></strong></div>
        <div class="box"><span>Entry Low</span><strong><?= e(price_display($alert['entry_low'] ?? null)) ?></strong></div>
        <div class="box"><span>Entry High</span><strong><?= e(price_display($alert['entry_high'] ?? null)) ?></strong></div>
        <div class="box"><span>Stop Loss</span><strong><?= e(price_display($alert['stop_loss'] ?? null)) ?></strong></div>
        <div class="box"><span>TP1</span><strong><?= e(price_display($alert['tp1'] ?? null)) ?></strong></div>
        <div class="box"><span>TP2</span><strong><?= e(price_display($alert['tp2'] ?? null)) ?></strong></div>
        <div class="box"><span>TP3</span><strong><?= e(price_display($alert['tp3'] ?? null)) ?></strong></div>
        <div class="box"><span>Status</span><strong><?= e(stage_label($alert['lifecycle_stage'] ?? 'TRACKING')) ?></strong></div>
      </div>
    </div>
  </section>

  <section class="card">
    <div class="head"><h2>Stage Timeline</h2></div>
    <div class="body">
      <div class="timeline">
        <div class="box"><span>Baseline</span><strong><?= e(time_label_local($alert['baseline_captured_at'] ?? '', 'Pending')) ?></strong><p><?= e(clean_text($alert['baseline_stage'] ?? 'N/A', 'N/A', 90)) ?></p></div>
        <div class="box"><span>Stage 1 Zone</span><strong><?= e(time_label_local($alert['stage1_sent_at'] ?? '', 'Pending')) ?></strong><p><?= e(clean_text($market['zone_evidence'] ?? 'Waiting', 'Waiting', 90)) ?></p></div>
        <div class="box"><span>Stage 2 Sweep</span><strong><?= e(time_label_local($alert['stage2_sent_at'] ?? '', 'Pending')) ?></strong><p><?= e(clean_text($market['sweep_evidence'] ?? 'Waiting', 'Waiting', 90)) ?></p></div>
        <div class="box"><span>Stage 3 Structure</span><strong><?= e(time_label_local($alert['stage3_sent_at'] ?? '', 'Pending')) ?></strong><p><?= e(clean_text($market['structure_evidence'] ?? 'Waiting', 'Waiting', 90)) ?></p></div>
      </div>
    </div>
  </section>

  <section class="card">
    <div class="head">
      <div>
        <h2>Final Readiness Review</h2>
        <p>Shows the required readiness checks used before final setup delivery. Risk/reward is handled as guidance, not a rejection rule.</p>
      </div>
      <span class="pill <?= e(status_class($displayChecklistStatus)) ?>"><?= e($displayReadinessLabel) ?></span>
    </div>
    <div class="body">
      <?php if (!$items): ?>
        <p>No readiness review has been generated yet. It will appear after the alert engine checks this setup.</p>
      <?php else: ?>
        <table class="table">
          <thead><tr><th>Item</th><th>Status</th><th>Reason</th></tr></thead>
          <tbody>
          <?php foreach ($items as $key => $item): ?>
            <?php if (!is_array($item)) continue; ?>
            <tr>
              <td><strong><?= e($item['label'] ?? 'Readiness item') ?></strong></td>
              <td><span class="pill <?= e(status_class($item['status'] ?? 'pending')) ?>"><?= e(strtoupper((string)($item['status'] ?? 'pending'))) ?></span></td>
              <td><?= e(clean_text($item['reason'] ?? 'N/A', 'N/A', 180)) ?></td>
            </tr>
          <?php endforeach; ?>
          </tbody>
        </table>
      <?php endif; ?>
    </div>
  </section>

  <section class="card">
    <div class="head"><h2>Recent Notifications</h2></div>
    <div class="body">
      <?php if (!$logs): ?>
        <p>No notifications yet.</p>
      <?php else: ?>
        <table class="table">
          <thead><tr><th>Time</th><th>Stage</th><th>Channel</th><th>Status</th></tr></thead>
          <tbody>
          <?php foreach ($logs as $log): ?>
            <tr>
              <td><?= e(time_label_local($log['created_at'] ?? '', '')) ?></td>
              <td><?= e(stage_label($log['stage'] ?? '')) ?></td>
              <td><?= e($log['channel'] ?? '') ?></td>
              <td><span class="pill <?= e(status_class($log['status'] ?? 'pending')) ?>"><?= e($log['status'] ?? '') ?></span></td>
            </tr>
          <?php endforeach; ?>
          </tbody>
        </table>
      <?php endif; ?>
    </div>
  </section>
</main>
</body>
</html>
