/*
庆安数字孪生可视化看板 - 前端埋点数据库对象
目标数据库：DDV_AQ
用途：
1. 创建前端埋点日志表 dbo.TV_前端埋点事件日志
2. 创建写入存储过程 dbo.TV_前端埋点事件_写入
3. 创建清理存储过程 dbo.TV_前端埋点事件日志_清理
4. 前端页面启动时调用清理过程，小批量清理 365 天以前的数据
*/

IF OBJECT_ID(N'dbo.TV_前端埋点事件日志', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.[TV_前端埋点事件日志]
    (
        [ID] BIGINT IDENTITY(1,1) NOT NULL CONSTRAINT [PK_TV_前端埋点事件日志] PRIMARY KEY,
        [app_id] NVARCHAR(100) NOT NULL,
        [app_version] NVARCHAR(50) NULL,
        [env] NVARCHAR(20) NULL,
        [page_path] NVARCHAR(500) NULL,
        [referrer] NVARCHAR(500) NULL,
        [trace_id] NVARCHAR(100) NULL,
        [session_id] NVARCHAR(100) NULL,
        [user_id] NVARCHAR(100) NULL,
        [timestamp] BIGINT NULL,
        [client_ip] NVARCHAR(64) NULL,
        [client_info] NVARCHAR(MAX) NULL,
        [event_type] NVARCHAR(50) NOT NULL,
        [event_name] NVARCHAR(100) NOT NULL,
        [event_level] NVARCHAR(20) NULL,
        [event_data] NVARCHAR(MAX) NULL,
        [duration_ms] INT NULL,
        [success] BIT NULL,
        [error_code] NVARCHAR(100) NULL,
        [error_message] NVARCHAR(MAX) NULL,
        [create_time] DATETIME2(0) NOT NULL CONSTRAINT [DF_TV_前端埋点事件日志_create_time] DEFAULT SYSDATETIME()
    );
END;
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_TV_前端埋点事件日志_create_time' AND object_id = OBJECT_ID(N'dbo.TV_前端埋点事件日志'))
    CREATE INDEX [IX_TV_前端埋点事件日志_create_time] ON dbo.[TV_前端埋点事件日志]([create_time] DESC);
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_TV_前端埋点事件日志_trace_id' AND object_id = OBJECT_ID(N'dbo.TV_前端埋点事件日志'))
    CREATE INDEX [IX_TV_前端埋点事件日志_trace_id] ON dbo.[TV_前端埋点事件日志]([trace_id]);
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_TV_前端埋点事件日志_session_time' AND object_id = OBJECT_ID(N'dbo.TV_前端埋点事件日志'))
    CREATE INDEX [IX_TV_前端埋点事件日志_session_time] ON dbo.[TV_前端埋点事件日志]([session_id], [timestamp]);
GO

IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_TV_前端埋点事件日志_event_time' AND object_id = OBJECT_ID(N'dbo.TV_前端埋点事件日志'))
    CREATE INDEX [IX_TV_前端埋点事件日志_event_time] ON dbo.[TV_前端埋点事件日志]([event_name], [create_time] DESC);
GO

CREATE OR ALTER PROCEDURE dbo.[TV_前端埋点事件日志_清理]
    @retention_days INT = 365,
    @batch_size INT = 2000,
    @return_result BIT = 1
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @safe_retention_days INT = CASE WHEN ISNULL(@retention_days, 365) < 1 THEN 365 ELSE @retention_days END;
    DECLARE @safe_batch_size INT = CASE WHEN ISNULL(@batch_size, 2000) < 1 THEN 2000 ELSE @batch_size END;
    DECLARE @cutoff_time DATETIME2(0) = DATEADD(DAY, -@safe_retention_days, SYSDATETIME());

    DELETE TOP (@safe_batch_size)
    FROM dbo.[TV_前端埋点事件日志]
    WHERE [create_time] < @cutoff_time;

    DECLARE @deleted_count INT = @@ROWCOUNT;

    IF @return_result = 1
    BEGIN
        SELECT N'1' AS result, @deleted_count AS deleted_count, @cutoff_time AS cutoff_time;
    END;
END;
GO

CREATE OR ALTER PROCEDURE dbo.[TV_前端埋点事件_写入]
    @app_id NVARCHAR(100),
    @app_version NVARCHAR(50) = NULL,
    @env NVARCHAR(20) = NULL,
    @page_path NVARCHAR(500) = NULL,
    @referrer NVARCHAR(500) = NULL,
    @trace_id NVARCHAR(100) = NULL,
    @session_id NVARCHAR(100) = NULL,
    @user_id NVARCHAR(100) = NULL,
    @timestamp NVARCHAR(30) = NULL,
    @client_ip NVARCHAR(64) = NULL,
    @client_info NVARCHAR(MAX) = NULL,
    @event_type NVARCHAR(50),
    @event_name NVARCHAR(100),
    @event_level NVARCHAR(20) = NULL,
    @event_data NVARCHAR(MAX) = NULL,
    @duration_ms NVARCHAR(30) = NULL,
    @success NVARCHAR(10) = NULL,
    @error_code NVARCHAR(100) = NULL,
    @error_message NVARCHAR(MAX) = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @success_bit BIT = NULL;
    IF NULLIF(LTRIM(RTRIM(@success)), N'') IS NOT NULL
    BEGIN
        SET @success_bit = CASE
            WHEN UPPER(LTRIM(RTRIM(@success))) IN (N'1', N'TRUE', N'YES', N'是') THEN 1
            ELSE 0
        END;
    END;

    INSERT INTO dbo.[TV_前端埋点事件日志]
    (
        [app_id], [app_version], [env], [page_path], [referrer],
        [trace_id], [session_id], [user_id], [timestamp], [client_ip],
        [client_info], [event_type], [event_name], [event_level], [event_data],
        [duration_ms], [success], [error_code], [error_message]
    )
    VALUES
    (
        NULLIF(@app_id, N''), NULLIF(@app_version, N''), NULLIF(@env, N''), NULLIF(@page_path, N''), NULLIF(@referrer, N''),
        NULLIF(@trace_id, N''), NULLIF(@session_id, N''), NULLIF(@user_id, N''), TRY_CONVERT(BIGINT, NULLIF(@timestamp, N'')), NULLIF(@client_ip, N''),
        NULLIF(@client_info, N''), NULLIF(@event_type, N''), NULLIF(@event_name, N''), NULLIF(@event_level, N''), NULLIF(@event_data, N''),
        TRY_CONVERT(INT, NULLIF(@duration_ms, N'')), @success_bit, NULLIF(@error_code, N''), NULLIF(@error_message, N'')
    );

    SELECT CAST(SCOPE_IDENTITY() AS BIGINT) AS ID, N'1' AS result, N'写入成功' AS message;
END;
GO
