<?php
declare(strict_types=1);

date_default_timezone_set('America/Asuncion');

require_once __DIR__ . '/../../app/bootstrap.php';
require_once __DIR__ . '/../../app/services/biometricos/BiometricoRepository.php';

header('Content-Type: application/json; charset=utf-8');

function normalizarCedula(?string $valor): string
{
    $valor = trim((string)$valor);
    return preg_replace('/\D+/', '', $valor) ?? '';
}

function contieneTexto(string $texto, string $busqueda): bool
{
    return mb_stripos($texto, $busqueda) !== false;
}

function fechaDentroDelPeriodo(string $fechaHora, string $periodo): bool
{
    if ($fechaHora === '') {
        return false;
    }

    try {
        $tz = new DateTimeZone('America/Asuncion');
        $fecha = new DateTime($fechaHora, $tz);
        $ahora = new DateTime('now', $tz);

        $hoy = $ahora->format('Y-m-d');
        $ayer = (clone $ahora)->modify('-1 day')->format('Y-m-d');
        $fechaSolo = $fecha->format('Y-m-d');

        switch ($periodo) {
            case 'hoy':
                return $fechaSolo === $hoy;

            case 'ayer':
                return $fechaSolo === $ayer;

            case 'semana':
                $inicioSemana = (clone $ahora)->modify('monday this week')->setTime(0, 0, 0);
                $finSemana = (clone $inicioSemana)->modify('+6 days')->setTime(23, 59, 59);
                return $fecha >= $inicioSemana && $fecha <= $finSemana;

            case 'mes':
                return $fecha->format('Y-m') === $ahora->format('Y-m');

            case 'todos':
            default:
                return true;
        }
    } catch (Throwable $e) {
        return false;
    }
}

function normalizarInstitucion(string $valor): string
{
    $v = strtoupper(trim($valor));
    if ($v === 'ENC') return 'ENC';
    if ($v === 'CARF') return 'CARF';
    return '';
}

function nombrePersona(?string $nombres, ?string $apellidos): string
{
    $n = trim((string)$nombres);
    $a = trim((string)$apellidos);

    if ($n === '-' || $n === '—') $n = '';
    if ($a === '-' || $a === '—') $a = '';

    $full = trim($n . ' ' . $a);
    return $full !== '' ? $full : '-';
}

function construirGrupoAcademico(string $nivel, string $curso): array
{
    $nivel = strtoupper(trim($nivel));
    $curso = trim($curso);

    $grado = '-';
    $cursoOut = '-';
    $grupo = '-';

    if ($nivel === 'EEB' && in_array($curso, ['7°', '8°', '9°'], true)) {
        $grado = $curso;
        $grupo = $curso;
    } elseif (in_array($nivel, ['BTC', 'BC'], true) && in_array($curso, ['1°', '2°', '3°'], true)) {
        $cursoOut = $curso;
        $grupo = $curso;
    } else {
        if (in_array($curso, ['7°', '8°', '9°'], true)) {
            $grado = $curso;
            $grupo = $curso;
        } elseif (in_array($curso, ['1°', '2°', '3°'], true)) {
            $cursoOut = $curso;
            $grupo = $curso;
        }
    }

    return [
        'grado' => $grado,
        'curso' => $cursoOut,
        'grupo_academico' => $grupo,
    ];
}

