<?php
session_start();
require_once '../config/database.php';
require_once '../includes/asistencia_auth.php';

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

$conn = (new Database())->connect();
$userId = (int)$_SESSION['user_id'];
$userRole = (int)($_SESSION['user_role'] ?? 0);
$isAdminAsistencia = $userRole === 1;

function escaneo_get_lector(PDO $conn, $userId)
{
    $stmt = $conn->prepare("SELECT id_lector, alcance, tipo_lector FROM asistencia_lectores WHERE id_personal = ? AND estado = 1 LIMIT 1");
    $stmt->execute([(int)$userId]);
    $lector = $stmt->fetch(PDO::FETCH_ASSOC);
    return $lector ?: null;
}

function escaneo_lector_curso_habilitado(PDO $conn, $idLector, $idCurso)
{
    if ((int)$idLector <= 0 || (int)$idCurso <= 0) {
        return false;
    }
    $stmt = $conn->prepare("SELECT 1 FROM asistencia_lectores_cursos WHERE id_lector = ? AND id_curso = ? AND estado = 1 LIMIT 1");
    $stmt->execute([(int)$idLector, (int)$idCurso]);
    return (bool)$stmt->fetchColumn();
}

function escaneo_usuario_puede_registrar(PDO $conn, $isAdminAsistencia, $lectorInfo, $idCurso)
{
    if ($isAdminAsistencia) {
        return true;
    }
    if (!$lectorInfo || (int)$idCurso <= 0) {
        return false;
    }
    if (($lectorInfo['alcance'] ?? '') === 'GLOBAL') {
        return true;
    }
    if (($lectorInfo['alcance'] ?? '') === 'POR_CURSO') {
        return escaneo_lector_curso_habilitado($conn, (int)$lectorInfo['id_lector'], (int)$idCurso);
    }
    return false;
}

function escaneo_resolver_puntualidad(PDO $conn, $fecha, $horaActual)
{
    $stmt = $conn->prepare("SELECT hora_ingreso, tolerancia_min
        FROM asistencia_horarios_ingreso
        WHERE estado = 1 AND ? BETWEEN fecha_inicio AND fecha_fin
        ORDER BY fecha_inicio DESC, id_horario DESC
        LIMIT 1");
    $stmt->execute([$fecha]);
    $horario = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$horario) {
        return [
            'estado_puntualidad' => null,
            'hora_ingreso_programada' => null,
            'tolerancia_min' => null,
        ];
    }

    $toleranciaMin = max((int)($horario['tolerancia_min'] ?? 0), 0);
    $horaIngreso = (string)$horario['hora_ingreso'];
    $limite = date('H:i:s', strtotime($fecha . ' ' . $horaIngreso . ' +' . $toleranciaMin . ' minutes'));
    $estado = ($horaActual <= $limite) ? 'TEMPRANO' : 'TARDE';

    return [
        'estado_puntualidad' => $estado,
        'hora_ingreso_programada' => $horaIngreso,
        'tolerancia_min' => $toleranciaMin,
    ];
}

$lectorInfo = $isAdminAsistencia ? null : escaneo_get_lector($conn, $userId);
if (!$isAdminAsistencia && !$lectorInfo) {
    http_response_code(403);
    echo '<h3>Acceso denegado</h3><p>Tu usuario no está habilitado para registrar asistencia.</p>';
    exit();
}

