<?php
session_start();
include 'db.php';

if (!isset($_SESSION['admin_id'])) { header("Location: admin_login.php"); exit(); }
$admin_username = isset($_SESSION['admin_username']) ? $_SESSION['admin_username'] : 'أدمن';
if ($admin_username === 'alawael0') { session_unset(); session_destroy(); header("Location: admin_login.php"); exit(); }

function h($s){ return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); }
function json_out($arr, $code=200){
  http_response_code($code);
  header("Content-Type: application/json; charset=utf-8");
  echo json_encode($arr, JSON_UNESCAPED_UNICODE);
  exit();
}

mysqli_set_charset($conn, "utf8mb4");

/* ==========================================================
   ✅ AJAX: جلب كل بصمات الطلاب (بدون مرحلة/شعبة)
   ========================================================== */
if (isset($_GET['ajax']) && $_GET['ajax'] === 'faces_all') {

    $sql = "
      SELECT s.id, s.name, s.stage, s.class, sf.descriptors
      FROM students s
      INNER JOIN student_faces sf ON sf.student_id = s.id
      ORDER BY s.name ASC
    ";
    $res = mysqli_query($conn, $sql);
    $rows = array();
    while ($r = mysqli_fetch_assoc($res)) {
        $rows[] = array(
          "id" => (int)$r["id"],
          "name" => $r["name"],
          "stage" => $r["stage"],
          "class" => $r["class"],
          "descriptors" => $r["descriptors"]
        );
    }
    json_out(array("ok"=>true, "students"=>$rows));
}

