<?php

declare(strict_types=1);

require_once DENTAL_ROOT . '/app/bootstrap.php';
require_once DENTAL_ROOT . '/app/layout.php';

$pdo = db();
$user = current_user();
$requestedBranchId = max(0, (int) ($_GET['branch_id'] ?? 0));
$userBranchId = (int) ($user['branch_id'] ?? 0);

if ($requestedBranchId < 1) {
    $requestedBranchId = $userBranchId;
}
if ($requestedBranchId < 1) {
    $requestedBranchId = (int) ($pdo->query('SELECT id FROM `' . table('branches') . '` WHERE is_active=1 ORDER BY id LIMIT 1')->fetchColumn() ?: 0);
}

$token = trim((string) ($_GET['token'] ?? ''));
$tokenValid = queue_display_token_valid($requestedBranchId, $token);
$isPrivilegedUser = $user !== null && has_role(['super_admin','clinic_admin']);
$isSameBranchUser = $user !== null && ($userBranchId < 1 || $userBranchId === $requestedBranchId);

if (!$tokenValid && !$isPrivilegedUser && !$isSameBranchUser) {
    http_response_code(403);
    ?><!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Patient screen unavailable</title><style>body{font-family:system-ui,sans-serif;background:#071c29;color:#fff;display:grid;place-items:center;min-height:100vh;margin:0}.box{max-width:560px;padding:2rem;border:1px solid #34505d;border-radius:20px;background:#0d2b3b}.box h1{margin-top:0}.box p{color:#b7c7ce;line-height:1.6}</style></head><body><main class="box"><h1>Patient screen unavailable</h1><p>Open the Patient Queue Screen from the secure Clinic Queue page, then bookmark the generated screen link on the waiting-room device.</p></main></body></html><?php
    exit;
}

$branchStmt = $pdo->prepare('SELECT id,name,timezone FROM `' . table('branches') . '` WHERE id=? AND is_active=1 LIMIT 1');
$branchStmt->execute([$requestedBranchId]);
$branch = $branchStmt->fetch();
if (!$branch) {
    http_response_code(404);
    exit('Clinic branch not found.');
}

$branchTimezone = trim((string) ($branch['timezone'] ?? '')) ?: (string) app_config('app.timezone', 'Asia/Manila');
try { date_default_timezone_set($branchTimezone); } catch (Throwable) {}

function patient_screen_destination(array $row): string
{
    $status = (string) ($row['status'] ?? '');
    $chair = trim((string) ($row['chair_name'] ?? ''));
    if ($status === 'cashier_called') return 'Proceed to Cashier';
    if ($status === 'seated') return $chair !== '' ? 'Proceed to ' . $chair : 'Proceed to the dental treatment area';
    if ($status === 'called') return $chair !== '' ? 'Proceed to ' . $chair : 'Please proceed when called';
    return ucwords(str_replace('_', ' ', $status));
}

function patient_screen_payload(PDO $pdo, int $branchId): array
{
    $stmt = $pdo->prepare(
        'SELECT queue_no,source_type,status,checked_in_at,updated_at,chair_name,dentist_name '
        . 'FROM `' . table('queue_entries') . '` '
        . 'WHERE branch_id=? AND DATE(checked_in_at)=CURDATE() '
        . 'AND status NOT IN ("completed","cancelled") '
        . 'ORDER BY FIELD(priority,"emergency","urgent","regular"),checked_in_at,id'
    );
    $stmt->execute([$branchId]);
    $rows = $stmt->fetchAll();

    $serving = [];
    $waitingDental = [];
    $waitingCashier = [];
    $inTreatment = 0;

    foreach ($rows as $row) {
        $ticket = [
            'queue_no' => (string) $row['queue_no'],
            'source_type' => (string) $row['source_type'],
            'status' => (string) $row['status'],
            'destination' => patient_screen_destination($row),
            'wait_minutes' => max(0, (int) floor((time() - strtotime((string) $row['checked_in_at'])) / 60)),
        ];
        if (in_array($row['status'], ['called','seated','cashier_called'], true)) {
            $serving[] = $ticket;
        } elseif ($row['status'] === 'waiting') {
            $waitingDental[] = $ticket;
        } elseif ($row['status'] === 'waiting_billing') {
            $waitingCashier[] = $ticket;
        } elseif ($row['status'] === 'in_treatment') {
            $inTreatment++;
        }
    }

    return [
        'ok' => true,
        'server_time' => date(DATE_ATOM),
        'time_label' => date('g:i:s A'),
        'date_label' => date('l, F j, Y'),
        'serving' => array_slice($serving, 0, 6),
        'waiting_dental' => array_slice($waitingDental, 0, 18),
        'waiting_cashier' => array_slice($waitingCashier, 0, 12),
        'counts' => [
            'serving' => count($serving),
            'waiting_dental' => count($waitingDental),
            'waiting_cashier' => count($waitingCashier),
            'in_treatment' => $inTreatment,
        ],
    ];
}

$payload = patient_screen_payload($pdo, $requestedBranchId);
if (isset($_GET['feed'])) {
    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    echo json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    exit;
}

$brand = branding_profile();
$screenUrl = queue_display_relative_url($requestedBranchId);
?><!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<meta name="robots" content="noindex,nofollow,noarchive">
<title>Patient Queue Screen · <?= e((string) $brand['name']) ?></title>
<link rel="stylesheet" href="public/assets/css/app.css?v=<?= e(app_release_version()) ?>">
<?php if ($brand['favicon']): ?><link rel="icon" href="<?= e((string) $brand['favicon']) ?>"><?php endif; ?>
<style>:root{--primary:<?=e((string)$brand['primary'])?>;--primary2:<?=e((string)$brand['secondary'])?>;--brand-accent:<?=e((string)$brand['accent'])?>}</style>
</head>
<body class="patient-queue-screen" data-queue-screen>
<header class="patient-screen-header">
    <div class="patient-screen-brand">
        <?= brand_mark($brand, 'patient-screen-mark') ?>
        <div><span class="patient-screen-kicker">Live patient queue</span><h1><?= e((string) $brand['name']) ?></h1><p><?= e((string) $branch['name']) ?></p></div>
    </div>
    <div class="patient-screen-time"><strong data-screen-clock><?= e((string) $payload['time_label']) ?></strong><span data-screen-date><?= e((string) $payload['date_label']) ?></span></div>
    <div class="patient-screen-controls">
        <button type="button" data-screen-sound aria-pressed="false">Sound off</button>
        <button type="button" data-screen-fullscreen>Full screen</button>
        <?php if ($user !== null): ?><a href="queue.php">Staff queue</a><?php endif; ?>
    </div>
</header>

<main class="patient-screen-layout">
    <section class="patient-serving-section">
        <div class="patient-screen-section-head"><div><span>Now serving</span><h2>Please proceed when your number appears</h2></div><div class="patient-screen-live"><i></i><span data-screen-status>Live</span></div></div>
        <div class="patient-serving-grid" data-screen-serving>
            <?php if (!$payload['serving']): ?><div class="patient-screen-empty">Please wait for your ticket number to be called.</div><?php endif; ?>
            <?php foreach ($payload['serving'] as $ticket): ?><article class="patient-serving-card"><strong><?= e((string) $ticket['queue_no']) ?></strong><span><?= e((string) $ticket['destination']) ?></span></article><?php endforeach; ?>
        </div>
    </section>

    <section class="patient-waiting-grid">
        <article class="patient-waiting-panel">
            <div class="patient-waiting-title"><div><span>Dental care</span><h2>Waiting tickets</h2></div><strong data-count-dental><?= (int) $payload['counts']['waiting_dental'] ?></strong></div>
            <div class="patient-ticket-grid" data-screen-waiting-dental>
                <?php if (!$payload['waiting_dental']): ?><div class="patient-screen-small-empty">No tickets waiting for dental care.</div><?php endif; ?>
                <?php foreach ($payload['waiting_dental'] as $ticket): ?><span class="patient-ticket <?= e((string) $ticket['source_type']) ?>"><?= e((string) $ticket['queue_no']) ?></span><?php endforeach; ?>
            </div>
        </article>
        <article class="patient-waiting-panel cashier-panel">
            <div class="patient-waiting-title"><div><span>Cashier</span><h2>Waiting for payment</h2></div><strong data-count-cashier><?= (int) $payload['counts']['waiting_cashier'] ?></strong></div>
            <div class="patient-ticket-grid" data-screen-waiting-cashier>
                <?php if (!$payload['waiting_cashier']): ?><div class="patient-screen-small-empty">No tickets waiting for the cashier.</div><?php endif; ?>
                <?php foreach ($payload['waiting_cashier'] as $ticket): ?><span class="patient-ticket cashier-ticket"><?= e((string) $ticket['queue_no']) ?></span><?php endforeach; ?>
            </div>
        </article>
    </section>
</main>

<footer class="patient-screen-footer">
    <div><strong>Keep your ticket ready.</strong><span>Ticket numbers are used to protect patient privacy.</span></div>
    <div class="patient-screen-summary"><span><b data-count-treatment><?= (int) $payload['counts']['in_treatment'] ?></b> currently in treatment</span><span>Screen refreshes automatically</span></div>
</footer>

<script>
(()=>{
  const initial=<?= json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?>;
  const feedUrl=new URL(<?= json_encode($screenUrl) ?>,window.location.href);
  feedUrl.searchParams.set('feed','1');
  let knownServing=new Set(initial.serving.map(item=>item.queue_no+'|'+item.status));
  let soundEnabled=localStorage.getItem('dentalcare-queue-sound')==='on';
  let audioContext=null;
  const q=(selector)=>document.querySelector(selector);
  const text=(tag,value,className='')=>{const el=document.createElement(tag);el.textContent=value;if(className)el.className=className;return el;};
  const soundButton=q('[data-screen-sound]');
  const syncSoundButton=()=>{soundButton.textContent=soundEnabled?'Sound on':'Sound off';soundButton.setAttribute('aria-pressed',soundEnabled?'true':'false');};
  const beep=()=>{if(!soundEnabled)return;try{audioContext??=new (window.AudioContext||window.webkitAudioContext)();const osc=audioContext.createOscillator();const gain=audioContext.createGain();osc.frequency.value=880;gain.gain.setValueAtTime(.0001,audioContext.currentTime);gain.gain.exponentialRampToValueAtTime(.18,audioContext.currentTime+.03);gain.gain.exponentialRampToValueAtTime(.0001,audioContext.currentTime+.55);osc.connect(gain);gain.connect(audioContext.destination);osc.start();osc.stop(audioContext.currentTime+.6);}catch(e){}};
  soundButton?.addEventListener('click',async()=>{soundEnabled=!soundEnabled;localStorage.setItem('dentalcare-queue-sound',soundEnabled?'on':'off');if(soundEnabled){try{audioContext??=new (window.AudioContext||window.webkitAudioContext)();await audioContext.resume();beep();}catch(e){}}syncSoundButton();});
  syncSoundButton();
  q('[data-screen-fullscreen]')?.addEventListener('click',()=>{if(!document.fullscreenElement)document.documentElement.requestFullscreen?.();else document.exitFullscreen?.();});
  const renderServing=(items)=>{const root=q('[data-screen-serving]');root.replaceChildren();if(!items.length){root.append(text('div','Please wait for your ticket number to be called.','patient-screen-empty'));return;}items.forEach(item=>{const card=document.createElement('article');card.className='patient-serving-card';card.append(text('strong',item.queue_no),text('span',item.destination));root.append(card);});};
  const renderTickets=(selector,items,emptyText,extraClass='')=>{const root=q(selector);root.replaceChildren();if(!items.length){root.append(text('div',emptyText,'patient-screen-small-empty'));return;}items.forEach(item=>root.append(text('span',item.queue_no,`patient-ticket ${extraClass||item.source_type}`.trim())));};
  const render=(data)=>{const nextServing=new Set(data.serving.map(item=>item.queue_no+'|'+item.status));const hasNew=[...nextServing].some(key=>!knownServing.has(key));renderServing(data.serving);renderTickets('[data-screen-waiting-dental]',data.waiting_dental,'No tickets waiting for dental care.');renderTickets('[data-screen-waiting-cashier]',data.waiting_cashier,'No tickets waiting for the cashier.','cashier-ticket');q('[data-count-dental]').textContent=data.counts.waiting_dental;q('[data-count-cashier]').textContent=data.counts.waiting_cashier;q('[data-count-treatment]').textContent=data.counts.in_treatment;q('[data-screen-date]').textContent=data.date_label;if(hasNew)beep();knownServing=nextServing;};
  const refresh=async()=>{const status=q('[data-screen-status]');try{const url=new URL(feedUrl);url.searchParams.set('_',Date.now());const response=await fetch(url,{headers:{Accept:'application/json'},cache:'no-store'});if(!response.ok)throw new Error('refresh failed');const data=await response.json();render(data);status.textContent='Live';document.body.classList.remove('screen-offline');}catch(e){status.textContent='Reconnecting';document.body.classList.add('screen-offline');}};
  const updateClock=()=>{const now=new Date();q('[data-screen-clock]').textContent=now.toLocaleTimeString([],{hour:'numeric',minute:'2-digit',second:'2-digit'});};
  updateClock();setInterval(updateClock,1000);setInterval(refresh,3000);document.addEventListener('visibilitychange',()=>{if(!document.hidden)refresh();});
})();
</script>
</body>
</html>
