-- V023_ROLLBACK.sql
-- PRC-001: Reversa de V023__refactor_chargeable_char_config_to_product_type.sql.
--
-- ADVERTENCIA: rollback destructivo — elimina ProductTypeId y restaura MedioId.
--   - Todos los datos de ProductTypeId se pierden.
--   - Las filas globales (ProductTypeId NULL) se preservan como globales (MedioId NULL).
--   - El historial temporal puede quedar inconsistente si la tabla fue modificada después.
--
-- Solo para uso en DEV/TEST. No ejecutar en producción si hay datos de ProductTypeId.
-- Run on: SIGCM2 (dev), SIGCM2_Test_App, SIGCM2_Test_Api.

SET QUOTED_IDENTIFIER ON;
SET ANSI_NULLS ON;
SET NOCOUNT ON;
GO

-- ─── 1. Drop new SPs ────────────────────────────────────────────────────────

IF OBJECT_ID('dbo.usp_ChargeableCharConfig_ReactivateWithGuard', 'P') IS NOT NULL
BEGIN
    DROP PROCEDURE dbo.usp_ChargeableCharConfig_ReactivateWithGuard;
    PRINT 'V023 ROLLBACK: usp_ChargeableCharConfig_ReactivateWithGuard dropped.';
END
GO

IF OBJECT_ID('dbo.usp_ChargeableCharConfig_GetActiveForProductType', 'P') IS NOT NULL
BEGIN
    DROP PROCEDURE dbo.usp_ChargeableCharConfig_GetActiveForProductType;
    PRINT 'V023 ROLLBACK: usp_ChargeableCharConfig_GetActiveForProductType dropped.';
END
GO

IF OBJECT_ID('dbo.usp_ChargeableCharConfig_InsertWithClose', 'P') IS NOT NULL
BEGIN
    DROP PROCEDURE dbo.usp_ChargeableCharConfig_InsertWithClose;
    PRINT 'V023 ROLLBACK: usp_ChargeableCharConfig_InsertWithClose dropped.';
END
GO

-- ─── 2. Reverse table alterations if ProductTypeId column exists ─────────────

IF EXISTS (SELECT 1 FROM sys.tables WHERE name = 'ChargeableCharConfig' AND schema_id = SCHEMA_ID('dbo'))
   AND EXISTS (SELECT 1 FROM sys.columns
               WHERE object_id = OBJECT_ID('dbo.ChargeableCharConfig')
                 AND name = 'ProductTypeId')
