<?= $this->extend('layouts/main') ?>
<?= $this->section('content') ?>
<?php $CSRF = csrf_hash(); ?>

<style>
body { background:#0f172a }
.scan-wrap { max-width:480px; margin:0 auto; padding:12px }
.scan-header { text-align:center; color:#fff; margin-bottom:16px }
.scan-header h4 { font-weight:800; margin:0 }
.scan-header small { color:#94a3b8; font-size:12px }

/* Video area */
#reader { min-height:250px; border-radius:14px; overflow:hidden; background:#1e293b; position:relative }
#reader video { width:100%!important; height:auto!important; min-height:250px; display:block; object-fit:cover; border-radius:14px }
/* Overlay target box */
.scan-overlay { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
    width:200px; height:200px; border:3px solid rgba(99,102,241,.8); border-radius:12px;
    box-shadow:0 0 0 2000px rgba(0,0,0,.35); pointer-events:none; z-index:5 }
.scan-overlay::before,.scan-overlay::after {
    content:''; position:absolute; width:24px; height:24px; border-color:#6366F1; border-style:solid }
.scan-overlay::before { top:-3px; left:-3px; border-width:4px 0 0 4px; border-radius:4px 0 0 4px }
.scan-overlay::after  { bottom:-3px; right:-3px; border-width:0 4px 4px 0; border-radius:0 4px 4px 0 }

/* Counter bar */
.counter-bar { display:flex; align-items:center; justify-content:space-between;
    background:#1e293b; border-radius:10px; padding:10px 14px; margin:10px 0; color:#e2e8f0 }
.counter-bar .cnt { font-size:1.6rem; font-weight:800; color:#6366F1 }
.counter-bar small { font-size:11px; color:#64748b }

/* Hasil scan */
#scanResult { border-radius:12px; padding:14px; margin:10px 0; display:none;
    transition:all .2s; font-size:13px }
.res-ok   { background:#064E3B; border:1px solid #10B981; color:#D1FAE5 }
.res-dup  { background:#451A03; border:1px solid #F59E0B; color:#FEF3C7 }
.res-err  { background:#450A0A; border:1px solid #EF4444; color:#FEE2E2 }
.res-name { font-size:1.1rem; font-weight:700; margin-bottom:2px }
.res-meta { font-size:11px; opacity:.75 }

/* Kontrol */
.ctrl-bar { display:flex; gap:8px; margin-top:8px }
.ctrl-btn { flex:1; padding:10px; border-radius:8px; border:1px solid #334155;
    background:#1e293b; color:#94a3b8; font-size:12px; font-weight:600;
    cursor:pointer; transition:all .15s }
.ctrl-btn:hover { background:#334155; color:#e2e8f0 }
.ctrl-btn.active { background:#4f46e5; border-color:#4f46e5; color:#fff }

/* Status jam */
.hour-badge { text-align:center; font-size:11px; padding:4px 12px; border-radius:20px;
    margin-bottom:8px; display:inline-block }
.hour-ok  { background:#064E3B; color:#6EE7B7 }
.hour-off { background:#450A0A; color:#FCA5A5 }

/* Log terakhir */
.log-list { list-style:none; padding:0; margin:10px 0 0 }
.log-list li { display:flex; justify-content:space-between; align-items:center;
    padding:6px 10px; background:#1e293b; border-radius:7px; margin-bottom:4px;
    font-size:11px; color:#94a3b8 }
.log-list li span.name { color:#e2e8f0; font-weight:600 }

/* Input manual (scanner USB) */
#manualInput { background:#1e293b; border:1px solid #334155; color:#e2e8f0;
    border-radius:8px; padding:8px 12px; width:100%; font-size:13px; margin-top:8px }
#manualInput:focus { outline:none; border-color:#6366F1 }

.camera-fallback { display:none; padding:10px; background:#450A0A; border:1px solid #EF4444;
    border-radius:10px; color:#FCA5A5; font-size:12px; text-align:center; margin-bottom:8px }
.camera-fallback i { font-size:1.2rem; display:block; margin-bottom:4px }
.camera-retry { margin-top:8px; padding:7px 14px; border:1px solid #FCA5A5; border-radius:7px;
    background:transparent; color:#FEE2E2; font-size:12px; cursor:pointer }

/* ── OVERLAY AKTIVASI ── */
#overlayAktif {
    position:fixed; inset:0; background:rgba(15,23,42,.95);
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    z-index:9999; gap:20px;
}
#overlayAktif h2 { color:#fff; font-weight:800; font-size:1.8rem; margin:0; text-align:center }
#overlayAktif p  { color:#94a3b8; font-size:14px; margin:0; text-align:center; line-height:1.6 }
#btnMulai {
    padding:20px 56px; font-size:1.4rem; font-weight:800;
    background:#4f46e5; color:#fff; border:none; border-radius:16px;
    cursor:pointer; box-shadow:0 0 40px rgba(99,102,241,.6);
    transition:transform .1s, box-shadow .1s;
}
#btnMulai:hover { box-shadow:0 0 56px rgba(99,102,241,.8) }
#btnMulai:active { transform:scale(.97) }
</style>

<!-- OVERLAY AKTIVASI — muncul sekali saat pertama buka halaman -->
<div id="overlayAktif">
    <i class="bi bi-volume-up-fill" style="font-size:4rem;color:#6366F1"></i>
    <h2>Sistem Absensi QR</h2>
    <p>Tekan tombol di bawah untuk mengaktifkan<br>kamera dan suara notifikasi</p>
    <button id="btnMulai" onclick="aktivasiSistem()">
        <i class="bi bi-play-circle-fill me-2"></i>Mulai Sistem
    </button>
    <small style="color:#475569">Wajib diklik sekali setiap kali membuka halaman ini</small>
</div>

<!-- KONTEN UTAMA -->
<div class="scan-wrap">
    <div class="scan-header">
        <h4><i class="bi bi-qr-code-scan me-2"></i>Absensi QR Code</h4>
        <small>Scan kartu pelajar untuk mencatat kehadiran</small>
    </div>

    <!-- STATUS JAM -->
    <div class="text-center mb-2">
        <span class="hour-badge" id="hourBadge">Memeriksa jam...</span>
    </div>

    <!-- VIDEO SCAN -->
    <div style="position:relative">
        <div id="reader"></div>
        <div class="scan-overlay"></div>
    </div>

    <!-- Fallback kamera gagal -->
    <div class="camera-fallback" id="cameraFallback">
        <i class="bi bi-camera-video-off-fill"></i>
        <span id="cameraFallbackMsg">Kamera tidak tersedia</span>
        <br>
        <button type="button" class="camera-retry" onclick="retryScanner()">
            <i class="bi bi-arrow-clockwise me-1"></i>Coba Lagi
        </button>
    </div>

    <!-- Input manual (scanner USB atau ketik NISN) -->
    <input type="text" id="manualInput" placeholder="Ketik nama atau NISN siswa..."
           autocomplete="off" list="studentList">

    <datalist id="studentList">
        <?php foreach ($students as $std): ?>
        <option value="<?= esc($std['nisn']) ?>"><?= esc($std['full_name'] . ' (' . ($std['grade_name'] ?? '') . ' ' . esc($std['classroom_name'] ?? '') . ')') ?></option>
        <?php endforeach; ?>
    </datalist>

    <!-- HASIL SCAN -->
    <div id="scanResult"></div>

    <!-- COUNTER -->
    <div class="counter-bar">
        <div>
            <div class="cnt" id="countToday"><?= $count_today ?></div>
            <small>Siswa hadir hari ini</small>
        </div>
        <div style="text-align:right">
            <div style="font-size:12px;color:#e2e8f0;font-weight:600"><?= date('d M Y') ?></div>
            <small id="clockDisplay"></small>
        </div>
    </div>

    <!-- KONTROL -->
    <div class="ctrl-bar">
        <button class="ctrl-btn" id="btnPause" onclick="togglePause()">
            <i class="bi bi-pause-fill me-1"></i>Pause
        </button>
        <a href="/attendance/qr-report?date=<?= $today ?>" class="ctrl-btn text-center text-decoration-none">
            <i class="bi bi-list-ul me-1"></i>Rekap Hari Ini
        </a>
        <a href="/attendance" class="ctrl-btn text-center text-decoration-none">
            <i class="bi bi-arrow-left me-1"></i>Absensi BK
        </a>
    </div>

    <!-- LOG 5 SCAN TERAKHIR -->
    <div style="color:#64748b;font-size:11px;margin-top:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em">
        <i class="bi bi-clock-history me-1"></i>Scan Terakhir
    </div>
    <ul class="log-list" id="recentLog"></ul>
</div>

<?= $this->endSection() ?>
<?= $this->section('scripts') ?>
<script src="https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js"></script>
<script>
'use strict';
const CSRF       = '<?= $CSRF ?>';
const SCAN_START = '<?= $scan_start ?>';
const SCAN_END   = '<?= $scan_end ?>';

let isPaused     = false;
let isProcessing = false;
let scanner      = null;
let cameraError  = null;
const recentLog  = [];
const manualInput = document.getElementById('manualInput');

// ── JAM ──────────────────────────────────────────────────────
function clockTick() {
    const now  = new Date();
    const hhmm = now.toTimeString().substring(0, 5);
    document.getElementById('clockDisplay').textContent = now.toLocaleTimeString('id-ID');
    const badge = document.getElementById('hourBadge');
    if (hhmm >= SCAN_START && hhmm <= SCAN_END) {
        badge.textContent = `✅ Absensi aktif ${SCAN_START}–${SCAN_END}`;
        badge.className   = 'hour-badge hour-ok';
    } else {
        badge.textContent = `⛔ Di luar jam absensi (${SCAN_START}–${SCAN_END})`;
        badge.className   = 'hour-badge hour-off';
    }
}
setInterval(clockTick, 1000);
clockTick();

// ── AKTIVASI SISTEM (klik tombol pertama kali) ───────────────
// Wajib dipanggil dari user gesture agar browser izinkan speech + audio
function aktivasiSistem() {
    // Wake up speech engine
    const u = new SpeechSynthesisUtterance('Sistem siap');
    u.lang   = 'id-ID';
    u.volume = 1.0;
    u.rate   = 1.0;
    window.speechSynthesis.speak(u);

    // Sembunyikan overlay
    document.getElementById('overlayAktif').style.display = 'none';

    // Mulai kamera
    startScanner();

    // Fokus ke input (untuk scanner USB)
    manualInput.focus();
}

// ── SCANNER KAMERA ───────────────────────────────────────────
function startScanner() {
    if (typeof Html5Qrcode === 'undefined') {
        showCameraFallback('Library scanner gagal dimuat. Periksa koneksi internet lalu coba lagi.');
        return;
    }

    if (!window.isSecureContext && location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {
        showCameraFallback('Kamera memerlukan HTTPS. Buka aplikasi melalui alamat https://.');
        return;
    }

    document.getElementById('reader').style.display = 'block';
    document.getElementById('cameraFallback').style.display = 'none';
    cameraError = null;
    scanner = new Html5Qrcode('reader');

    const cameraConfigs = [
        { facingMode: 'environment', width: { ideal: 1280 } },
        { facingMode: { ideal: 'environment' }, width: { ideal: 1280 } },
        { width: { ideal: 1280 } },
    ];

    const scanConfig = { fps: 15, qrbox: { width: 250, height: 250 } };

    let configIndex = 0;

    function tryNextCamera() {
        if (configIndex >= cameraConfigs.length) {
            showCameraFallback(cameraError || 'Kamera tidak tersedia. Gunakan input manual atau scanner USB.');
            return;
        }

        const cfg = cameraConfigs[configIndex];
        scanner.start(cfg, scanConfig,
            (decodedText) => {
                if (isPaused || isProcessing) return;
                processNisn(decodedText.trim());
            },
            () => {} // error scan diabaikan
        ).catch(err => {
            cameraError = cameraErrorMessage(err);
            configIndex++;
            tryNextCamera();
        });
    }

    tryNextCamera();
}

function cameraErrorMessage(error) {
    const name = error && error.name ? error.name : '';
    if (name === 'NotAllowedError' || name === 'PermissionDeniedError') {
        return 'Izin kamera ditolak. Izinkan kamera di pengaturan browser, lalu tekan Coba Lagi.';
    }
    if (name === 'NotFoundError' || name === 'DevicesNotFoundError') {
        return 'Kamera tidak ditemukan pada perangkat ini.';
    }
    if (name === 'NotReadableError' || name === 'TrackStartError') {
        return 'Kamera sedang digunakan aplikasi lain. Tutup aplikasi tersebut, lalu coba lagi.';
    }
    if (name === 'OverconstrainedError') {
        return 'Konfigurasi kamera tidak didukung perangkat ini.';
    }
    return 'Kamera gagal dibuka. Pastikan izin kamera aktif dan halaman menggunakan HTTPS.';
}

function showCameraFallback(message) {
    document.getElementById('reader').style.display = 'none';
    document.getElementById('cameraFallback').style.display = 'block';
    document.getElementById('cameraFallbackMsg').textContent = message;
}

function retryScanner() {
    if (scanner) {
        scanner.stop().catch(() => {}).finally(() => startScanner());
    } else {
        startScanner();
    }
}

// ── INPUT MANUAL (Scanner USB / keyboard) ────────────────────
manualInput.addEventListener('keydown', function(e) {
    if (e.key === 'Enter') {
        const val = this.value.trim();
        if (val) { processNisn(val); this.value = ''; }
    }
});
// Jaga fokus di input agar scanner USB langsung terbaca
document.addEventListener('click', (e) => {
    if (e.target.id !== 'btnMulai') manualInput.focus();
});

// ── PROSES NISN ──────────────────────────────────────────────
async function processNisn(nisn) {
    if (isProcessing) return;
    isProcessing = true;

    showResult('info', '⏳ Memproses...', nisn);

    try {
        const res  = await fetch('/attendance/qr-process', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': CSRF,
            },
            body: JSON.stringify({ nisn }),
        });
        const data = await res.json();

        if (data.success) {
            const s = data.student;
            showResult('ok',
                `✅ ${s.full_name}`,
                `${s.classroom || '-'} · NISN: ${s.nisn} · ${s.scan_time}`
            );
            addLog(s.full_name, s.classroom || '-', s.scan_time);
            document.getElementById('countToday').textContent = data.count_today;
            playBeep('ok');
            speak('Hadir');
        } else {
            const type = data.type || 'err';
            if (type === 'duplicate' && data.student) {
                showResult('dup',
                    `⚠️ ${data.student.full_name} — Sudah absen`,
                    'Siswa ini sudah melakukan scan hari ini'
                );
                playBeep('dup');
                speak('Sudah Absen');
            } else {
                showResult('err', '❌ ' + data.message, '');
                playBeep('err');
                speak('Gagal');
            }
        }
    } catch (e) {
        showResult('err', '❌ Error koneksi', e.message);
        playBeep('err');
    }

    // Reset setelah 1.5 detik
    setTimeout(() => {
        document.getElementById('scanResult').style.display = 'none';
        isProcessing = false;
        manualInput.focus();
    }, 1500);
}

// ── UI HELPERS ───────────────────────────────────────────────
function showResult(type, name, meta) {
    const el  = document.getElementById('scanResult');
    const cls = type === 'ok' ? 'res-ok' : type === 'dup' ? 'res-dup' : type === 'info' ? 'res-dup' : 'res-err';
    el.className = cls;
    el.innerHTML = `<div class="res-name">${name}</div><div class="res-meta">${meta}</div>`;
    el.style.display = 'block';
}

function addLog(name, kelas, time) {
    recentLog.unshift({ name, kelas, time });
    if (recentLog.length > 5) recentLog.pop();
    const ul = document.getElementById('recentLog');
    ul.innerHTML = recentLog.map(l =>
        `<li><span class="name">${l.name}</span><span>${l.kelas} · ${l.time}</span></li>`
    ).join('');
}

function togglePause() {
    isPaused = !isPaused;
    const btn = document.getElementById('btnPause');
    if (isPaused) {
        btn.innerHTML = '<i class="bi bi-play-fill me-1"></i>Lanjut';
        btn.classList.add('active');
    } else {
        btn.innerHTML = '<i class="bi bi-pause-fill me-1"></i>Pause';
        btn.classList.remove('active');
        manualInput.focus();
    }
}

// ── AUDIO: Beep via Web Audio API ────────────────────────────
function playBeep(type) {
    try {
        const ctx  = new (window.AudioContext || window.webkitAudioContext)();
        const osc  = ctx.createOscillator();
        const gain = ctx.createGain();
        osc.connect(gain);
        gain.connect(ctx.destination);
        osc.frequency.value = type === 'ok' ? 1000 : type === 'dup' ? 600 : 300;
        osc.type = 'sine';
        gain.gain.setValueAtTime(0.3, ctx.currentTime);
        gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.25);
        osc.start();
        osc.stop(ctx.currentTime + 0.25);
    } catch(e) {}
}

// ── SUARA: Web Speech API ─────────────────────────────────────
// Catatan: speak() hanya berfungsi setelah aktivasiSistem() dipanggil
function speak(text) {
    try {
        window.speechSynthesis.cancel();
        const u  = new SpeechSynthesisUtterance(text);
        u.lang   = 'id-ID';
        u.rate   = 1.1;
        u.pitch  = 1.0;
        u.volume = 1.0;
        window.speechSynthesis.speak(u);
    } catch(e) {}
}
</script>
<?= $this->endSection() ?>
