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

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

/* ====================== Helpers ====================== */
function hoy(): string { return date('Y-m-d'); }

function validarFechaISO(?string $s): bool {
  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);
}

function normalizar_estado($s) {
  $s = (string)$s;
  $s = trim($s);
  $s = mb_strtolower($s, 'UTF-8');
  $s = preg_replace('/[\s\-]+/', '_', $s); // espacios/guiones -> _
  if ($s === 'no_operativo') return 'inactivo';
  if ($s === 'operativo')    return 'activo';
  return $s; // activo | inactivo | mantenimiento | desincorporado
}

/* ====================== Validaciones iniciales ====================== */
// Solo POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  echo json_encode(['success' => false, 'message' => 'Método no permitido.']); exit;
}
// Sesión activa
if (!isset($_SESSION['usuario'])) {
  echo json_encode(['success' => false, 'message' => 'Sesión expirada. Debe iniciar sesión nuevamente.']); exit;
}

// Entradas
$idGrifo       = isset($_POST['grifo_id']) ? (int)$_POST['grifo_id'] : (int)($_POST['id'] ?? 0);
$nuevoEstado   = normalizar_estado($_POST['estado'] ?? '');
$motivo        = isset($_POST['motivo']) ? trim($_POST['motivo']) : null;
$fechaCambio   = $_POST['fecha_cambio']  ?? null; // cuando sale de ACTIVO (hacia no activo)
$fechaRegreso  = $_POST['fecha_regreso'] ?? null; // cuando vuelve a ACTIVO

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

$catalogo = [
  'activo'         => ['label' => 'Activo',         'badge' => 'bg-success'],
  'inactivo'       => ['label' => 'Inactivo',       'badge' => 'bg-secondary'],
  'mantenimiento'  => ['label' => 'Mantenimiento',  'badge' => 'bg-primary'],
  'desincorporado' => ['label' => 'Desincorporado', 'badge' => 'bg-danger'],
];

if (!isset($catalogo[$nuevoEstado])) {
  echo json_encode(['success' => false, 'message' => 'Estado inválido.']); exit;
}

// Motivo obligatorio para todo estado ≠ activo
if ($nuevoEstado !== 'activo' && ($motivo === null || $motivo === '')) {
  echo json_encode(['success' => false, 'message' => 'Debe ingresar el motivo del cambio.']); exit;
}
// Recortar motivo (y dejar NULL si vuelve a activo)
$motivo = ($nuevoEstado === 'activo') ? null : mb_substr($motivo, 0, 255);

// Definir fecha del evento (si no viene, usa hoy para no romper el flujo actual)
$fechaEvento = ($nuevoEstado === 'activo') ? ($fechaRegreso ?: hoy()) : ($fechaCambio ?: hoy());
if (!validarFechaISO($fechaEvento)) {
  $et = ($nuevoEstado === 'activo') ? 'fecha_regreso' : 'fecha_cambio';
  echo json_encode(['success' => false, 'message' => "Fecha inválida o faltante ($et)."]); exit;
}

