<?php
/** Facial attendance kiosk — webcam (wired USB) or IP camera (wireless) clock-in / enrol. */
if (session_status() === PHP_SESSION_NONE) session_start();
if (!isset($_SESSION['user_id'])) { header('Location: ../index.php'); exit; }

require_once '../config.php';
requireModule('biometric_attendance');
require_once __DIR__ . '/../includes/biometric_lib.php';

$role = $_SESSION['role'] ?? '';
$mode = ($_GET['mode'] ?? 'clockin') === 'enroll' ? 'enroll' : 'clockin';
if ($mode === 'enroll' && !biometric_can_manage($role)) { header('Location: index.php'); exit; }
$school = getSettingValue('school_name') ?: 'School';
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Face Kiosk — <?php echo htmlspecialchars($school); ?></title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        body{background:#0f172a;color:#fff;min-height:100vh;}
        .kiosk{max-width:560px;margin:0 auto;padding:24px;text-align:center;}
        video,canvas{width:100%;max-width:480px;border-radius:14px;background:#000;}
        .wrap{position:relative;display:inline-block;}
        .wrap canvas{position:absolute;left:0;top:0;}
        #status{min-height:28px;font-size:1.1rem;margin-top:12px;}
        .badge-mode{position:absolute;top:12px;right:12px;}
    </style>
</head>
<body>
<div class="kiosk">
    <span class="badge bg-<?php echo $mode==='enroll'?'warning text-dark':'success'; ?> badge-mode position-static mb-2 d-inline-block">
        <?php echo $mode==='enroll' ? 'ENROL MODE' : 'CLOCK-IN'; ?>
    </span>
    <h3><i class="fas fa-face-viewfinder me-1"></i><?php echo htmlspecialchars($school); ?> — Face <?php echo $mode==='enroll'?'Enrolment':'Attendance'; ?></h3>

    <?php if ($mode === 'enroll'): ?>
    <div class="mb-2">
        <input id="stuSearch" class="form-control form-control-sm d-inline-block" style="max-width:320px" placeholder="Search person to enrol">
        <select id="stuResults" class="form-select form-select-sm mt-1" size="3"></select>
    </div>
    <?php endif; ?>

    <div class="wrap">
        <video id="video" autoplay muted playsinline></video>
        <canvas id="overlay"></canvas>
    </div>
    <div id="status" class="text-info">Loading camera &amp; face model…</div>
    <div class="mt-2">
        <button id="captureBtn" class="btn btn-lg btn-<?php echo $mode==='enroll'?'warning':'success'; ?>" disabled>
            <i class="fas fa-camera me-1"></i><?php echo $mode==='enroll'?'Capture & Enrol':'Clock In'; ?>
        </button>
        <a href="index.php" class="btn btn-lg btn-outline-light ms-2">Exit</a>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/face_mesh.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const MODE = "<?php echo $mode; ?>";
const video = document.getElementById('video');
const overlay = document.getElementById('overlay');
const statusEl = document.getElementById('status');
const captureBtn = document.getElementById('captureBtn');
let latestDescriptor = null, selectedPerson = null, busy = false;
function esc(s){const d=document.createElement('div');d.textContent=s==null?'':s;return d.innerHTML;}

const faceMesh = new FaceMesh({ locateFile: f => `https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/${f}` });
faceMesh.setOptions({ maxNumFaces:1, refineLandmarks:true, minDetectionConfidence:0.5, minTrackingConfidence:0.5 });
faceMesh.onResults(res => {
    const ctx = overlay.getContext('2d');
    overlay.width = video.videoWidth; overlay.height = video.videoHeight;
    ctx.clearRect(0,0,overlay.width,overlay.height);
    if (res.multiFaceLandmarks && res.multiFaceLandmarks.length) {
        const lm = res.multiFaceLandmarks[0];
        latestDescriptor = lm.map(p => ({x:p.x, y:p.y, z:p.z}));
        ctx.fillStyle = 'rgba(34,197,94,0.9)';
        lm.forEach(p => { ctx.beginPath(); ctx.arc(p.x*overlay.width, p.y*overlay.height, 1.1, 0, 6.28); ctx.fill(); });
        if (!busy) { captureBtn.disabled = (MODE==='enroll' && !selectedPerson); statusEl.textContent = 'Face detected — ready.'; statusEl.className='text-success'; }
    } else {
        latestDescriptor = null;
        if (!busy) { captureBtn.disabled = true; statusEl.textContent = 'Position your face in view.'; statusEl.className='text-warning'; }
    }
});

const cam = new Camera(video, { onFrame: async () => { await faceMesh.send({image: video}); }, width:480, height:360 });
cam.start().then(()=>{ statusEl.textContent='Camera ready.'; }).catch(e=>{ statusEl.textContent='Camera error: '+e.message; statusEl.className='text-danger'; });

<?php if ($mode === 'enroll'): ?>
document.getElementById('stuSearch').addEventListener('keyup', e=>{ if(e.key==='Enter'){
    fetch(`ajax/api.php?action=search_persons&q=${encodeURIComponent(e.target.value)}`).then(r=>r.json()).then(d=>{
        document.getElementById('stuResults').innerHTML=d.data.map(p=>`<option value="${p.type}:${p.id}" data-label="${esc(p.label)}">${esc(p.label)}</option>`).join('');
    });
}});
document.getElementById('stuResults').addEventListener('change', function(){ const o=this.selectedOptions[0]; selectedPerson=o?{v:o.value,label:o.dataset.label}:null; });
<?php endif; ?>

captureBtn.addEventListener('click', () => {
    if (!latestDescriptor) { alert('No face detected.'); return; }
    busy = true; captureBtn.disabled = true;
    if (MODE === 'enroll') {
        if (!selectedPerson) { alert('Select a person first.'); busy=false; return; }
        const [type,id] = selectedPerson.v.split(':');
        const fd = new FormData();
        fd.append('action','enroll_face'); fd.append('person_type',type); fd.append('person_id',id);
        fd.append('person_name',selectedPerson.label); fd.append('descriptor', JSON.stringify(latestDescriptor));
        fetch('ajax/api.php',{method:'POST',body:fd}).then(r=>r.json()).then(d=>{
            statusEl.textContent=d.message; statusEl.className=d.success?'text-success':'text-danger'; busy=false;
        });
    } else {
        const fd = new FormData();
        fd.append('action','kiosk_match'); fd.append('descriptor', JSON.stringify(latestDescriptor));
        fetch('ajax/api.php',{method:'POST',body:fd}).then(r=>r.json()).then(d=>{
            statusEl.textContent=d.message; statusEl.className=d.success?'text-success':'text-danger';
            setTimeout(()=>{ busy=false; }, 2500);
        });
    }
});
</script>
</body>
</html>
