<?php
/**
 * Cron: inserta horarios para las 2 quincenas siguientes a la quincena actual.
 *
 * Tablas afectadas:
 * - HorariosAsignados
 * - DetalleHorariosSemana
 * - DiasDescanso
 *
 * Fuente de horarios base:
 * - horarios_fijos (reemplaza horarios_admin)
 *
 * Ejecución esperada:
 * - Una vez al mes por cron
 * - Día opcional configurable con --day=DD o env HORARIOS_CRON_DAY
 * - Puede forzarse con --force
 */

date_default_timezone_set('America/Merida');
require_once __DIR__ . '/../backend/config/database.php';

$force = in_array('--force', $argv ?? [], true);
$hoy = new DateTime('now');

// Día de ejecución opcional (si no se define, no se valida día)
$runDay = null;

foreach (($argv ?? []) as $arg) {
    if (strpos($arg, '--day=') === 0) {
        $runDay = (int)substr($arg, 6);
        break;
    }
}

if ($runDay === null) {
    $envDay = getenv('HORARIOS_CRON_DAY');
    if ($envDay !== false && $envDay !== '') {
        $runDay = (int)$envDay;
    }
}

if ($runDay !== null) {
    if ($runDay < 1 || $runDay > 31) {
        throw new InvalidArgumentException('El día configurado debe estar entre 1 y 31.');
    }

    if ((int)$hoy->format('j') !== $runDay && !$force) {
        echo "[INFO] Hoy ({$hoy->format('Y-m-d')}) no coincide con el día configurado ($runDay). No se ejecuta el proceso.\n";
        echo "[INFO] Usa --force si deseas ejecutarlo manualmente.\n";
        exit(0);
    }
}