/* ====================== Operación con historial ====================== */
try {
  $conn = new Conexion_BD();
  $db   = $conn->getConnection();

  $actorId  = $_SESSION['id_usuario'] ?? null; // <- se graba en grifo_estado_historial.actor_id
  $actorNom = $_SESSION['nombre'] ?? ($_SESSION['usuario'] ?? 'sistema');
  $actorRol = $_SESSION['rol'] ?? '';

  $db->begin_transaction();

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

  // 2) Gestionar historial (tabla: grifo_estado_historial)
  // Recuperar último período ABIERTO (si existe)
  $openId = null; $openEstado = null;
  $sql = "SELECT id, estado
          FROM grifo_estado_historial
          WHERE grifo_id = ? AND fecha_fin IS NULL
          ORDER BY id DESC
          LIMIT 1";
  if ($stmt = $db->prepare($sql)) {
    $stmt->bind_param("i", $idGrifo);
    $stmt->execute();
    $stmt->bind_result($openId, $openEstado);
    $stmt->fetch();
    $stmt->close();
  }

  if ($openId !== null) {
    if ($openEstado === $nuevoEstado) {
      // Mismo estado -> ajustar inicio/motivo/actor_id
      $sql = "UPDATE grifo_estado_historial
              SET fecha_inicio = ?, motivo = ?, actor_id = ?
              WHERE id = ?";
      $stmt = $db->prepare($sql);
      if (!$stmt) throw new Exception("Error prepare UPDATE historial (ajustar mismo estado): ".$db->error);
      $stmt->bind_param("ssii", $fechaEvento, $motivo, $actorId, $openId);
      if (!$stmt->execute()) throw new Exception("Error ejecutando UPDATE historial (ajustar mismo estado).");
      $stmt->close();
    } else {
      // Estado CAMBIA -> cerrar período abierto y crear nuevo
      $sql = "UPDATE grifo_estado_historial
              SET fecha_fin = ?, actor_id = ?
              WHERE id = ?";
      $stmt = $db->prepare($sql);
      if (!$stmt) throw new Exception("Error prepare UPDATE historial (cerrar): ".$db->error);
      $stmt->bind_param("sii", $fechaEvento, $actorId, $openId);
      if (!$stmt->execute()) throw new Exception("Error ejecutando UPDATE historial (cerrar).");
      $stmt->close();

      $sql = "INSERT INTO grifo_estado_historial
              (grifo_id, estado, fecha_inicio, fecha_fin, motivo, actor_id)
              VALUES (?,?,?,?,?,?)";
      $stmt = $db->prepare($sql);
      if (!$stmt) throw new Exception("Error prepare INSERT historial (nuevo): ".$db->error);
      $null = null;
      $stmt->bind_param("issssi", $idGrifo, $nuevoEstado, $fechaEvento, $null, $motivo, $actorId);
      if (!$stmt->execute()) throw new Exception("Error ejecutando INSERT historial (nuevo).");
      $stmt->close();
    }
  } else {
    // No hay período abierto -> crear uno directo con el nuevo estado
    $sql = "INSERT INTO grifo_estado_historial
            (grifo_id, estado, fecha_inicio, fecha_fin, motivo, actor_id)
            VALUES (?,?,?,?,?,?)";
    $stmt = $db->prepare($sql);
    if (!$stmt) throw new Exception("Error prepare INSERT historial (sin abierto): ".$db->error);
    $null = null;
    $stmt->bind_param("issssi", $idGrifo, $nuevoEstado, $fechaEvento, $null, $motivo, $actorId);
    if (!$stmt->execute()) throw new Exception("Error ejecutando INSERT historial (sin abierto).");
    $stmt->close();
  }

  // 3) Actualizar grifos
  $sql = "UPDATE grifos SET estado = ?, motivo_estado = ? WHERE id = ?";
  $stmt = $db->prepare($sql);
  if (!$stmt) throw new Exception("Error prepare UPDATE grifos: ".$db->error);
  $stmt->bind_param("ssi", $nuevoEstado, $motivo, $idGrifo);
  if (!$stmt->execute()) throw new Exception("Error ejecutando UPDATE grifos.");
  $stmt->close();

  // 4) Auditoría
  $descripcion = "Se cambió el estado del grifo ID {$idGrifo} a {$catalogo[$nuevoEstado]['label']} (fecha: {$fechaEvento})";
  $observacion = $motivo ? "Motivo: {$motivo}" : "";
  registrarAuditoria(
    'grifos',          // modulo
    'cambiar_estado',  // accion
    $descripcion,      // descripcion
    $actorId ?? 0,     // id_usuario (actor)
    $actorNom,         // nombre_usuario
    'grifos',          // tabla_afectada
    $idGrifo,          // id_registro_afectado
    $actorRol,         // tipo_usuario
    $observacion       // observacion
  );

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

  echo json_encode([
    'success' => true,
    'message' => "El estado del grifo ha sido actualizado a \"{$catalogo[$nuevoEstado]['label']}\".",
    'data'    => [
      'id'            => $idGrifo,
      'estado'        => $nuevoEstado,
      'label'         => $catalogo[$nuevoEstado]['label'],
      'badge'         => $catalogo[$nuevoEstado]['badge'],
      'fecha_evento'  => $fechaEvento
    ],
  ], JSON_UNESCAPED_UNICODE);

} catch (Throwable $e) {
  if (isset($db))  { $db->rollback(); }
  if (isset($conn)) { $conn->closeConnection(); }
  echo json_encode([
    'success' => false,
    'message' => 'Error en el servidor: '.$e->getMessage(),
  ]);
}
