-- 安全相关数据库表结构
-- 创建时间: 2026-04-01

-- 用户表
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sec_users]') AND type in (N'U'))
BEGIN
    CREATE TABLE [dbo].[sec_users] (
        [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
        [Username] NVARCHAR(50) NOT NULL UNIQUE,
        [DisplayName] NVARCHAR(100) NOT NULL,
        [Email] NVARCHAR(255) NOT NULL,
        [PhoneNumber] NVARCHAR(20) NULL,
        [PasswordHash] NVARCHAR(255) NOT NULL,
        [PasswordSalt] NVARCHAR(255) NOT NULL,
        [Status] INT NOT NULL DEFAULT 0, -- 0:Enabled, 1:Disabled, 2:Locked, 3:Deleted
        [LastLoginAtUtc] DATETIME2 NULL,
        [LastLoginIp] NVARCHAR(45) NULL,
        [LoginFailedCount] INT NOT NULL DEFAULT 0,
        [LockedUntilUtc] DATETIME2 NULL,
        [IsFirstLogin] BIT NOT NULL DEFAULT 1,
        [CreatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [UpdatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [CreatedBy] NVARCHAR(100) NOT NULL,
        [UpdatedBy] NVARCHAR(100) NOT NULL,
        [Remark] NVARCHAR(500) NULL
    );
    
    CREATE INDEX [IX_sec_users_Username] ON [dbo].[sec_users] ([Username]);
    CREATE INDEX [IX_sec_users_Email] ON [dbo].[sec_users] ([Email]);
    CREATE INDEX [IX_sec_users_Status] ON [dbo].[sec_users] ([Status]);
END

-- 角色表
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sec_roles]') AND type in (N'U'))
BEGIN
    CREATE TABLE [dbo].[sec_roles] (
        [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
        [Name] NVARCHAR(50) NOT NULL UNIQUE,
        [DisplayName] NVARCHAR(100) NOT NULL,
        [Description] NVARCHAR(500) NULL,
        [Status] INT NOT NULL DEFAULT 0, -- 0:Enabled, 1:Disabled
        [IsSystemRole] BIT NOT NULL DEFAULT 0,
        [SortOrder] INT NOT NULL DEFAULT 0,
        [CreatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [UpdatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [CreatedBy] NVARCHAR(100) NOT NULL,
        [UpdatedBy] NVARCHAR(100) NOT NULL,
        [Remark] NVARCHAR(500) NULL
    );
    
    CREATE INDEX [IX_sec_roles_Name] ON [dbo].[sec_roles] ([Name]);
    CREATE INDEX [IX_sec_roles_Status] ON [dbo].[sec_roles] ([Status]);
END

-- 权限表
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sec_permissions]') AND type in (N'U'))
BEGIN
    CREATE TABLE [dbo].[sec_permissions] (
        [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
        [Code] NVARCHAR(100) NOT NULL UNIQUE,
        [Name] NVARCHAR(100) NOT NULL,
        [Description] NVARCHAR(500) NULL,
        [Type] INT NOT NULL DEFAULT 0, -- 0:Page, 1:Function, 2:Data, 3:Api
        [Module] NVARCHAR(50) NOT NULL,
        [Action] NVARCHAR(50) NOT NULL,
        [Status] INT NOT NULL DEFAULT 0, -- 0:Enabled, 1:Disabled
        [IsSystemPermission] BIT NOT NULL DEFAULT 0,
        [ParentId] UNIQUEIDENTIFIER NULL,
        [SortOrder] INT NOT NULL DEFAULT 0,
        [CreatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [UpdatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [CreatedBy] NVARCHAR(100) NOT NULL,
        [UpdatedBy] NVARCHAR(100) NOT NULL,
        [Remark] NVARCHAR(500) NULL,
        CONSTRAINT [FK_sec_permissions_sec_permissions] FOREIGN KEY ([ParentId]) REFERENCES [dbo].[sec_permissions] ([Id])
    );
    
    CREATE INDEX [IX_sec_permissions_Code] ON [dbo].[sec_permissions] ([Code]);
    CREATE INDEX [IX_sec_permissions_Module] ON [dbo].[sec_permissions] ([Module]);
    CREATE INDEX [IX_sec_permissions_Status] ON [dbo].[sec_permissions] ([Status]);
    CREATE INDEX [IX_sec_permissions_ParentId] ON [dbo].[sec_permissions] ([ParentId]);
END

-- 用户角色关联表
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sec_user_roles]') AND type in (N'U'))
BEGIN
    CREATE TABLE [dbo].[sec_user_roles] (
        [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
        [UserId] UNIQUEIDENTIFIER NOT NULL,
        [RoleId] UNIQUEIDENTIFIER NOT NULL,
        [GrantedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [GrantedBy] NVARCHAR(100) NOT NULL,
        [ExpiresAtUtc] DATETIME2 NULL,
        [IsEnabled] BIT NOT NULL DEFAULT 1,
        [CreatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [CreatedBy] NVARCHAR(100) NOT NULL,
        CONSTRAINT [FK_sec_user_roles_sec_users] FOREIGN KEY ([UserId]) REFERENCES [dbo].[sec_users] ([Id]) ON DELETE CASCADE,
        CONSTRAINT [FK_sec_user_roles_sec_roles] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[sec_roles] ([Id]) ON DELETE CASCADE
    );
    
    CREATE UNIQUE INDEX [UX_sec_user_roles_UserId_RoleId] ON [dbo].[sec_user_roles] ([UserId], [RoleId]);
    CREATE INDEX [IX_sec_user_roles_UserId] ON [dbo].[sec_user_roles] ([UserId]);
    CREATE INDEX [IX_sec_user_roles_RoleId] ON [dbo].[sec_user_roles] ([RoleId]);
END

-- 角色权限关联表
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sec_role_permissions]') AND type in (N'U'))
BEGIN
    CREATE TABLE [dbo].[sec_role_permissions] (
        [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
        [RoleId] UNIQUEIDENTIFIER NOT NULL,
        [PermissionId] UNIQUEIDENTIFIER NOT NULL,
        [GrantedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [GrantedBy] NVARCHAR(100) NOT NULL,
        [IsEnabled] BIT NOT NULL DEFAULT 1,
        [CreatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [CreatedBy] NVARCHAR(100) NOT NULL,
        CONSTRAINT [FK_sec_role_permissions_sec_roles] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[sec_roles] ([Id]) ON DELETE CASCADE,
        CONSTRAINT [FK_sec_role_permissions_sec_permissions] FOREIGN KEY ([PermissionId]) REFERENCES [dbo].[sec_permissions] ([Id]) ON DELETE CASCADE
    );
    
    CREATE UNIQUE INDEX [UX_sec_role_permissions_RoleId_PermissionId] ON [dbo].[sec_role_permissions] ([RoleId], [PermissionId]);
    CREATE INDEX [IX_sec_role_permissions_RoleId] ON [dbo].[sec_role_permissions] ([RoleId]);
    CREATE INDEX [IX_sec_role_permissions_PermissionId] ON [dbo].[sec_role_permissions] ([PermissionId]);
END

-- 操作日志表
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sec_operation_logs]') AND type in (N'U'))
BEGIN
    CREATE TABLE [dbo].[sec_operation_logs] (
        [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
        [UserId] UNIQUEIDENTIFIER NOT NULL,
        [Username] NVARCHAR(50) NOT NULL,
        [OperationType] INT NOT NULL,
        [Module] NVARCHAR(50) NOT NULL,
        [Description] NVARCHAR(500) NOT NULL,
        [OperationDetailJson] NVARCHAR(MAX) NULL,
        [IpAddress] NVARCHAR(45) NULL,
        [UserAgent] NVARCHAR(500) NULL,
        [Result] INT NOT NULL DEFAULT 0, -- 0:Success, 1:Failed, 2:Warning
        [ErrorMessage] NVARCHAR(MAX) NULL,
        [OperatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
        [SessionId] NVARCHAR(100) NULL,
        [RequestId] NVARCHAR(100) NULL,
        [CreatedAtUtc] DATETIME2 NOT NULL DEFAULT GETUTCDATE()
    );
    
    CREATE INDEX [IX_sec_operation_logs_UserId] ON [dbo].[sec_operation_logs] ([UserId]);
    CREATE INDEX [IX_sec_operation_logs_OperationType] ON [dbo].[sec_operation_logs] ([OperationType]);
    CREATE INDEX [IX_sec_operation_logs_Module] ON [dbo].[sec_operation_logs] ([Module]);
    CREATE INDEX [IX_sec_operation_logs_OperatedAtUtc] ON [dbo].[sec_operation_logs] ([OperatedAtUtc]);
END

-- 插入基础系统数据
IF NOT EXISTS (SELECT * FROM [dbo].[sec_permissions])
BEGIN
    -- 插入系统权限
    INSERT INTO [dbo].[sec_permissions] ([Id], [Code], [Name], [Description], [Type], [Module], [Action], [IsSystemPermission], [CreatedBy], [UpdatedBy]) VALUES
        (NEWID(), 'TRAINING_VIEW', '训练任务查看', '查看训练任务管理页面', 0, 'TRAINING', 'VIEW', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'TRAINING_CREATE', '训练任务创建', '创建新的训练任务', 1, 'TRAINING', 'CREATE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'TRAINING_EDIT', '训练任务编辑', '编辑训练任务信息', 1, 'TRAINING', 'EDIT', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'TRAINING_DELETE', '训练任务删除', '删除训练任务', 1, 'TRAINING', 'DELETE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'SESSION_VIEW', '产品会话查看', '查看产品会话管理页面', 0, 'SESSION', 'VIEW', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'SESSION_CREATE', '产品会话创建', '创建新的产品会话', 1, 'SESSION', 'CREATE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'SESSION_EDIT', '产品会话编辑', '编辑产品会话信息', 1, 'SESSION', 'EDIT', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'SESSION_DELETE', '产品会话删除', '删除产品会话', 1, 'SESSION', 'DELETE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'RULE_VIEW', '规则配置查看', '查看规则配置页面', 0, 'RULE', 'VIEW', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'RULE_CREATE', '规则配置创建', '创建新的规则配置', 1, 'RULE', 'CREATE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'RULE_EDIT', '规则配置编辑', '编辑规则配置', 1, 'RULE', 'EDIT', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'RULE_DELETE', '规则配置删除', '删除规则配置', 1, 'RULE', 'DELETE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'RULE_PUBLISH', '规则版本发布', '发布规则版本', 1, 'RULE', 'PUBLISH', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'RULE_ROLLBACK', '规则版本回滚', '回滚规则版本', 1, 'RULE', 'ROLLBACK', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'CVAT_SYNC', 'CVAT标注同步', '同步CVAT标注数据', 1, 'CVAT', 'SYNC', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'USER_MANAGE', '用户管理', '管理系统用户', 1, 'SYSTEM', 'MANAGE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'ROLE_MANAGE', '角色管理', '管理系统角色', 1, 'SYSTEM', 'MANAGE', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'PERMISSION_MANAGE', '权限管理', '管理系统权限', 1, 'SYSTEM', 'MANAGE', 1, 'SYSTEM', 'SYSTEM');
END

IF NOT EXISTS (SELECT * FROM [dbo].[sec_roles])
BEGIN
    -- 插入系统角色
    INSERT INTO [dbo].[sec_roles] ([Id], [Name], [DisplayName], [Description], [IsSystemRole], [CreatedBy], [UpdatedBy]) VALUES
        (NEWID(), 'ADMIN', '系统管理员', '拥有系统所有权限', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'TRAINER', '训练管理员', '负责训练任务管理', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'OPERATOR', '操作员', '负责产品会话管理', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'CONFIGURATOR', '配置员', '负责规则配置', 1, 'SYSTEM', 'SYSTEM'),
        (NEWID(), 'VIEWER', '查看员', '只拥有查看权限', 1, 'SYSTEM', 'SYSTEM');
END

-- 为管理员角色分配所有权限
DECLARE @adminRoleId UNIQUEIDENTIFIER;
SELECT @adminRoleId = Id FROM [dbo].[sec_roles] WHERE Name = 'ADMIN';

IF @adminRoleId IS NOT NULL AND NOT EXISTS (SELECT * FROM [dbo].[sec_role_permissions] WHERE RoleId = @adminRoleId)
BEGIN
    INSERT INTO [dbo].[sec_role_permissions] ([Id], [RoleId], [PermissionId], [GrantedBy], [CreatedBy])
    SELECT NEWID(), @adminRoleId, Id, 'SYSTEM', 'SYSTEM' FROM [dbo].[sec_permissions] WHERE IsSystemPermission = 1;
END

-- 插入默认管理员用户
IF NOT EXISTS (SELECT * FROM [dbo].[sec_users] WHERE Username = 'admin')
BEGIN
    DECLARE @adminUserId UNIQUEIDENTIFIER = NEWID();
    DECLARE @passwordHash NVARCHAR(255) = 'AQAAAAEAACcQAAAAEKqgkTJ6F4G8Q9X2r8v3wX5Y7Z0a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6'; -- 模拟密码哈希
    DECLARE @passwordSalt NVARCHAR(255) = 'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6'; -- 模拟密码盐
    
    INSERT INTO [dbo].[sec_users] ([Id], [Username], [DisplayName], [Email], [PasswordHash], [PasswordSalt], [CreatedBy], [UpdatedBy]) VALUES
        (@adminUserId, 'admin', '系统管理员', 'admin@orpaonvision.com', @passwordHash, @passwordSalt, 'SYSTEM', 'SYSTEM');
    
    -- 为管理员用户分配管理员角色
    INSERT INTO [dbo].[sec_user_roles] ([Id], [UserId], [RoleId], [GrantedBy], [CreatedBy]) VALUES
        (NEWID(), @adminUserId, @adminRoleId, 'SYSTEM', 'SYSTEM');
END