// Procesar registro de asistencia (cuando se escanea un QR)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['qr_data'])) {
    header('Content-Type: application/json; charset=utf-8');
    $raw_qr = trim((string)$_POST['qr_data']);
    $id_estudiante = null;

    $qr_data = json_decode($raw_qr, true);
    if (is_array($qr_data) && isset($qr_data['id_estudiante'])) {
        $id_estudiante = (int)$qr_data['id_estudiante'];
    } elseif (preg_match('/^EST:(\d+)$/', $raw_qr, $m)) {
        $id_estudiante = (int)$m[1];
    } elseif (ctype_digit($raw_qr)) {
        $id_estudiante = (int)$raw_qr;
    }

    if ($id_estudiante > 0) {
        $stmtEstInfo = $conn->prepare("SELECT id_curso, nombres, apellido_paterno, apellido_materno FROM estudiantes WHERE id_estudiante = ? LIMIT 1");
        $stmtEstInfo->execute([$id_estudiante]);
        $estudianteInfo = $stmtEstInfo->fetch(PDO::FETCH_ASSOC);

        if (!$estudianteInfo) {
            echo json_encode([
                'success' => false,
                'message' => 'Estudiante no encontrado'
            ]);
            exit();
        }

        $idCursoEscaneado = (int)$estudianteInfo['id_curso'];

        if (!escaneo_usuario_puede_registrar($conn, $isAdminAsistencia, $lectorInfo, $idCursoEscaneado)) {
            echo json_encode([
                'success' => false,
                'message' => 'No tienes permiso para registrar asistencia en este curso.'
            ]);
            exit();
        }

        $hoy = date('Y-m-d');
        $hora_actual = date('H:i:s');
        
        $puntualidad = escaneo_resolver_puntualidad($conn, $hoy, $hora_actual);

        // Registrar asistencia
        $stmt = $conn->prepare("INSERT IGNORE INTO asistencia
            (id_estudiante, fecha, hora_entrada, tipo_registro, estado_puntualidad, hora_ingreso_programada, tolerancia_min)
            VALUES (?, ?, ?, 'QR', ?, ?, ?)");

        if ($stmt->execute([
            $id_estudiante,
            $hoy,
            $hora_actual,
            $puntualidad['estado_puntualidad'],
            $puntualidad['hora_ingreso_programada'],
            $puntualidad['tolerancia_min']
        ])) {
            if ($stmt->rowCount() > 0) {
                echo json_encode([
                    'success' => true,
                    'message' => 'Asistencia registrada correctamente',
                    'id_estudiante' => $id_estudiante,
                    'estudiante' => $estudianteInfo['apellido_paterno'] . ' ' . $estudianteInfo['apellido_materno'] . ', ' . $estudianteInfo['nombres'],
                    'hora' => $hora_actual,
                    'puntualidad' => $puntualidad['estado_puntualidad']
                ]);
            } else {
                $stmtHora = $conn->prepare("SELECT hora_entrada FROM asistencia WHERE id_estudiante = ? AND fecha = ? LIMIT 1");
                $stmtHora->execute([$id_estudiante, $hoy]);
                $horaExistente = (string)$stmtHora->fetchColumn();

                echo json_encode([
                    'success' => false,
                    'message' => 'El estudiante ya registró asistencia hoy' . ($horaExistente !== '' ? ' a las ' . $horaExistente : '')
                ]);
            }
        } else {
            echo json_encode([
                'success' => false,
                'message' => 'Error al registrar la asistencia'
            ]);
        }
    } else {
        echo json_encode([
            'success' => false,
            'message' => 'QR inválido'
        ]);
    }
    exit();
}

// Obtener información del curso
$id_curso = $_GET['id_curso'] ?? null;
$curso_info = null;

if ($id_curso && !escaneo_usuario_puede_registrar($conn, $isAdminAsistencia, $lectorInfo, (int)$id_curso)) {
    http_response_code(403);
    echo '<h3>Acceso denegado</h3><p>No tienes permiso para operar en este curso.</p>';
    exit();
}

if ($id_curso) {
    $stmt_curso = $conn->prepare("SELECT nivel, curso, paralelo FROM cursos WHERE id_curso = ?");
    $stmt_curso->execute([$id_curso]);
    $curso_info = $stmt_curso->fetch(PDO::FETCH_ASSOC);
}

