-- =============================================================================
--  ACTIVAR LA RÉPLICA INVERSA (Reservaciones V2 → portal) — devuelve el esquema retirado
--
--  Proyecto : CL032BACK (portal público)   ·   Esquema: asturias_api
--  Archivo  : docs/replicacion/sql/activar_replica_inversa.sql
--  Guía     : docs/replicacion/07-ACTIVACION-PASO-A-PASO.md
-- =============================================================================
--
--  ESTE SCRIPT ES **EL PASO 1** DE LA ACTIVACIÓN, NO LA ACTIVACIÓN ENTERA.
--  Devuelve las columnas e índices. Falta después: configuración, .env, Reservaciones V2 y las
--  pruebas de aceptación. El orden completo está en 07-ACTIVACION-PASO-A-PASO.md y NO es
--  intercambiable — encender la aplicación antes que el esquema devuelve 500 en cada
--  réplica; encender Reservaciones V2 antes que el endpoint hace que descarte marcas sin reintentar.
--
--  IDEMPOTENTE: cada bloque comprueba si la columna ya existe antes de crearla, así que se
--  puede ejecutar varias veces sin error.
--
--  CÓMO EJECUTAR
--    mysql -u USUARIO -p asturias_api < activar_replica_inversa.sql
-- =============================================================================


-- -----------------------------------------------------------------------------
-- 0. Requisito previo: la frontera de maestría debe existir
--
--    Si esto falla, NO sigas: falta la Fase 0 completa
--    (database/sql/rsv_reservacion_add_maestria.sql). Sin maestría el canal inverso no
--    tiene sentido — el portal seguiría pisando al privado.
-- -----------------------------------------------------------------------------
SELECT IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'rsv_reservacion'
      AND COLUMN_NAME = 'reservacionMaestro') = 1,
  'OK: la frontera de maestria existe',
  'ABORTA: falta reservacionMaestro. Aplica primero rsv_reservacion_add_maestria.sql'
) AS requisito_previo;


-- -----------------------------------------------------------------------------
-- 1. ESTADO DE RÉPLICA en la cabecera
--    (equivale a 2026_08_18_140000_add_estado_replica_to_rsv_reservacion)
--
--    `reservacionVersionReplica` es la pieza que suele olvidarse: sin ella, dos snapshots
--    encolados que lleguen en orden inverso harían que el socio viera un cambio deshacerse
--    solo. Con ella, el portal rechaza con 409 cualquier versión <= la ya aplicada.
-- -----------------------------------------------------------------------------
SET @sql := IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'rsv_reservacion'
      AND COLUMN_NAME = 'reservacionVersionReplica') = 0,
  "ALTER TABLE `rsv_reservacion`
     ADD COLUMN `reservacionVersionReplica` BIGINT NOT NULL DEFAULT 0
         COMMENT 'Ultima replicaSalidaVersion de Reservaciones V2 aplicada. Rechaza versiones obsoletas (409).'
         AFTER `reservacionNoPrivado`,
     ADD COLUMN `reservacionHashReplica` CHAR(64)
         CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL
         COMMENT 'sha256 del ultimo snapshot aplicado. Corta reintentos con 200 sin_cambios.'
         AFTER `reservacionVersionReplica`,
     ADD COLUMN `reservacionFechaReplica` DATETIME NULL DEFAULT NULL
         COMMENT 'Instante en que se aplico la ultima replica inversa.'
         AFTER `reservacionHashReplica`",
  "SELECT 'ya existe: estado de replica en rsv_reservacion'"
);
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;


-- -----------------------------------------------------------------------------
-- 2. PUNTEROS DE ORIGEN del detalle
--    (equivale a 2026_08_18_130000_add_punteros_privado_to_rsv_detalle)
--
--    EL UNIQUE ES COMPUESTO CON EL PADRE, no suelto: el puntero solo debe ser único dentro
--    de su reservación (o de su habitación). Un índice global convertiría un payload mal
--    formado en un 500 por violación de índice, en vez de un rechazo controlado.
--
--    NULL = "aún no adoptada". MySQL admite múltiples NULL en un UNIQUE, así que todo lo
--    anterior convive sin conflicto.
-- -----------------------------------------------------------------------------
SET @sql := IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'rsv_reservacionhabitacion'
      AND COLUMN_NAME = 'idReservacionHabitacionPrivado') = 0,
  "ALTER TABLE `rsv_reservacionhabitacion`
     ADD COLUMN `idReservacionHabitacionPrivado` INT NULL DEFAULT NULL
         COMMENT 'PK de rsv_reservacionhabitacion en Reservaciones V2. NULL = aun no adoptada.'
         AFTER `idReservacion`,
     ADD UNIQUE INDEX `uq_rh_privado` (`idReservacion`, `idReservacionHabitacionPrivado`)",
  "SELECT 'ya existe: idReservacionHabitacionPrivado'"
);
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;

SET @sql := IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'rsv_reservacionhabitacionpaquete'
      AND COLUMN_NAME = 'idReservacionHabitacionPaquetePrivado') = 0,
  "ALTER TABLE `rsv_reservacionhabitacionpaquete`
     ADD COLUMN `idReservacionHabitacionPaquetePrivado` INT NULL DEFAULT NULL
         COMMENT 'PK de rsv_reservacionhabitacionpaquete en Reservaciones V2. NULL = aun no adoptada.'
         AFTER `idReservacionHabitacion`,
     ADD UNIQUE INDEX `uq_rhp_privado` (`idReservacionHabitacion`, `idReservacionHabitacionPaquetePrivado`)",
  "SELECT 'ya existe: idReservacionHabitacionPaquetePrivado'"
);
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;