try {
    $database = new Database();
    $db = $database->connect();
    $db->beginTransaction();

    // 1) Detectar quincena actual
    $sqlActual = "
        SELECT id_quincena, fecha_inicio, fecha_fin
        FROM Quincenas
        WHERE CURDATE() BETWEEN fecha_inicio AND fecha_fin
        ORDER BY id_quincena DESC
        LIMIT 1
    ";
    $stmtActual = $db->query($sqlActual);
    $quincenaActual = $stmtActual->fetch(PDO::FETCH_ASSOC);

    if (!$quincenaActual) {
        throw new Exception('No se encontró quincena actual para la fecha de hoy en la tabla Quincenas.');
    }

    // 2) Obtener las 2 quincenas siguientes
    $sqlSiguientes = "
        SELECT id_quincena, fecha_inicio, fecha_fin
        FROM Quincenas
        WHERE fecha_inicio > :fecha_fin_actual
        ORDER BY fecha_inicio ASC
        LIMIT 2
    ";
    $stmtSiguientes = $db->prepare($sqlSiguientes);
    $stmtSiguientes->execute([':fecha_fin_actual' => $quincenaActual['fecha_fin']]);
    $quincenasObjetivo = $stmtSiguientes->fetchAll(PDO::FETCH_ASSOC);

    if (count($quincenasObjetivo) < 2) {
        throw new Exception('No existen 2 quincenas siguientes disponibles en Quincenas.');
    }

    $idQ1 = (int)$quincenasObjetivo[0]['id_quincena'];
    $idQ2 = (int)$quincenasObjetivo[1]['id_quincena'];

    echo "[INFO] Quincena actual: {$quincenaActual['id_quincena']} ({$quincenaActual['fecha_inicio']} a {$quincenaActual['fecha_fin']})\n";
    echo "[INFO] Quincenas objetivo: {$idQ1} y {$idQ2}\n";

    // 3) Preparar datos base
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_curps");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_quincenas");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_nums");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_fechas");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_fechas_semana");

    $db->exec("
        CREATE TEMPORARY TABLE tmp_curps AS
        SELECT DISTINCT curp FROM miembros_area_admin
        UNION
        SELECT DISTINCT CURP COLLATE latin1_general_ci AS curp FROM horarios_fijos
    ");

    $stmtTmpQ = $db->prepare("
        CREATE TEMPORARY TABLE tmp_quincenas AS
        SELECT id_quincena, fecha_inicio, fecha_fin
        FROM Quincenas
        WHERE id_quincena IN (:id_q1, :id_q2)
    ");
    $stmtTmpQ->execute([
        ':id_q1' => $idQ1,
        ':id_q2' => $idQ2,
    ]);

    $db->exec("CREATE TEMPORARY TABLE tmp_nums (n INT PRIMARY KEY)");
    $db->exec("
        INSERT INTO tmp_nums (n) VALUES
        (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),
        (11),(12),(13),(14),(15),(16),(17),(18),(19),(20),
        (21),(22),(23),(24),(25),(26),(27),(28),(29),(30),
        (31)
    ");

    $db->exec("
        CREATE TEMPORARY TABLE tmp_fechas AS
        SELECT q.id_quincena,
               DATE_ADD(q.fecha_inicio, INTERVAL n.n DAY) AS fecha
        FROM tmp_quincenas q
        JOIN tmp_nums n
          ON DATE_ADD(q.fecha_inicio, INTERVAL n.n DAY) <= q.fecha_fin
    ");

    $db->exec("
        CREATE TEMPORARY TABLE tmp_fechas_semana AS
        SELECT f.id_quincena,
               f.fecha,
               1 + (
                   SELECT COUNT(*)
                   FROM tmp_fechas f2
                   WHERE f2.id_quincena = f.id_quincena
                     AND f2.fecha < f.fecha
                     AND DAYOFWEEK(f2.fecha) = 1
               ) AS semana,
               CONVERT(
                   CASE DAYOFWEEK(f.fecha)
                     WHEN 1 THEN 'Domingo'
                     WHEN 2 THEN 'Lunes'
                     WHEN 3 THEN 'Martes'
                     WHEN 4 THEN 'Miércoles'
                     WHEN 5 THEN 'Jueves'
                     WHEN 6 THEN 'Viernes'
                     WHEN 7 THEN 'Sábado'
                   END USING latin1
               ) COLLATE latin1_general_ci AS dia_semana
        FROM tmp_fechas f
    ");

    // 4) Insertar HorariosAsignados (CURP x quincena)
    $sqlInsertHA = "
        INSERT INTO HorariosAsignados (curp, id_quincena, fecha_inicio, fecha_fin)
        SELECT c.curp, q.id_quincena, q.fecha_inicio, q.fecha_fin
        FROM tmp_curps c
        CROSS JOIN tmp_quincenas q
        WHERE NOT EXISTS (
            SELECT 1 FROM HorariosAsignados h
            WHERE h.curp = c.curp AND h.id_quincena = q.id_quincena
        )
    ";
    $rowsHA = $db->exec($sqlInsertHA);

    // 5) Insertar DetalleHorariosSemana
    $sqlInsertDHS = "
        INSERT INTO DetalleHorariosSemana (id_horario, semana, dia_semana, fecha, hora_entrada, hora_salida)
        SELECT h.id_horario,
               f.semana,
               f.dia_semana,
               f.fecha,
               COALESCE(hf.hora_entrada, '00:00:00') AS hora_entrada,
               COALESCE(
                   CASE WHEN f.dia_semana = 'Domingo' THEN '00:00:00' ELSE hf.hora_salida END,
                   '00:00:00'
               ) AS hora_salida
        FROM HorariosAsignados h
        JOIN tmp_fechas_semana f ON f.id_quincena = h.id_quincena
        LEFT JOIN horarios_fijos hf
          ON hf.CURP COLLATE latin1_general_ci = h.curp COLLATE latin1_general_ci
         AND hf.dia_semana COLLATE latin1_general_ci = f.dia_semana COLLATE latin1_general_ci
        WHERE h.id_quincena IN (SELECT id_quincena FROM tmp_quincenas)
          AND h.curp IN (SELECT curp FROM tmp_curps)
          AND NOT EXISTS (
              SELECT 1 FROM DetalleHorariosSemana d
              WHERE d.id_horario = h.id_horario AND d.fecha = f.fecha
          )
    ";
    $rowsDHS = $db->exec($sqlInsertDHS);

    // 6) Insertar domingos en DiasDescanso
    $sqlInsertDD = "
        INSERT INTO DiasDescanso (id_horario, id_quincena, dia_semana, fecha_descanso)
        SELECT h.id_horario, h.id_quincena, 'Domingo', f.fecha
        FROM HorariosAsignados h
        JOIN tmp_fechas_semana f
          ON f.id_quincena = h.id_quincena
         AND f.dia_semana = 'Domingo'
        WHERE h.id_quincena IN (SELECT id_quincena FROM tmp_quincenas)
          AND h.curp IN (SELECT curp FROM tmp_curps)
          AND NOT EXISTS (
              SELECT 1 FROM DiasDescanso d
              WHERE d.id_horario = h.id_horario AND d.fecha_descanso = f.fecha
          )
    ";
    $rowsDD = $db->exec($sqlInsertDD);

    // 7) Limpiar temporales
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_fechas_semana");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_fechas");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_nums");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_quincenas");
    $db->exec("DROP TEMPORARY TABLE IF EXISTS tmp_curps");

    $db->commit();

    echo "[OK] Proceso completado correctamente.\n";
    echo "[OK] HorariosAsignados insertados: " . (int)$rowsHA . "\n";
    echo "[OK] DetalleHorariosSemana insertados: " . (int)$rowsDHS . "\n";
    echo "[OK] DiasDescanso insertados: " . (int)$rowsDD . "\n";

} catch (Exception $e) {
    if (isset($db) && $db instanceof PDO && $db->inTransaction()) {
        $db->rollBack();
    }
    echo "[ERROR] " . $e->getMessage() . "\n";
    exit(1);
}