// Obtener asistencia de hoy
$hoy = date('Y-m-d');
$asistencia_hoy = [];
if ($id_curso) {
    $stmt_asist = $conn->prepare("
        SELECT a.hora_entrada, e.nombres, e.apellido_paterno, e.apellido_materno
        FROM asistencia a
        JOIN estudiantes e ON a.id_estudiante = e.id_estudiante
        WHERE a.fecha = ? AND e.id_curso = ?
        ORDER BY a.hora_entrada DESC
    ");
    $stmt_asist->execute([$hoy, $id_curso]);
    $asistencia_hoy = $stmt_asist->fetchAll(PDO::FETCH_ASSOC);
}

$estudiantes_cache = [];
if ($id_curso) {
    $stmt_est_cache = $conn->prepare("SELECT id_estudiante, nombres, apellido_paterno, apellido_materno FROM estudiantes WHERE id_curso = ? ORDER BY apellido_paterno, apellido_materno, nombres");
    $stmt_est_cache->execute([(int)$id_curso]);
    $estudiantes_cache = $stmt_est_cache->fetchAll(PDO::FETCH_ASSOC);
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Escanear Asistencia</title>
    <link rel="stylesheet" href="../css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/remixicon@4.1.0/fonts/remixicon.css">
    <script src="https://unpkg.com/html5-qrcode" type="text/javascript"></script>
    <style>
        body {
            font-family: 'Segoe UI', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }
        .scanner-container {
            max-width: 500px;
            margin: 0 auto;
        }
        .reader-frame {
            border: 4px solid #d0d7de;
            border-radius: 14px;
            padding: 4px;
            transition: border-color 0.12s linear, box-shadow 0.12s linear;
            box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
        }
        .reader-frame.state-ok {
            border-color: #198754;
            box-shadow: 0 0 0 3px rgba(25, 135, 84, 0.22);
        }
        .reader-frame.state-error {
            border-color: #dc3545;
            box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.2);
        }
        #reader {
            border-radius: 10px;
            overflow: hidden;
        }
        .asistencia-list {
            max-height: 300px;
            overflow-y: auto;
        }
        .scan-status {
            min-height: 42px;
            border-radius: 10px;
            padding: 10px 12px;
            font-weight: 600;
            border: 1px solid #d0d7de;
            background: #f8f9fa;
            color: #475467;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .scan-status.status-ok {
            border-color: #198754;
            background: #e8f7ef;
            color: #0f5132;
        }
        .scan-status.status-error {
            border-color: #dc3545;
            background: #fdecec;
            color: #842029;
        }
    </style>
