<?php
/**
 * POST /modules/turnero/api/llamar_turno.php
 * Llama el siguiente turno de una cola con el motor de prioridades.
 * Requiere login + módulo turnero.
 *
 * Body JSON:
 *   area        string  requerido   "recepcion" | "lugar"
 *   lugar_id    int     requerido si area = "lugar"
 */

require_once __DIR__ . '/_helpers.php';
require_once __DIR__ . '/../../../classes/lab/ActividadAdmin.php';
requireMethod('POST');
requireTurnero();

$datos   = inputJson();
$area    = $datos['area'] ?? '';
$lugarId = isset($datos['lugar_id']) ? (int) $datos['lugar_id'] : null;
$deskId  = isset($datos['desk_id'])  ? (int) $datos['desk_id']  : null;
$turnoId = isset($datos['turno_id']) ? (int) $datos['turno_id'] : null; // llamar uno específico

// ── Validación ────────────────────────────────────────────────
if (!in_array($area, ['recepcion', 'lugar'], true)) {
    jsonError('area debe ser "recepcion" o "lugar".');
}
if ($area === 'lugar' && !$lugarId) {
    jsonError('lugar_id es obligatorio cuando area = "lugar".');
}

$pdo = db();
// Obtener sesión del día ANTES de abrir la transacción para que un posible
// INSERT de sesión nueva no quede dentro del rollback.
$sesionHoy = obtenerOCrearSesionHoy();
$pdo->beginTransaction();

try {
    if ($area === 'recepcion') {
        // Cola recepción: solo turnos de la sesión activa de hoy
        $turno = siguienteTurnoEnCola('espera', null, null, $sesionHoy);

        if (!$turno) {
            $pdo->rollBack();
            jsonOk(['turno' => null], 'Cola de recepción vacía');
        }

        // Actualizar estado + timestamp
        // $deskId puede ser null si el recepcionista no seleccionó escritorio;
        // se guarda igual (puede quedar NULL) pero la query del display ya no
        // usa IS NULL para evitar que aparezca en todos los escritorios.
        $stmt = $pdo->prepare(
            'UPDATE turnero_turnos
                SET estado = "en_recepcion",
                    llamado_recepcion_at   = NOW(),
                    inicio_recepcion_at    = NOW(),
                    atendido_recepcion_por = ?,
                    recepcion_desk_id      = ?
              WHERE id = ? AND estado = "espera"'
        );
        $stmt->execute([adminId(), $deskId, $turno['id']]);

        if ($stmt->rowCount() === 0) {
            // Otro proceso lo tomó primero (race condition)
            $pdo->rollBack();
            jsonError('El turno ya fue tomado por otro operador. Intente de nuevo.', 409);
        }

    } else {
        // Cola de un Lugar específico: turnos 'en_espera_lugar' asignados a ese lugar
        if ($turnoId) {
            // Llamar uno específico por id (puede ser en_espera_lugar o ya en_servicio para re-llamar)
            $stmt = $pdo->prepare(
                'SELECT t.*, p.codigo AS prioridad_codigo, p.nombre AS prioridad_nombre, p.color AS prioridad_color
                   FROM turnero_turnos t
                   JOIN turnero_prioridades p ON p.id = t.prioridad_id
                  WHERE t.id = ? AND t.estado IN ("en_espera_lugar", "en_servicio")'
            );
            $stmt->execute([$turnoId]);
            $turno = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$turno) {
                $pdo->rollBack();
                jsonError('El turno no está en espera o no existe.', 404);
            }
        } else {
            $turno = siguienteTurnoEnCola('en_espera_lugar', $lugarId, null, $sesionHoy);
            if (!$turno) {
                $pdo->rollBack();
                jsonOk(['turno' => null], 'Cola del lugar vacía');
            }
        }

        // Re-llamar: si ya está en_servicio en ESTA estación, solo actualiza llamado_at
        if ($turno['estado'] === 'en_servicio' && $turno['lugar_destino_id'] == $lugarId) {
            $pdo->prepare(
                'UPDATE turnero_turnos SET llamado_lugar_at = NOW() WHERE id = ?'
            )->execute([$turno['id']]);
            $pdo->commit();
            // Refrescar y retornar
            $stmt = $pdo->prepare(
                'SELECT t.*, p.codigo AS prioridad_codigo, p.nombre AS prioridad_nombre, p.color AS prioridad_color,
                        COALESCE(ts.solo_muestras, 0) AS solo_muestras
                   FROM turnero_turnos t
                   JOIN turnero_prioridades p ON p.id = t.prioridad_id
                   LEFT JOIN turnero_solicitudes ts ON ts.turno_id = t.id
                  WHERE t.id = ?'
            );
            $stmt->execute([$turno['id']]);
            $turnoActualizado = $stmt->fetch(PDO::FETCH_ASSOC);
            notificarSSE((int)$turnoActualizado['sesion_id']);
            jsonOk(['turno' => $turnoActualizado], "Turno {$turnoActualizado['codigo']} re-llamado");
        }

        $stmt = $pdo->prepare(
            'UPDATE turnero_turnos
                SET estado            = "en_servicio",
                    llamado_lugar_at  = NOW(),
                    inicio_lugar_at   = NOW(),
                    atendido_lugar_por= ?,
                    lugar_destino_id  = ?
              WHERE id = ? AND estado = "en_espera_lugar"'
        );
        $stmt->execute([adminId(), $lugarId, $turno['id']]);

        if ($stmt->rowCount() === 0) {
            $pdo->rollBack();
            jsonError('El turno ya fue tomado por otro operador. Intente de nuevo.', 409);
        }
    }

    // Refrescar datos del turno actualizado
    $stmt = $pdo->prepare(
        'SELECT t.*,
                p.codigo  AS prioridad_codigo,
                p.nombre  AS prioridad_nombre,
                p.color   AS prioridad_color,
                COALESCE(ts.solo_muestras, 0) AS solo_muestras
           FROM turnero_turnos t
           JOIN turnero_prioridades p ON p.id = t.prioridad_id
           LEFT JOIN turnero_solicitudes ts ON ts.turno_id = t.id
          WHERE t.id = ?'
    );
    $stmt->execute([$turno['id']]);
    $turnoActualizado = $stmt->fetch(PDO::FETCH_ASSOC);

    $pdo->commit();
    notificarSSE((int) $turnoActualizado['sesion_id']);

    // Quién llamó no se guardaba en ninguna parte: el turno solo conserva la hora
    // del último llamado, así que en la bitácora aparecía «Llamado a X» sin autor.
    try {
        (new ActividadAdmin())->registrar(
            adminId(), 'turnero', 'llamar_turno', $turnoId,
            [
                'turno_id'     => $turnoId,
                'turno_codigo' => $turnoActualizado['codigo'] ?? null,
            ]
        );
    } catch (\Throwable $e) {
        error_log('[llamar_turno] auditoría: ' . $e->getMessage());
    }

    jsonOk(['turno' => $turnoActualizado], "Turno {$turnoActualizado['codigo']} llamado");

} catch (\Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    jsonError('Error al llamar turno: ' . $e->getMessage(), 500);
}
