<?php
// ../../Controlador/Ctrl_Administrador/MySQL_Cambiar_Estado_Usuario.php
session_start();
header('Content-Type: application/json; charset=utf-8');

require_once "../Utilidades/Conexion_BD.php";
require_once "../Utilidades/Auditoria.php";

/* ---------- Helpers ---------- */
function validarFechaISO($s) {
  if (!$s) return false;
  if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $s)) return false;
  [$y,$m,$d] = explode('-', $s);
  return checkdate((int)$m,(int)$d,(int)$y);
}

try {
  // Requiere sesión
  if (!isset($_SESSION['usuario'])) {
    echo json_encode(['ok'=>false,'success'=>false,'message'=>'Sesión expirada.']);
    exit;
  }

  // Aceptar id_usuario o id
  $idUsuario   = isset($_POST['id_usuario']) ? (int)$_POST['id_usuario'] : (int)($_POST['id'] ?? 0);
  $nuevoEstado = trim($_POST['estado'] ?? '');
  // Aceptar 'motivo' o 'motivo_estado'
  $motivo      = isset($_POST['motivo']) ? trim($_POST['motivo']) : trim($_POST['motivo_estado'] ?? '');
  // Fechas: cuando sale de ACTIVO (=> no activo) y cuando vuelve a ACTIVO
  $fCambio     = $_POST['fecha_cambio']  ?? null;
  $fRegreso    = $_POST['fecha_regreso'] ?? null;

  if ($idUsuario <= 0 || $nuevoEstado === '') {
    echo json_encode(['ok'=>false,'success'=>false,'message'=>'Parámetros incompletos.']);
    exit;
  }

  $estadosValidos = ['activo','inactivo','suspendido','bloqueado'];
  if (!in_array($nuevoEstado, $estadosValidos, true)) {
    echo json_encode(['ok'=>false,'success'=>false,'message'=>'Estado inválido.']);
    exit;
  }

  // Motivo obligatorio para estados ≠ activo
  if ($nuevoEstado !== 'activo' && $motivo === '') {
    echo json_encode(['ok'=>false,'success'=>false,'message'=>'Debe ingresar un motivo para este cambio de estado.']);
    exit;
  }

  // La fecha requerida depende del estado
  $fechaEvento = ($nuevoEstado === 'activo') ? $fRegreso : $fCambio;
  if (!$fechaEvento || !validarFechaISO($fechaEvento)) {
    $et = ($nuevoEstado === 'activo') ? 'fecha_regreso' : 'fecha_cambio';
    echo json_encode(['ok'=>false,'success'=>false,'message'=>"Fecha inválida o faltante ($et)."]);
    exit;
  }

  $conn = new Conexion_BD();
  $db   = $conn->getConnection();

  $actorId  = isset($_SESSION['id_usuario']) ? (int)$_SESSION['id_usuario'] : null; // <- se guarda en actor_id
  $actorNm  = $_SESSION['usuario'] ?? 'sistema';
  $actorRol = $_SESSION['rol'] ?? '';

  $db->begin_transaction();

  // 1) Leer estado actual y bloquear fila
  $sql = "SELECT estado, fecha_estado_desde FROM usuarios WHERE id_usuario = ? FOR UPDATE";
  $stmt = $db->prepare($sql);
  if (!$stmt) throw new Exception("Error prepare SELECT: ".$db->error);
  $stmt->bind_param("i", $idUsuario);
  $stmt->execute();
  $stmt->bind_result($estadoActual, $fechaDesdeActual);
  if (!$stmt->fetch()) {
    $stmt->close();
    throw new Exception("Usuario no encontrado (ID $idUsuario).");
  }
  $stmt->close();

  // (Opcional) si vuelve a ACTIVO, no permitir fecha_regreso < fecha_estado_desde actual
  if ($nuevoEstado === 'activo' && $fechaDesdeActual && $fechaEvento < $fechaDesdeActual) {
    throw new Exception("La fecha de regreso ($fechaEvento) no puede ser menor a la fecha desde la que quedó no activo ($fechaDesdeActual).");
  }

  // 2) Actualizar tabla usuarios (estado, motivo, fecha_estado_desde)
  $sql = "UPDATE usuarios
          SET estado = ?, motivo_estado = ?, fecha_estado_desde = ?
          WHERE id_usuario = ?";
  $stmt = $db->prepare($sql);
  if (!$stmt) throw new Exception("Error prepare UPDATE usuarios: ".$db->error);
  $stmt->bind_param("sssi", $nuevoEstado, $motivo, $fechaEvento, $idUsuario);
  if (!$stmt->execute()) throw new Exception("Error ejecutando UPDATE usuarios.");
  $stmt->close();

  // 3) Historial: cerrar período abierto y abrir uno nuevo (o ajustar si es el mismo estado)
  // 3.1 Cerrar cualquier período abierto (si existe)
  $sql = "UPDATE usuario_estado_historial
          SET fecha_fin = ?
          WHERE usuario_id = ? AND fecha_fin IS NULL";
  $stmt = $db->prepare($sql);
  if (!$stmt) throw new Exception("Error prepare UPDATE historial(fin): ".$db->error);
  $stmt->bind_param("si", $fechaEvento, $idUsuario);
  if (!$stmt->execute()) throw new Exception("Error ejecutando UPDATE historial(fin).");
  $stmt->close();

  // 3.2 Si el nuevo estado es IGUAL al actual: intentar ajustar inicio de un período abierto (si existiera)
  $sql = "UPDATE usuario_estado_historial
          SET fecha_inicio = ?, motivo = ?, actor_id = ?
          WHERE usuario_id = ? AND fecha_fin IS NULL AND estado = ?";
  $stmt = $db->prepare($sql);
  if (!$stmt) throw new Exception("Error prepare UPDATE historial(inicio): ".$db->error);
  $stmt->bind_param("sssis", $fechaEvento, $motivo, $actorId, $idUsuario, $nuevoEstado);
  if (!$stmt->execute()) throw new Exception("Error ejecutando UPDATE historial(inicio).");
  $reabierto = ($stmt->affected_rows > 0);
  $stmt->close();

  if (!$reabierto) {
    // 3.3 Insertar nuevo período abierto con el nuevo estado
    $sql = "INSERT INTO usuario_estado_historial
            (usuario_id, estado, fecha_inicio, fecha_fin, motivo, actor_id)
            VALUES (?,?,?,?,?,?)";
    $stmt = $db->prepare($sql);
    if (!$stmt) throw new Exception("Error prepare INSERT historial: ".$db->error);
    $fin = null;
    $stmt->bind_param("issssi", $idUsuario, $nuevoEstado, $fechaEvento, $fin, $motivo, $actorId);
    if (!$stmt->execute()) throw new Exception("Error ejecutando INSERT historial.");
    $stmt->close();
  }

  // 4) Auditoría
  $descripcion = "Se cambió el estado del usuario ID $idUsuario a $nuevoEstado (fecha: $fechaEvento)";
  $observacion = trim(($motivo ? "Motivo: $motivo" : ""));
  registrarAuditoria(
    'usuarios',            // modulo
    'cambiar_estado',      // accion
    $descripcion,          // descripcion
    $actorId ?? 0,         // id_usuario (editor)
    $actorNm,              // nombre_usuario
    'usuarios',            // tabla_afectada
    $idUsuario,            // id_registro_afectado
    $actorRol,             // tipo_usuario
    $observacion           // observacion
  );

  $db->commit();
  $conn->closeConnection();

  echo json_encode([
    'ok'      => true,
    'success' => true,
    'message' => 'Estado actualizado correctamente.',
    'msg'     => 'Estado actualizado correctamente.',
    'fecha'   => $fechaEvento,
    'estado'  => $nuevoEstado
  ]);
} catch (Throwable $e) {
  if (isset($db)) { $db->rollback(); }
  if (isset($conn)) { $conn->closeConnection(); }
  echo json_encode([
    'ok'      => false,
    'success' => false,
    'message' => 'Error en el servidor: '.$e->getMessage(),
    'msg'     => 'Error en el servidor: '.$e->getMessage()
  ]);
}