</head>
<body>
    <div class="container py-4">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card shadow">
                    <div class="card-header bg-primary text-white">
                        <div class="d-flex justify-content-between align-items-center">
                            <h4 class="mb-0">
                                <i class="ri-qr-scan-line"></i> Escanear Asistencia
                            </h4>
                            <a href="asistencia.php<?= $id_curso ? '?id_curso=' . $id_curso : '' ?>" class="btn btn-sm btn-light">
                                <i class="ri-arrow-left-line"></i> Volver
                            </a>
                        </div>
                    </div>
                    <div class="card-body">
                        <?php if ($curso_info): ?>
                            <div class="alert alert-info">
                                <strong>Curso:</strong> <?= htmlspecialchars($curso_info['nivel'] . ' ' . $curso_info['curso'] . ' "' . $curso_info['paralelo'] . '"') ?>
                                <br>
                                <strong>Fecha:</strong> <?= date('d/m/Y') ?>
                            </div>
                        <?php endif; ?>

                        <!-- Scanner -->
                        <div class="scanner-container mb-4">
                            <div id="readerFrame" class="reader-frame">
                                <div id="reader"></div>
                            </div>
                        </div>

                        <!-- Resultado del escaneo -->
                        <div id="result" class="mb-4 scan-status" aria-live="polite">Listo para escanear</div>

                        <!-- Lista de asistencia de hoy -->
                        <div class="card mt-4" id="asistencia-hoy-card">
                            <div class="card-header bg-success text-white">
                                <h6 class="mb-0">
                                    <i class="ri-check-double-line"></i> Asistencia Registrada Hoy (<span id="asistencia-count"><?= count($asistencia_hoy) ?></span>)
                                </h6>
                            </div>
                            <div class="card-body p-0">
                                <div class="table-responsive asistencia-list">
                                    <table class="table table-striped mb-0">
                                        <thead class="table-light">
                                            <tr>
                                                <th>Hora</th>
                                                <th>Estudiante</th>
                                            </tr>
                                        </thead>
                                        <tbody id="asistencia-hoy-body">
                                            <?php if (!empty($asistencia_hoy)): ?>
                                                <?php foreach ($asistencia_hoy as $asist): ?>
                                                    <tr>
                                                        <td><?= $asist['hora_entrada'] ?></td>
                                                        <td><?= htmlspecialchars($asist['apellido_paterno'] . ' ' . $asist['apellido_materno'] . ', ' . $asist['nombres']) ?></td>
                                                    </tr>
                                                <?php endforeach; ?>
                                            <?php else: ?>
                                                <tr id="asistencia-empty-row">
                                                    <td colspan="2" class="text-center text-muted py-3">Sin registros todavia.</td>
                                                </tr>
                                            <?php endif; ?>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        let html5QrcodeScanner;
        let isProcessingScan = false;
        let pendingPayload = '';
        let readerStateTimer = null;
        let statusTimer = null;
        let audioContext = null;
        let lastScannedValue = '';
        let lastScannedAt = 0;
        const DUPLICATE_WINDOW_MS = 160;
        const BORDER_FEEDBACK_MS = 170;
        const STATUS_RESET_MS = 950;
        const CACHE_TTL_MS = 30 * 60 * 1000;
        const ACTIVE_COURSE_ID = <?= $id_curso ? (int)$id_curso : 0 ?>;
        const COURSE_STUDENTS_FROM_SERVER = <?= json_encode($estudiantes_cache, JSON_UNESCAPED_UNICODE) ?>;
        let studentNameMap = {};

        function getStudentCacheKey(courseId) {
            return 'qr_students_cache_' + String(courseId || 0);
        }

        function buildStudentMap(list) {
            const map = {};
            if (!Array.isArray(list)) {
                return map;
            }
            for (const st of list) {
                const id = parseInt(st.id_estudiante, 10);
                if (!id) {
                    continue;
                }
                const nombre = `${st.apellido_paterno || ''} ${st.apellido_materno || ''}, ${st.nombres || ''}`.trim();
                map[id] = nombre.replace(/\s+/g, ' ').trim();
            }
            return map;
        }

        function saveStudentCache(courseId, list) {
            if (!courseId || !window.localStorage) {
                return;
            }
            try {
                const payload = { ts: Date.now(), students: Array.isArray(list) ? list : [] };
                localStorage.setItem(getStudentCacheKey(courseId), JSON.stringify(payload));
            } catch (e) {
            }
        }

        function loadStudentCache(courseId) {
            if (!courseId || !window.localStorage) {
                return [];
            }
            try {
                const raw = localStorage.getItem(getStudentCacheKey(courseId));
                if (!raw) {
                    return [];
                }
                const parsed = JSON.parse(raw);
                if (!parsed || !Array.isArray(parsed.students) || !parsed.ts) {
                    return [];
                }
                if ((Date.now() - parsed.ts) > CACHE_TTL_MS) {
                    localStorage.removeItem(getStudentCacheKey(courseId));
                    return [];
                }
                return parsed.students;
            } catch (e) {
                return [];
            }
        }

        function parseStudentIdFromPayload(payload) {
            const value = (payload || '').trim();
            const m = value.match(/^EST:(\d+)$/);
            if (m) {
                return parseInt(m[1], 10);
            }
            if (/^\d+$/.test(value)) {
                return parseInt(value, 10);
            }
            try {
                const obj = JSON.parse(value);
                const id = parseInt(obj && obj.id_estudiante, 10);
                return id > 0 ? id : 0;
            } catch (e) {
                return 0;
            }
        }

        function setStatusMessage(text, state) {
            const box = document.getElementById('result');
            if (!box) {
                return;
            }

            box.classList.remove('status-ok', 'status-error');
            if (state === 'ok') {
                box.classList.add('status-ok');
            } else if (state === 'error') {
                box.classList.add('status-error');
            }
            box.textContent = text || 'Listo para escanear';

            if (statusTimer) {
                clearTimeout(statusTimer);
                statusTimer = null;
            }

            if (state === 'ok' || state === 'error') {
                statusTimer = setTimeout(() => {
                    box.classList.remove('status-ok', 'status-error');
                    box.textContent = 'Listo para escanear';
                    statusTimer = null;
                }, STATUS_RESET_MS);
            }
        }

        function ensureAudioContext() {
            if (audioContext) {
                return audioContext;
            }
            const Ctx = window.AudioContext || window.webkitAudioContext;
            if (!Ctx) {
                return null;
            }
            audioContext = new Ctx();
            return audioContext;
        }

        function playBeep(type) {
            const ctx = ensureAudioContext();
            if (!ctx) {
                return;
            }
            if (ctx.state === 'suspended') {
                ctx.resume();
            }

            const oscillator = ctx.createOscillator();
            const gainNode = ctx.createGain();
            oscillator.connect(gainNode);
            gainNode.connect(ctx.destination);

            if (type === 'detect') {
                oscillator.frequency.value = 1300;
                oscillator.type = 'sine';
                gainNode.gain.value = 0.2;
            } else {
                oscillator.frequency.value = 320;
                oscillator.type = 'square';
                gainNode.gain.value = 0.14;
            }

            oscillator.start();
            oscillator.stop(ctx.currentTime + (type === 'detect' ? 0.045 : 0.055));
        }

        function setReaderState(state) {
            const frame = document.getElementById('readerFrame');
            if (!frame) {
                return;
            }

            frame.classList.remove('state-ok', 'state-error');
            if (readerStateTimer) {
                clearTimeout(readerStateTimer);
                readerStateTimer = null;
            }

            if (state === 'ok') {
                frame.classList.add('state-ok');
            } else if (state === 'error') {
                frame.classList.add('state-error');
            }

            if (state === 'ok' || state === 'error') {
                readerStateTimer = setTimeout(() => {
                    frame.classList.remove('state-ok', 'state-error');
                    readerStateTimer = null;
                }, BORDER_FEEDBACK_MS);
            }
        }

        function appendAttendanceRow(hora, estudiante) {
            const tbody = document.getElementById('asistencia-hoy-body');
            if (!tbody) {
                return;
            }

            const emptyRow = document.getElementById('asistencia-empty-row');
            if (emptyRow) {
                emptyRow.remove();
            }

            const row = document.createElement('tr');
            const cellHora = document.createElement('td');
            const cellEstudiante = document.createElement('td');
            cellHora.textContent = hora || '';
            cellEstudiante.textContent = estudiante || '';
            row.appendChild(cellHora);
            row.appendChild(cellEstudiante);
            tbody.prepend(row);

            const countEl = document.getElementById('asistencia-count');
            if (countEl) {
                const current = parseInt(countEl.textContent || '0', 10);
                countEl.textContent = String(Number.isNaN(current) ? 1 : current + 1);
            }
        }

        function procesarPayload(payload) {
            if (!payload) {
                return;
            }

            if (isProcessingScan) {
                pendingPayload = payload;
                return;
            }

            isProcessingScan = true;

            fetch('escanear_asistencia.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                cache: 'no-store',
                body: 'qr_data=' + encodeURIComponent(payload)
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    appendAttendanceRow(data.hora, data.estudiante);
                    setReaderState('ok');
                    setStatusMessage((data.estudiante || 'Estudiante') + ' + REGISTRADO', 'ok');
                    const studentId = parseInt(data.id_estudiante, 10);
                    if (studentId > 0 && data.estudiante) {
                        studentNameMap[studentId] = data.estudiante;
                    }
                } else {
                    setReaderState('error');
                    setStatusMessage(data.message || 'Error al registrar', 'error');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                setReaderState('error');
                setStatusMessage('Error de red al registrar', 'error');
                playBeep('error');
            })
            .finally(() => {
                isProcessingScan = false;
                if (pendingPayload) {
                    const next = pendingPayload;
                    pendingPayload = '';
                    procesarPayload(next);
                }
            });
        }

        function onScanSuccess(decodedText) {
            const payload = (decodedText || '').trim();
            if (!payload) {
                return;
            }

            const now = Date.now();
            if (payload === lastScannedValue && (now - lastScannedAt) < DUPLICATE_WINDOW_MS) {
                return;
            }

            playBeep('detect');

            lastScannedValue = payload;
            lastScannedAt = now;
            procesarPayload(payload);
        }

        function onScanFailure(error) {
            // Manejar errores de escaneo (opcional)
            // console.warn(`Code scan error = ${error}`);
        }

        // Iniciar el escáner
        document.addEventListener('DOMContentLoaded', function() {
            const localStudents = loadStudentCache(ACTIVE_COURSE_ID);
            if (Array.isArray(COURSE_STUDENTS_FROM_SERVER) && COURSE_STUDENTS_FROM_SERVER.length > 0) {
                studentNameMap = buildStudentMap(COURSE_STUDENTS_FROM_SERVER);
                saveStudentCache(ACTIVE_COURSE_ID, COURSE_STUDENTS_FROM_SERVER);
            } else {
                studentNameMap = buildStudentMap(localStudents);
            }

            document.addEventListener('click', ensureAudioContext, { once: true });
            document.addEventListener('touchstart', ensureAudioContext, { once: true });
            html5QrcodeScanner = new Html5QrcodeScanner(
                "reader",
                {
                    fps: 30,
                    qrbox: { width: 220, height: 220 },
                    aspectRatio: 1.0,
                    formatsToSupport: [Html5QrcodeSupportedFormats.QR_CODE],
                    disableFlip: true
                },
                /* verbose= */ false
            );
            
            html5QrcodeScanner.render(onScanSuccess, onScanFailure);

            const originalOnScanSuccess = onScanSuccess;
            onScanSuccess = function(decodedText) {
                const payload = (decodedText || '').trim();
                const id = parseStudentIdFromPayload(payload);
                if (id > 0 && studentNameMap[id]) {
                    setStatusMessage(studentNameMap[id] + ' detectado', 'neutral');
                }
                originalOnScanSuccess(decodedText);
            };
        });
    </script>
</body>
</html>