try {
    $repo = new BiometricoRepository();
    $pdo = db();

    $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 50;
    if ($limit <= 0) $limit = 50;
    if ($limit > 200) $limit = 200;

    $institucionFiltro = normalizarInstitucion((string)($_GET['institucion'] ?? ''));
    $tipoPersonaFiltro = trim((string)($_GET['tipo_persona'] ?? ''));
    $gradoFiltro = trim((string)($_GET['grado'] ?? ''));
    $cursoFiltro = trim((string)($_GET['curso'] ?? ''));
    $periodoFiltro = trim((string)($_GET['periodo'] ?? 'hoy'));
    $qFiltro = trim((string)($_GET['q'] ?? ''));

    $rawRows = $repo->obtenerUltimasMarcaciones(300);
    $resumenBase = $repo->obtenerResumenMonitor();
    $anioActual = (int)date('Y');

    // Estudiante con matrícula ACTIVA del año
    $sqlEstudianteActivo = "
        SELECT
            e.id,
            e.ci,
            e.nombres,
            e.apellidos,
            m.id AS matricula_id,
            m.institucion,
            m.anio_lectivo,
            m.nivel,
            m.curso,
            m.seccion,
            m.turno,
            m.estado
        FROM estudiantes e
        INNER JOIN matriculas m ON m.estudiante_id = e.id
        WHERE e.ci = :cedula
          AND e.activo = 1
          AND m.anio_lectivo = :anio
          AND m.estado = 'ACTIVO'
        ORDER BY m.id DESC
        LIMIT 1
    ";
    $stEstudianteActivo = $pdo->prepare($sqlEstudianteActivo);

    // Última matrícula del año, aunque esté inactiva
    $sqlEstudianteMatriculaAnio = "
        SELECT
            e.id,
            e.ci,
            e.nombres,
            e.apellidos,
            m.id AS matricula_id,
            m.institucion,
            m.anio_lectivo,
            m.nivel,
            m.curso,
            m.seccion,
            m.turno,
            m.estado
        FROM estudiantes e
        LEFT JOIN matriculas m ON m.estudiante_id = e.id
        WHERE REPLACE(REPLACE(REPLACE(COALESCE(e.ci, ''), '.', ''), '-', ''), ' ', '') = :cedula
          AND e.activo = 1
          AND m.anio_lectivo = :anio
        ORDER BY m.id DESC
        LIMIT 1
    ";
    $stEstudianteMatriculaAnio = $pdo->prepare($sqlEstudianteMatriculaAnio);

    // Estudiante base, aunque no tenga matrícula
    $sqlEstudianteBase = "
        SELECT
            e.id,
            e.ci,
            e.nombres,
            e.apellidos
        FROM estudiantes e
        WHERE REPLACE(REPLACE(REPLACE(COALESCE(e.ci, ''), '.', ''), '-', ''), ' ', '') = :cedula
          AND e.activo = 1
        LIMIT 1
    ";
    $stEstudianteBase = $pdo->prepare($sqlEstudianteBase);

    // Nombre del reloj
    $sqlReloj = "
        SELECT id, nombre
        FROM relojes_biometricos
        WHERE id = :id
        LIMIT 1
    ";
    $stReloj = $pdo->prepare($sqlReloj);

    // Nombre desde reloj_nomina
    $sqlNomina = "
        SELECT
            rn.id,
            rn.nombre,
            rn.empleado_no,
            rn.device_user_id
        FROM reloj_nomina rn
        WHERE rn.reloj_id = :reloj_id
          AND (
              rn.device_user_id = :device_user_id
              OR rn.empleado_no = :device_user_id
          )
        LIMIT 1
    ";
    $stNomina = $pdo->prepare($sqlNomina);

    $filtradas = [];

    foreach ($rawRows as $row) {
        $rowId = (int)($row['id'] ?? 0);
        $relojId = (int)($row['reloj_id'] ?? 0);
        $deviceUserId = trim((string)($row['device_user_id'] ?? ''));
        $cedula = normalizarCedula($deviceUserId);
        $fechaHora = trim((string)($row['fecha_hora'] ?? ''));

        $relojNombre = '-';
        if ($relojId > 0) {
            $stReloj->execute([':id' => $relojId]);
            $rj = $stReloj->fetch(PDO::FETCH_ASSOC);
            if ($rj) {
                $relojNombre = trim((string)($rj['nombre'] ?? '-'));
            }
        }

        $item = [
            'id' => $rowId,
            'fecha_hora' => $fechaHora,
            'cedula' => $cedula !== '' ? $cedula : $deviceUserId,
            'device_user_id' => $deviceUserId,
            'nombre' => '-',
            'tipo_persona' => 'desconocido',
            'institucion' => '-',
            'nivel' => '-',
            'grado' => '-',
            'curso' => '-',
            'grupo_academico' => '-',
            'estado_matricula' => '-',
            'estado_asistencia' => 'presente',
            'reloj_id' => $relojId,
            'reloj_nombre' => $relojNombre,
            'tipo_evento' => (string)($row['tipo_evento'] ?? '-'),
        ];

        // 1) Estudiante activo
        $estActivo = null;
        if ($cedula !== '') {
            $stEstudianteActivo->execute([
                ':cedula' => $cedula,
                ':anio' => $anioActual,
            ]);
            $estActivo = $stEstudianteActivo->fetch(PDO::FETCH_ASSOC) ?: null;
        }

        if ($estActivo) {
            $item['tipo_persona'] = 'estudiante_activo';
            $item['nombre'] = nombrePersona($estActivo['nombres'] ?? '', $estActivo['apellidos'] ?? '');
            $item['institucion'] = trim((string)($estActivo['institucion'] ?? '')) ?: '-';
            $item['nivel'] = trim((string)($estActivo['nivel'] ?? '')) ?: '-';
            $item['estado_matricula'] = trim((string)($estActivo['estado'] ?? 'ACTIVO')) ?: 'ACTIVO';

            $grupo = construirGrupoAcademico(
                (string)($estActivo['nivel'] ?? ''),
                (string)($estActivo['curso'] ?? '')
            );
            $item['grado'] = $grupo['grado'];
            $item['curso'] = $grupo['curso'];
            $item['grupo_academico'] = $grupo['grupo_academico'];
        } else {
            // 2) Tiene matrícula del año pero no activa
            $estAnio = null;
            if ($cedula !== '') {
                $stEstudianteMatriculaAnio->execute([
                    ':cedula' => $cedula,
                    ':anio' => $anioActual,
                ]);
                $estAnio = $stEstudianteMatriculaAnio->fetch(PDO::FETCH_ASSOC) ?: null;
            }

            if ($estAnio) {
                $item['tipo_persona'] = 'estudiante_inactivo';
                $item['nombre'] = nombrePersona($estAnio['nombres'] ?? '', $estAnio['apellidos'] ?? '');
                $item['institucion'] = trim((string)($estAnio['institucion'] ?? '')) ?: '-';
                $item['nivel'] = trim((string)($estAnio['nivel'] ?? '')) ?: '-';
                $item['estado_matricula'] = trim((string)($estAnio['estado'] ?? 'INACTIVO')) ?: 'INACTIVO';

                $grupo = construirGrupoAcademico(
                    (string)($estAnio['nivel'] ?? ''),
                    (string)($estAnio['curso'] ?? '')
                );
                $item['grado'] = $grupo['grado'];
                $item['curso'] = $grupo['curso'];
                $item['grupo_academico'] = $grupo['grupo_academico'];
            } else {
                // 3) Existe en estudiantes pero sin matrícula del año
                $estBase = null;
                if ($cedula !== '') {
                    $stEstudianteBase->execute([':cedula' => $cedula]);
                    $estBase = $stEstudianteBase->fetch(PDO::FETCH_ASSOC) ?: null;
                }

                if ($estBase) {
                    $item['tipo_persona'] = 'registrado_sin_matricula';
                    $item['nombre'] = nombrePersona($estBase['nombres'] ?? '', $estBase['apellidos'] ?? '');
                } else {
                    // 4) Solo aparece en reloj_nomina
                    $nom = null;
                    if ($relojId > 0 && $deviceUserId !== '') {
                        $stNomina->execute([
                            ':reloj_id' => $relojId,
                            ':device_user_id' => $deviceUserId,
                        ]);
                        $nom = $stNomina->fetch(PDO::FETCH_ASSOC) ?: null;
                    }

                    if ($nom) {
                        $item['tipo_persona'] = 'registrado';
                        $item['nombre'] = trim((string)($nom['nombre'] ?? '-')) ?: '-';
                    }
                }
            }
        }

        if (!fechaDentroDelPeriodo($fechaHora, $periodoFiltro)) {
            continue;
        }

        if ($institucionFiltro !== '' && $item['institucion'] !== $institucionFiltro) {
            continue;
        }

        if ($tipoPersonaFiltro !== '' && $item['tipo_persona'] !== $tipoPersonaFiltro) {
            continue;
        }

        if ($gradoFiltro !== '' && $item['grado'] !== $gradoFiltro) {
            continue;
        }

        if ($cursoFiltro !== '' && $item['curso'] !== $cursoFiltro) {
            continue;
        }

        if ($qFiltro !== '') {
            $texto = mb_strtolower(trim(
                $item['cedula'] . ' ' .
                $item['device_user_id'] . ' ' .
                $item['nombre'] . ' ' .
                $item['institucion'] . ' ' .
                $item['nivel'] . ' ' .
                $item['grado'] . ' ' .
                $item['curso'] . ' ' .
                $item['grupo_academico'] . ' ' .
                $item['tipo_persona'] . ' ' .
                $item['reloj_nombre'] . ' ' .
                $item['estado_matricula']
            ));

            if (!contieneTexto($texto, mb_strtolower($qFiltro))) {
                continue;
            }
        }

        $filtradas[] = $item;
    }

    usort($filtradas, function (array $a, array $b): int {
        $fa = strtotime((string)($a['fecha_hora'] ?? '')) ?: 0;
        $fb = strtotime((string)($b['fecha_hora'] ?? '')) ?: 0;

        if ($fb !== $fa) {
            return $fb <=> $fa;
        }

        return ((int)($b['id'] ?? 0)) <=> ((int)($a['id'] ?? 0));
    });

    $totalFiltrado = count($filtradas);
    $rows = array_slice($filtradas, 0, $limit);
    $ultimaFechaHora = $rows[0]['fecha_hora'] ?? '-';

    echo json_encode([
        'ok' => true,
        'resumen' => [
            'total_general' => (int)($resumenBase['total'] ?? 0),
            'total_filtrado' => $totalFiltrado,
            'ultima_fecha_hora' => $ultimaFechaHora,
        ],
        'rows' => $rows,
        'server_time' => date('Y-m-d H:i:s'),
    ], JSON_UNESCAPED_UNICODE);

} catch (Throwable $e) {
    http_response_code(500);

    echo json_encode([
        'ok' => false,
        'error' => $e->getMessage(),
    ], JSON_UNESCAPED_UNICODE);
}