-- V002__create_refresh_token.sql
-- Creates dbo.RefreshToken table for opaque token rotation with chain revocation
-- Run on: SIGCM2 (prod) and SIGCM2_Test (integration tests)

SET QUOTED_IDENTIFIER ON;
SET ANSI_NULLS ON;
GO

IF OBJECT_ID(N'dbo.RefreshToken', N'U') IS NOT NULL
BEGIN
    PRINT 'Table dbo.RefreshToken already exists — skipping.';
    RETURN;
END
GO

CREATE TABLE dbo.RefreshToken
(
    Id            INT IDENTITY(1,1)  NOT NULL,
    UsuarioId     INT                NOT NULL,
    TokenHash     NVARCHAR(88)       NOT NULL,   -- SHA-256 base64url = 43 chars sin padding; margen a 88
    FamilyId      UNIQUEIDENTIFIER   NOT NULL,   -- una familia = una sesion de login
    IssuedAt      DATETIME2(3)       NOT NULL,
    ExpiresAt     DATETIME2(3)       NOT NULL,   -- absolute: heredado en cada rotacion
    RevokedAt     DATETIME2(3)       NULL,
    ReplacedById  INT                NULL,
    CreatedByIp   VARCHAR(45)        NOT NULL,   -- IPv4/IPv6 textual
    UserAgent     NVARCHAR(512)      NULL,

    CONSTRAINT PK_RefreshToken PRIMARY KEY CLUSTERED (Id),
    CONSTRAINT FK_RefreshToken_Usuario
        FOREIGN KEY (UsuarioId) REFERENCES dbo.Usuario(Id),
    CONSTRAINT FK_RefreshToken_ReplacedBy
        FOREIGN KEY (ReplacedById) REFERENCES dbo.RefreshToken(Id),
    CONSTRAINT UQ_RefreshToken_TokenHash UNIQUE (TokenHash)
);
GO

-- Lookup por familia para chain revocation
CREATE INDEX IX_RefreshToken_UsuarioId_FamilyId
    ON dbo.RefreshToken (UsuarioId, FamilyId);
GO

-- Indice filtrado para revocaciones masivas de activos
CREATE INDEX IX_RefreshToken_Active
    ON dbo.RefreshToken (UsuarioId, FamilyId)
    WHERE RevokedAt IS NULL;
GO

-- Housekeeping futuro
CREATE INDEX IX_RefreshToken_ExpiresAt
    ON dbo.RefreshToken (ExpiresAt)
    WHERE RevokedAt IS NULL;
GO

EXEC sys.sp_addextendedproperty
    @name = N'MS_Description',
    @value = N'Refresh tokens opacos (SHA-256 hash) con rotacion y chain revocation por familia',
    @level0type = N'SCHEMA', @level0name = N'dbo',
    @level1type = N'TABLE',  @level1name = N'RefreshToken';
GO

PRINT 'Table dbo.RefreshToken created successfully.';
GO