SET @sql := IF(
  (SELECT COUNT(*) FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'rsv_reservacionhabitacionextra'
      AND COLUMN_NAME = 'idReservacionHabitacionExtraPrivado') = 0,
  "ALTER TABLE `rsv_reservacionhabitacionextra`
     ADD COLUMN `idReservacionHabitacionExtraPrivado` INT NULL DEFAULT NULL
         COMMENT 'PK de rsv_reservacionhabitacionextra en Reservaciones V2. NULL = aun no adoptada.'
         AFTER `idReservacionHabitacion`,
     ADD UNIQUE INDEX `uq_rhe_privado` (`idReservacionHabitacion`, `idReservacionHabitacionExtraPrivado`)",
  "SELECT 'ya existe: idReservacionHabitacionExtraPrivado'"
);
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;


-- -----------------------------------------------------------------------------
-- 3. RESTAURAR LOS PUNTEROS RESPALDADOS (si hubo desactivación previa)
--
--    Evita que la primera réplica de cada reservación caiga al camino de respaldo
--    (reemplazo completo del detalle + incidencia R12). Si no existe el respaldo, este
--    bloque no hace nada y tampoco pasa nada: el respaldo es una comodidad, no un requisito.
-- -----------------------------------------------------------------------------
SET @sql := IF(
  (SELECT COUNT(*) FROM information_schema.TABLES
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'bkp_replica_inversa_punteros') = 1,
  "UPDATE `rsv_reservacion` r
     JOIN `bkp_replica_inversa_punteros` b ON b.`idReservacion` = r.`idReservacion`
      SET r.`reservacionVersionReplica` = IFNULL(b.`reservacionVersionReplica`, 0),
          r.`reservacionHashReplica`    = b.`reservacionHashReplica`,
          r.`reservacionFechaReplica`   = b.`reservacionFechaReplica`",
  "SELECT 'sin respaldo que restaurar (cabecera)'"
);
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;

SET @sql := IF(
  (SELECT COUNT(*) FROM information_schema.TABLES
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'bkp_replica_inversa_punteros') = 1,
  "UPDATE `rsv_reservacionhabitacion` h
     JOIN `bkp_replica_inversa_punteros` b
       ON b.`idReservacionHabitacion` = h.`idReservacionHabitacion`
      SET h.`idReservacionHabitacionPrivado` = b.`idReservacionHabitacionPrivado`
    WHERE b.`idReservacionHabitacionPrivado` IS NOT NULL",
  "SELECT 'sin respaldo que restaurar (detalle)'"
);
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;

-- Los punteros de paquetes y extras NO se respaldaron: al reactivar, la primera réplica de
-- cada habitación los reinserta desde el snapshot con sus punteros correctos. Se respaldó
-- solo el nivel habitación porque es el que decide si hay adopción por respaldo o no.


-- -----------------------------------------------------------------------------
-- 4. REGISTRO DE MIGRACIONES
--
--    Se reinstalan las filas de control para que `migrate:status` diga la verdad y
--    `php artisan migrate` no intente reejecutarlas.
-- -----------------------------------------------------------------------------
SET @batch := (SELECT IFNULL(MAX(`batch`), 0) + 1 FROM `migrations`);

INSERT INTO `migrations` (`migration`, `batch`)
SELECT '2026_08_18_130000_add_punteros_privado_to_rsv_detalle', @batch FROM DUAL
 WHERE NOT EXISTS (SELECT 1 FROM `migrations`
   WHERE `migration` = '2026_08_18_130000_add_punteros_privado_to_rsv_detalle');

INSERT INTO `migrations` (`migration`, `batch`)
SELECT '2026_08_18_140000_add_estado_replica_to_rsv_reservacion', @batch FROM DUAL
 WHERE NOT EXISTS (SELECT 1 FROM `migrations`
   WHERE `migration` = '2026_08_18_140000_add_estado_replica_to_rsv_reservacion');


-- =============================================================================
--  5. VERIFICACIÓN
-- =============================================================================
--  SHOW COLUMNS FROM `rsv_reservacion`                LIKE 'reservacion%Replica';  -- 3 filas
--  SHOW COLUMNS FROM `rsv_reservacionhabitacion`      LIKE '%Privado';             -- 1 fila
--  SHOW COLUMNS FROM `rsv_reservacionhabitacionpaquete` LIKE '%Privado';           -- 1 fila
--  SHOW COLUMNS FROM `rsv_reservacionhabitacionextra` LIKE '%Privado';             -- 1 fila
--
--  SHOW INDEX FROM `rsv_reservacionhabitacion` WHERE Key_name = 'uq_rh_privado';
--
--  ⚠ EL ESQUEMA NO ES LA ACTIVACIÓN. Continúa con el paso 2 de
--    docs/replicacion/07-ACTIVACION-PASO-A-PASO.md (configuración y .env).
--
--  Una vez verificado y con el canal estable, el respaldo se puede soltar:
--    -- DROP TABLE IF EXISTS `bkp_replica_inversa_punteros`;
-- =============================================================================
--  FIN
-- =============================================================================