/* ==========================================================
   ✅ AJAX: تسجيل حضور/مغادرة (Punch)
   ========================================================== */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'punch') {
    $student_id = isset($_POST['student_id']) ? (int)$_POST['student_id'] : 0;
    $mode       = isset($_POST['mode']) ? trim($_POST['mode']) : 'in'; // in/out
    $conf       = isset($_POST['confidence']) ? (float)$_POST['confidence'] : null;
    $device     = isset($_POST['device_name']) ? trim($_POST['device_name']) : 'Gate-PC';

    if ($student_id <= 0) json_out(array("ok"=>false, "message"=>"student_id required"), 400);
    if ($mode !== 'in' && $mode !== 'out') json_out(array("ok"=>false, "message"=>"invalid mode"), 400);

    $today = date("Y-m-d");
    $now   = date("Y-m-d H:i:s");

    // هل يوجد سجل اليوم؟
    $row_id = 0; $checkin_at = null; $checkout_at = null; $status = null;
    $stmt = mysqli_prepare($conn, "SELECT id, checkin_at, checkout_at, status FROM attendance_daily WHERE student_id=? AND att_date=? LIMIT 1");
    mysqli_stmt_bind_param($stmt, "is", $student_id, $today);
    mysqli_stmt_execute($stmt);
    mysqli_stmt_bind_result($stmt, $row_id, $checkin_at, $checkout_at, $status);
    $has = mysqli_stmt_fetch($stmt);
    mysqli_stmt_close($stmt);

    if ($mode === 'in') {
        if ($has && !empty($checkin_at)) {
            json_out(array("ok"=>true, "message"=>"تم تسجيل الحضور مسبقاً"));
        }

        // سياسة التأخير (عدّلها حسبكم)
        $late_after = "08:15:00";
        $time_now = date("H:i:s");
        $new_status = ($time_now > $late_after) ? "late" : "present";

        if ($has) {
            $stmt = mysqli_prepare($conn, "UPDATE attendance_daily SET checkin_at=?, status=?, method='face', confidence=?, device_name=? WHERE id=?");
            mysqli_stmt_bind_param($stmt, "ssdsi", $now, $new_status, $conf, $device, $row_id);
            mysqli_stmt_execute($stmt);
            mysqli_stmt_close($stmt);
        } else {
            $stmt = mysqli_prepare($conn, "INSERT INTO attendance_daily (student_id, att_date, checkin_at, status, method, confidence, device_name) VALUES (?,?,?,?, 'face', ?, ?)");
            mysqli_stmt_bind_param($stmt, "isssds", $student_id, $today, $now, $new_status, $conf, $device);
            mysqli_stmt_execute($stmt);
            mysqli_stmt_close($stmt);
        }

        json_out(array("ok"=>true, "message"=>"✅ تم تسجيل الحضور", "status"=>$new_status));
    }

    // out
    if (!$has || empty($checkin_at)) {
        json_out(array("ok"=>false, "message"=>"لا يمكن تسجيل المغادرة قبل الحضور"), 400);
    }
    if (!empty($checkout_at)) {
        json_out(array("ok"=>true, "message"=>"تم تسجيل المغادرة مسبقاً"));
    }

    $stmt = mysqli_prepare($conn, "UPDATE attendance_daily SET checkout_at=?, method='face', confidence=?, device_name=? WHERE id=?");
    mysqli_stmt_bind_param($stmt, "sdsi", $now, $conf, $device, $row_id);
    mysqli_stmt_execute($stmt);
    mysqli_stmt_close($stmt);

    json_out(array("ok"=>true, "message"=>"✅ تم تسجيل المغادرة"));
}
?>
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<title>✅ بوابة الحضور بالوجه | ثانوية الأوائل الأهلية للبنين</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;600;700&display=swap" rel="stylesheet">
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{
  font-family:'Tajawal',sans-serif;
  min-height:100vh;
  background:radial-gradient(circle at 20% 20%,#1a1f3b,#0b0d18 80%);
  color:#fff; overflow-x:hidden;
}
body::before{
  content:""; position:fixed; top:-50%; left:-50%; width:200%; height:200%;
  background:
    radial-gradient(circle at 30% 30%,rgba(0,255,255,0.2),transparent 70%),
    radial-gradient(circle at 70% 70%,rgba(255,215,0,0.2),transparent 80%),
    radial-gradient(circle at 50% 100%,rgba(138,43,226,0.15),transparent 60%);
  animation:nebula 25s linear infinite alternate; filter:blur(90px); z-index:-1;
}
@keyframes nebula{0%{transform:rotate(0deg) scale(1)}100%{transform:rotate(360deg) scale(1.2)}}
header{
  display:flex; align-items:center; justify-content:space-between;
  padding:18px 25px; background:rgba(255,255,255,0.07);
  border-bottom:1px solid rgba(255,255,255,0.12);
  backdrop-filter:blur(10px);
  box-shadow:0 2px 12px rgba(0,255,255,0.1);
  position:sticky; top:0; z-index:10;
}
header .left{display:flex;align-items:center;gap:12px}
header img{height:45px;border-radius:50%;box-shadow:0 0 10px rgba(0,255,255,0.3)}
header h1{font-size:18px;font-weight:700;margin:0}
header .user{font-size:13px;color:#0ff;opacity:0.85}
header .btn{
  background:linear-gradient(90deg,#00e6ff,#007bff);
  color:#fff;padding:9px 18px;border-radius:10px;
  text-decoration:none;font-weight:bold;transition:0.3s; display:inline-block;
}
header .btn:hover{transform:scale(1.05);box-shadow:0 0 15px rgba(0,255,255,0.4)}
.container{max-width:1200px;margin:20px auto 60px;padding:0 20px}
.hero{text-align:center;margin:24px 0 12px}
.hero h2{font-size:26px;color:#00e6ff;text-shadow:0 0 15px rgba(0,255,255,0.4)}
.hero p{color:#ddd;margin-top:8px;line-height:1.7}
.panel{
  background:rgba(255,255,255,0.08);
  border:1px solid rgba(255,255,255,0.12);
  border-radius:22px; padding:16px; box-shadow:0 0 20px rgba(0,255,255,0.08);
}
.row{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.btn2{
  background:linear-gradient(90deg,#00e6ff,#007bff);
  border:none; color:#fff; padding:10px 14px;
  border-radius:12px; font-weight:700; cursor:pointer; transition:.2s;
}
.btn2:hover{transform:scale(1.03);box-shadow:0 0 15px rgba(0,255,255,0.35)}
.btnGhost{
  background:rgba(255,255,255,0.10);
  border:1px solid rgba(255,255,255,0.15);
  color:#fff; padding:10px 14px; border-radius:12px; font-weight:700; cursor:pointer;
}
.grid{display:grid;grid-template-columns: 1.15fr 0.85fr;gap:14px;margin-top:14px}
@media(max-width:900px){.grid{grid-template-columns:1fr}}
.card{
  background:rgba(255,255,255,0.08);
  border:1px solid rgba(255,255,255,0.12);
  border-radius:22px; padding:14px;
  box-shadow:0 0 18px rgba(0,255,255,0.06);
}
.videoWrap{position:relative}
video{width:100%; border-radius:18px; border:1px solid rgba(255,255,255,0.15); background:#000; max-height:440px}
.overlay{position:absolute; inset:0; pointer-events:none;}
.modeWrap{display:flex;gap:10px;flex-wrap:wrap;margin-top:10px}
.modeBtn{
  flex:1; min-width:160px;
  padding:12px 14px; border-radius:14px;
  font-weight:800; cursor:pointer; border:1px solid rgba(255,255,255,0.15);
  background:rgba(255,255,255,0.08); color:#fff;
}
.modeBtn.active{background:linear-gradient(90deg,#00e6ff,#007bff); border:none}
.log{max-height:420px; overflow:auto; padding-right:6px;}
.item{
  padding:12px; border-radius:16px;
  border:1px solid rgba(255,255,255,0.12);
  background:rgba(0,0,0,0.18);
  margin-bottom:10px;
}
.item b{color:#00e6ff}
.small{color:#ccc;font-size:12px;margin-top:6px;line-height:1.6}
.statusLine{margin-top:10px;color:#00e6ff;font-weight:800}
.hint{color:#ccc;font-size:13px;line-height:1.7;margin-top:10px}
.kpi{margin-top:8px;color:#fff;opacity:.9;font-size:13px}
</style>
</head>
<body>

<header>
  <div class="left">
    <img src="logo.png" alt="logo">
    <div>
      <h1>بوابة الحضور بالوجه</h1>
      <div class="user">مرحباً، <?php echo h($admin_username); ?></div>
    </div>
  </div>
  <div style="display:flex; gap:10px; flex-wrap:wrap;">
    <a href="admin_dashboard.php" class="btn">لوحة التحكم</a>
    <a href="admin_logout.php" class="btn">تسجيل خروج</a>
  </div>
</header>

<div class="container">
  <div class="hero">
    <h2>✅ حضور/مغادرة سريع بالكامرة</h2>
    <p>لا تحتاج اختيار مرحلة أو شعبة — مرّر الطالب أمام الكامرة وسيتم التعرف والتسجيل فوراً.</p>
  </div>

  <div class="panel">
    <div class="row">
      <button type="button" class="btn2" onclick="initGate()">تشغيل البوابة</button>
      <button type="button" class="btnGhost" onclick="stopGate()">إيقاف</button>
      <a class="btnGhost" href="admin_attendance_manage.php">إدارة حضور اليوم</a>
    </div>

    <div class="grid">
      <div class="card">
        <div class="videoWrap">
          <video id="video" autoplay muted playsinline></video>
          <canvas id="overlay" class="overlay"></canvas>
        </div>

        <div class="modeWrap">
          <button type="button" class="modeBtn active" id="btnIn" onclick="setMode('in')">✅ وضع حضور</button>
          <button type="button" class="modeBtn" id="btnOut" onclick="setMode('out')">🚪 وضع مغادرة</button>
        </div>

        <div class="statusLine" id="statusLine">جاهز…</div>
        <div class="kpi" id="kpiLine"></div>
        <div class="hint">
          أسرع أداء: إضاءة جيدة + وجه واضح + الطالب يثبت 0.5 ثانية.
        </div>
      </div>

      <div class="card">
        <h3 style="margin-bottom:10px;">🧾 سجل العمليات</h3>
        <div class="log" id="log"></div>
      </div>
    </div>
  </div>
</div>

<script src="https://unpkg.com/face-api.js@0.22.2/dist/face-api.min.js"></script>
<script>
const MODEL_URL = './face_models';

let stream = null;
let running = false;
let mode = 'in';

let faceMatcher = null;
let descriptorsReady = false;

let idName = {};   // id => name
let idStage = {};  // id => stage
let idClass = {};  // id => class

let lastPunch = {};
let armed = true;
let noFaceFrames = 0;

let modelsLoaded = false;
let modelsPromise = null;

// ====== ✅ صوت نجاح (بدون ملفات) ======
let audioCtx = null;
function primeAudio(){
  try{
    if(!audioCtx){
      audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    }
    if(audioCtx.state === 'suspended'){
      audioCtx.resume();
    }
  }catch(e){}
}
function beep(freq, ms, gain){
  try{
    if(!audioCtx) return;
    const o = audioCtx.createOscillator();
    const g = audioCtx.createGain();
    o.type = 'sine';
    o.frequency.value = freq;
    g.gain.value = gain || 0.06;
    o.connect(g);
    g.connect(audioCtx.destination);
    o.start();
    setTimeout(()=>{ try{o.stop();}catch(e){} }, ms);
  }catch(e){}
}
function playSuccessSound(){
  // نغمة نجاح لطيفة: beep-beep
  beep(880, 90, 0.07);
  setTimeout(()=>beep(1320, 110, 0.07), 110);
}
function playErrorSound(){
  beep(220, 160, 0.08);
}

function uiStatus(t){ document.getElementById('statusLine').textContent = t; }
function uiKpi(t){ document.getElementById('kpiLine').textContent = t || ''; }

function setMode(m){
  mode = m;
  document.getElementById('btnIn').classList.toggle('active', m==='in');
  document.getElementById('btnOut').classList.toggle('active', m==='out');
}

function addLog(name, msg, extra){
  const log = document.getElementById('log');
  const div = document.createElement('div');
  div.className = 'item';
  const now = new Date();
  const ex = extra ? `<div class="small">${extra}</div>` : '';
  div.innerHTML = `<b>${name}</b>${ex}<div class="small">${msg}<br>⏱ ${now.toLocaleString('ar-IQ')}</div>`;
  log.prepend(div);
}

function loadModelsOnce(silent){
  if(modelsLoaded) { if(!silent) uiStatus('✅ النماذج جاهزة'); return Promise.resolve(true); }
  if(modelsPromise) return modelsPromise;

  if(!silent) uiStatus('جاري تحميل النماذج…');
  modelsPromise = Promise.all([
    faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL),
    faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL),
    faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URL)
  ]).then(async ()=>{
    try{
      if(faceapi.tf && faceapi.tf.setBackend){
        await faceapi.tf.setBackend('webgl').catch(()=>{});
        await faceapi.tf.ready().catch(()=>{});
      }
    }catch(e){}
    modelsLoaded = true;
    if(!silent) uiStatus('✅ تم تحميل النماذج');
    return true;
  }).catch((e)=>{
    console.log('MODEL LOAD ERROR =>', e);
    modelsPromise = null;
    if(!silent) uiStatus('❌ فشل تحميل النماذج');
    throw e;
  });

  return modelsPromise;
}

async function startCamera(){
  const video = document.getElementById('video');
  stream = await navigator.mediaDevices.getUserMedia({
    video: { facingMode: 'user', width:{ideal:640}, height:{ideal:480}, frameRate:{ideal:30} },
    audio:false
  });
  video.srcObject = stream;
  await new Promise(r => video.onloadedmetadata = r);
  try{ await video.play(); }catch(e){}

  const overlay = document.getElementById('overlay');
  overlay.width = video.videoWidth || 640;
  overlay.height = video.videoHeight || 480;
}

function stopCamera(){
  try{
    if(stream){
      stream.getTracks().forEach(t=>t.stop());
      stream = null;
    }
  }catch(e){}
}

async function loadDescriptorsOnce(silent){
  if(descriptorsReady && faceMatcher) { if(!silent) uiStatus('✅ البصمات جاهزة'); return true; }

  if(!silent) uiStatus('جاري تحميل بصمات كل الطلاب…');
  const url = `admin_attendance_gate.php?ajax=faces_all`;

  const res = await fetch(url, { cache: 'no-store' });
  const data = await res.json();
  if(!data.ok){ if(!silent) uiStatus('❌ فشل تحميل البصمات'); return false; }

  const labeled = [];
  let used = 0;

  idName = {}; idStage = {}; idClass = {};

  data.students.forEach(s=>{
    try{
      const list = JSON.parse(s.descriptors);
      const descs = [];
      if(Array.isArray(list)){
        // ✅ نخلي 3 بصمات فقط لكل طالب لسرعة أعلى
        for(let i=0;i<list.length && descs.length<3;i++){
          const d = list[i];
          if(Array.isArray(d) && d.length >= 64){
            descs.push(new Float32Array(d));
          }
        }
      }
      if(descs.length){
        const id = String(s.id);
        idName[id] = s.name;
        idStage[id] = s.stage || '';
        idClass[id] = s.class || '';
        labeled.push(new faceapi.LabeledFaceDescriptors(id, descs));
        used++;
      }
    }catch(e){}
  });

  if(!labeled.length){
    if(!silent) uiStatus('⚠️ لا توجد بصمات مسجلة. اذهب لصفحة تسجيل البصمات أولاً.');
    return false;
  }

  // ✅ العتبة (أقل = أدق)
  faceMatcher = new faceapi.FaceMatcher(labeled, 0.48);
  descriptorsReady = true;

  if(!silent){
    uiStatus('✅ جاهز… مرّر الطلاب');
    uiKpi('عدد الطلاب المحمّلين ببصمة: ' + used);
  }
  return true;
}

window.addEventListener('load', () => {
  try{ loadModelsOnce(true); }catch(e){}
});

async function initGate(){
  if(running) return;

  // ✅ مهم: تهيئة الصوت لازم تكون بعد ضغط زر (حتى لا يمنعه المتصفح)
  primeAudio();

  try{
    await loadModelsOnce(false);
    const ok = await loadDescriptorsOnce(false);
    if(!ok) return;

    await startCamera();

    running = true;
    armed = true;
    noFaceFrames = 0;

    uiStatus('✅ البوابة تعمل…');
    detectLoopFast();
  }catch(e){
    console.log(e);
    uiStatus('❌ فشل تشغيل البوابة (كامرة/نماذج)');
    playErrorSound();
  }
}

function stopGate(){
  running = false;
  stopCamera();
  uiStatus('تم الإيقاف');
}

async function punch(student_id, confidence){
  const now = Date.now();
  if(lastPunch[student_id] && (now - lastPunch[student_id]) < 8000){
    return;
  }
  lastPunch[student_id] = now;

  const form = new FormData();
  form.append('action','punch');
  form.append('student_id', student_id);
  form.append('mode', mode);
  form.append('confidence', confidence || '');
  form.append('device_name', 'Gate-PC');

  const res = await fetch('admin_attendance_gate.php', { method:'POST', body: form });
  const data = await res.json();

  const id = String(student_id);
  const name = idName[id] || ('طالب #' + id);
  const extra = (idStage[id] || idClass[id]) ? ('المرحلة: ' + (idStage[id]||'-') + ' — الشعبة: ' + (idClass[id]||'-')) : '';

  if(data.ok){
    addLog(name, data.message + (data.status ? (' — الحالة: ' + data.status) : ''), extra);

    // ✅ صوت نجاح بعد أي OK (حتى لو "مسبقاً")
    playSuccessSound();
  }else{
    addLog(name, '❌ ' + data.message, extra);
    playErrorSound();
  }
}

/* =========================================================
   ✅ التعرف السريع جداً:
   - detect سريع
   - heavy (descriptor) مرة واحدة عند ثبات الوجه
   - بعد التسجيل: ننتظر خروج الوجه حتى ما يعيد
   ========================================================= */
async function detectLoopFast(){
  const video = document.getElementById('video');
  const overlay = document.getElementById('overlay');
  const ctx = overlay.getContext('2d');

  const FAST_OPT  = new faceapi.TinyFaceDetectorOptions({ inputSize: 160, scoreThreshold: 0.45 });
  const HEAVY_OPT = new faceapi.TinyFaceDetectorOptions({ inputSize: 224, scoreThreshold: 0.5 });

  let prevBox = null;
  let stableHits = 0;
  let heavyLockUntil = 0;

  while(running){
    if((overlay.width !== (video.videoWidth||overlay.width)) || (overlay.height !== (video.videoHeight||overlay.height))){
      overlay.width = video.videoWidth || 640;
      overlay.height = video.videoHeight || 480;
    }

    ctx.clearRect(0,0,overlay.width,overlay.height);

    const detFast = await faceapi.detectSingleFace(video, FAST_OPT);

    if(!detFast){
      noFaceFrames++;
      prevBox = null;
      stableHits = 0;

      if(noFaceFrames >= 10) armed = true;

      uiStatus('ضع الوجه أمام الكامرة…');
      await new Promise(r=>setTimeout(r, 120));
      continue;
    }

    noFaceFrames = 0;
    const box = detFast.box;

    ctx.strokeStyle = 'rgba(0,230,255,0.9)';
    ctx.lineWidth = 3;
    ctx.strokeRect(box.x, box.y, box.width, box.height);

    const bigEnough = (box.width >= 90 && box.height >= 90);
    if(!bigEnough){
      prevBox = null;
      stableHits = 0;
      uiStatus('قرّب الوجه قليلاً…');
      await new Promise(r=>setTimeout(r, 120));
      continue;
    }

    let stable = false;
    if(prevBox){
      const cx1 = prevBox.x + prevBox.width/2;
      const cy1 = prevBox.y + prevBox.height/2;
      const cx2 = box.x + box.width/2;
      const cy2 = box.y + box.height/2;
      const dist = Math.sqrt((cx1-cx2)*(cx1-cx2) + (cy1-cy2)*(cy1-cy2));
      stable = (dist < 18);
    }
    prevBox = box;

    if(stable) stableHits++; else stableHits = 1;

    if(!armed){
      uiStatus('✅ تم التسجيل… مرّر الطالب التالي');
      await new Promise(r=>setTimeout(r, 120));
      continue;
    }

    // ✅ ثبات مرتين فقط = سريع
    if(stableHits >= 2){
      const now = Date.now();
      if(now < heavyLockUntil){
        await new Promise(r=>setTimeout(r, 90));
        continue;
      }
      heavyLockUntil = now + 650;

      uiStatus('🧠 جارِ التعرف…');

      const det = await faceapi
        .detectSingleFace(video, HEAVY_OPT)
        .withFaceLandmarks()
        .withFaceDescriptor();

      if(det && faceMatcher){
        const best = faceMatcher.findBestMatch(det.descriptor);
        const label = best.label;     // هنا label = student_id
        const dist = best.distance;

        ctx.fillStyle = 'rgba(0,0,0,0.55)';
        ctx.fillRect(box.x, Math.max(0, box.y-32), box.width, 28);
        ctx.fillStyle = '#00e6ff';
        ctx.font = 'bold 16px Tajawal, sans-serif';
        ctx.fillText(label === 'unknown' ? 'غير معروف' : (idName[label] || label), box.x+8, Math.max(18, box.y-12));

        if(label !== 'unknown'){
          const student_id = parseInt(label,10);
          const confidence = Math.max(0, Math.min(1, (1 - dist)));

          uiStatus('✅ تم التعرف: ' + (idName[label] || ('طالب #' + label)));

          await punch(student_id, confidence);

          armed = false;
          stableHits = 0;
          prevBox = null;
        }else{
          uiStatus('غير معروف…');
          stableHits = 0;
        }
      }else{
        uiStatus('لم يتم التقاط وجه واضح…');
        stableHits = 0;
      }
    }else{
      uiStatus('✅ ثبّت وجهك لحظة…');
    }

    await new Promise(r=>setTimeout(r, 120));
  }
}
</script>

</body>
</html>