BEGIN
    -- 2a. Turn off SYSTEM_VERSIONING
    ALTER TABLE dbo.ChargeableCharConfig SET (SYSTEM_VERSIONING = OFF);
    PRINT 'V023 ROLLBACK: SYSTEM_VERSIONING = OFF.';

    -- 2b. Drop indexes on ProductTypeId
    IF EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'UX_ChargeableCharConfig_Vigente'
               AND object_id = OBJECT_ID('dbo.ChargeableCharConfig'))
    BEGIN
        DROP INDEX UX_ChargeableCharConfig_Vigente ON dbo.ChargeableCharConfig;
        PRINT 'V023 ROLLBACK: UX_ChargeableCharConfig_Vigente dropped.';
    END

    IF EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_ChargeableCharConfig_Query'
               AND object_id = OBJECT_ID('dbo.ChargeableCharConfig'))
    BEGIN
        DROP INDEX IX_ChargeableCharConfig_Query ON dbo.ChargeableCharConfig;
        PRINT 'V023 ROLLBACK: IX_ChargeableCharConfig_Query dropped.';
    END

    -- 2c. Drop FK to ProductType
    DECLARE @fk_pt sysname;
    SELECT @fk_pt = name
      FROM sys.foreign_keys
     WHERE parent_object_id = OBJECT_ID('dbo.ChargeableCharConfig')
       AND referenced_object_id = OBJECT_ID('dbo.ProductType');
    IF @fk_pt IS NOT NULL
    BEGIN
        EXEC('ALTER TABLE dbo.ChargeableCharConfig DROP CONSTRAINT ' + @fk_pt);
        PRINT 'V023 ROLLBACK: FK_ChargeableCharConfig_ProductType dropped.';
    END

    -- 2d. Drop NonNegative price check; restore Positive check
    IF EXISTS (SELECT 1 FROM sys.check_constraints
               WHERE name = 'CK_ChargeableCharConfig_Price_NonNegative'
                 AND parent_object_id = OBJECT_ID('dbo.ChargeableCharConfig'))
    BEGIN
        ALTER TABLE dbo.ChargeableCharConfig DROP CONSTRAINT CK_ChargeableCharConfig_Price_NonNegative;
        PRINT 'V023 ROLLBACK: CK_ChargeableCharConfig_Price_NonNegative dropped.';
    END

    IF NOT EXISTS (SELECT 1 FROM sys.check_constraints
                   WHERE name = 'CK_ChargeableCharConfig_Price_Positive'
                     AND parent_object_id = OBJECT_ID('dbo.ChargeableCharConfig'))
    BEGIN
        ALTER TABLE dbo.ChargeableCharConfig
            ADD CONSTRAINT CK_ChargeableCharConfig_Price_Positive CHECK (PricePerUnit > 0);
        PRINT 'V023 ROLLBACK: CK_ChargeableCharConfig_Price_Positive restored.';
    END

    -- 2e. Drop ProductTypeId column from main + history
    ALTER TABLE dbo.ChargeableCharConfig DROP COLUMN ProductTypeId;
    PRINT 'V023 ROLLBACK: ProductTypeId dropped from ChargeableCharConfig.';

    IF EXISTS (SELECT 1 FROM sys.columns
               WHERE object_id = OBJECT_ID('dbo.ChargeableCharConfig_History')
                 AND name = 'ProductTypeId')
    BEGIN
        ALTER TABLE dbo.ChargeableCharConfig_History DROP COLUMN ProductTypeId;
        PRINT 'V023 ROLLBACK: ProductTypeId dropped from ChargeableCharConfig_History.';
    END

    -- 2f. Restore MedioId column
    ALTER TABLE dbo.ChargeableCharConfig ADD MedioId INT NULL;
    ALTER TABLE dbo.ChargeableCharConfig_History ADD MedioId INT NULL;
    PRINT 'V023 ROLLBACK: MedioId restored.';

    -- 2g. Restore FK to Medio
    ALTER TABLE dbo.ChargeableCharConfig
        ADD CONSTRAINT FK_ChargeableCharConfig_Medio
        FOREIGN KEY (MedioId) REFERENCES dbo.Medio(Id) ON DELETE NO ACTION;
    PRINT 'V023 ROLLBACK: FK_ChargeableCharConfig_Medio restored.';

    -- 2h. Restore indexes on MedioId
    CREATE UNIQUE NONCLUSTERED INDEX UX_ChargeableCharConfig_Vigente
        ON dbo.ChargeableCharConfig (MedioId, Symbol)
        WHERE ValidTo IS NULL;
    PRINT 'V023 ROLLBACK: UX_ChargeableCharConfig_Vigente restored (MedioId).';

    CREATE NONCLUSTERED INDEX IX_ChargeableCharConfig_Query
        ON dbo.ChargeableCharConfig (MedioId, Symbol, ValidFrom, ValidTo)
        INCLUDE (PricePerUnit, IsActive, Category);
    PRINT 'V023 ROLLBACK: IX_ChargeableCharConfig_Query restored (MedioId).';

    -- 2i. Restore SYSTEM_VERSIONING
    ALTER TABLE dbo.ChargeableCharConfig
        SET (SYSTEM_VERSIONING = ON (
            HISTORY_TABLE = dbo.ChargeableCharConfig_History,
            HISTORY_RETENTION_PERIOD = 10 YEARS
        ));
    PRINT 'V023 ROLLBACK: SYSTEM_VERSIONING = ON restored.';
END
ELSE
    PRINT 'V023 ROLLBACK: ProductTypeId column not found — table already in MedioId state or missing, skipping.';
GO

-- ─── 3. Restore original SPs ────────────────────────────────────────────────

IF OBJECT_ID('dbo.usp_ChargeableCharConfig_InsertWithClose', 'P') IS NULL
    EXEC('CREATE PROCEDURE dbo.usp_ChargeableCharConfig_InsertWithClose AS RETURN 0');
GO

ALTER PROCEDURE dbo.usp_ChargeableCharConfig_InsertWithClose
    @MedioId      INT           = NULL,
    @Symbol       NVARCHAR(4),
    @Category     NVARCHAR(32),
    @PricePerUnit DECIMAL(18,4),
    @ValidFrom    DATE,
    @NewId        BIGINT OUTPUT,
    @ClosedId     BIGINT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

    BEGIN TRY
        BEGIN TRANSACTION;

        IF @MedioId IS NOT NULL
           AND NOT EXISTS (SELECT 1 FROM dbo.Medio WITH (NOLOCK) WHERE Id = @MedioId)
        BEGIN
            ROLLBACK;
            THROW 50404, 'Medio not found', 1;
        END

        DECLARE @ActiveId BIGINT, @ActiveValidFrom DATE;
        SELECT TOP 1
            @ActiveId        = Id,
            @ActiveValidFrom = ValidFrom
        FROM dbo.ChargeableCharConfig WITH (UPDLOCK, HOLDLOCK, ROWLOCK)
        WHERE ((@MedioId IS NULL     AND MedioId IS NULL)
            OR (@MedioId IS NOT NULL AND MedioId = @MedioId))
          AND Symbol  = @Symbol
          AND ValidTo IS NULL;

        IF @ActiveId IS NOT NULL AND @ValidFrom <= @ActiveValidFrom
        BEGIN
            ROLLBACK;
            THROW 50409, 'ChargeableCharConfigForwardOnly: new ValidFrom must be > active.ValidFrom', 1;
        END

        IF @ActiveId IS NOT NULL
        BEGIN
            UPDATE dbo.ChargeableCharConfig
               SET ValidTo = DATEADD(DAY, -1, @ValidFrom)
             WHERE Id = @ActiveId;
            SET @ClosedId = @ActiveId;
        END
        ELSE
            SET @ClosedId = NULL;

        INSERT INTO dbo.ChargeableCharConfig
            (MedioId, Symbol, Category, PricePerUnit, ValidFrom, ValidTo, IsActive)
        VALUES
            (@MedioId, @Symbol, @Category, @PricePerUnit, @ValidFrom, NULL, 1);
        SET @NewId = SCOPE_IDENTITY();

        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
        THROW;
    END CATCH
END
GO

IF OBJECT_ID('dbo.usp_ChargeableCharConfig_GetActiveForMedio', 'P') IS NULL
    EXEC('CREATE PROCEDURE dbo.usp_ChargeableCharConfig_GetActiveForMedio AS RETURN 0');
GO

ALTER PROCEDURE dbo.usp_ChargeableCharConfig_GetActiveForMedio
    @MedioId  INT,
    @AsOfDate DATE
AS
BEGIN
    SET NOCOUNT ON;
    WITH Candidates AS (
        SELECT
            Id, MedioId, Symbol, Category, PricePerUnit, ValidFrom, ValidTo, IsActive,
            ROW_NUMBER() OVER (
                PARTITION BY Symbol
                ORDER BY
                    CASE WHEN MedioId = @MedioId THEN 0 ELSE 1 END,
                    ValidFrom DESC
            ) AS rn
        FROM dbo.ChargeableCharConfig
        WHERE IsActive   = 1
          AND ValidFrom <= @AsOfDate
          AND (ValidTo IS NULL OR ValidTo >= @AsOfDate)
          AND (MedioId = @MedioId OR MedioId IS NULL)
    )
    SELECT Id, MedioId, Symbol, Category, PricePerUnit, ValidFrom, ValidTo, IsActive
    FROM   Candidates
    WHERE  rn = 1;
END
GO

PRINT '';
PRINT 'V023 ROLLBACK complete — ChargeableCharConfig restored to MedioId model.';
GO
