-- =============================================
-- Cloudreve-like 文件管理系统 - 数据库初始化脚本
-- 包含: 文件管理 + RBAC权限 + SSO单点登录
-- =============================================

CREATE DATABASE IF NOT EXISTS seeyon_fs DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE seeyon_fs;

-- ========== 用户与权限 ==========

-- 用户表
CREATE TABLE IF NOT EXISTS fs_user (
    id            BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
    username      VARCHAR(64) UNIQUE NOT NULL COMMENT '用户名',
    password      VARCHAR(256) NOT NULL COMMENT '密码(bcrypt), SSO用户为_SSO_NO_PASSWORD_',
    email         VARCHAR(128) COMMENT '邮箱',
    nickname      VARCHAR(64) COMMENT '昵称',
    avatar        VARCHAR(512) COMMENT '头像URL',
    role          VARCHAR(32) DEFAULT 'user' COMMENT '旧版角色字段(兼容)',
    status        TINYINT DEFAULT 1 COMMENT '状态: 1=启用 0=禁用',
    storage_quota BIGINT DEFAULT 10737418240 COMMENT '存储配额(字节), 默认10GB',
    used_storage  BIGINT DEFAULT 0 COMMENT '已用存储(字节)',
    created_at    DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at    DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';

-- 角色表 (RBAC)
CREATE TABLE IF NOT EXISTS fs_role (
    id           BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '角色ID',
    name         VARCHAR(64) UNIQUE NOT NULL COMMENT '角色标识: admin/editor/viewer',
    display_name VARCHAR(64) NOT NULL COMMENT '显示名称',
    description  VARCHAR(256) COMMENT '角色描述',
    is_system    TINYINT DEFAULT 0 COMMENT '是否系统内置: 1=是(不可删除) 0=否',
    status       TINYINT DEFAULT 1 COMMENT '状态: 1=启用 0=禁用',
    created_at   DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at   DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色表';

-- 权限表 (RBAC)
CREATE TABLE IF NOT EXISTS fs_permission (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '权限ID',
    code        VARCHAR(64) UNIQUE NOT NULL COMMENT '权限标识: file:upload, user:manage',
    name        VARCHAR(64) NOT NULL COMMENT '显示名称',
    resource    VARCHAR(32) NOT NULL COMMENT '资源类型: file/folder/share/user/system',
    action      VARCHAR(32) NOT NULL COMMENT '操作类型: create/read/update/delete/manage',
    description VARCHAR(256) COMMENT '权限描述'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='权限表';

-- 角色-权限关联表
CREATE TABLE IF NOT EXISTS fs_role_permission (
    role_id       BIGINT NOT NULL COMMENT '角色ID',
    permission_id BIGINT NOT NULL COMMENT '权限ID',
    PRIMARY KEY (role_id, permission_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色权限关联表';

-- 用户-角色关联表
CREATE TABLE IF NOT EXISTS fs_user_role (
    user_id BIGINT NOT NULL COMMENT '用户ID',
    role_id BIGINT NOT NULL COMMENT '角色ID',
    PRIMARY KEY (user_id, role_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户角色关联表';

-- ========== SSO 单点登录 ==========

-- SSO提供商配置表
CREATE TABLE IF NOT EXISTS fs_sso_provider (
    id           BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '提供商ID',
    name         VARCHAR(64) NOT NULL COMMENT '提供商标识',
    type         VARCHAR(32) NOT NULL COMMENT '协议类型: oauth2/oidc/cas/ldap',
    display_name VARCHAR(64) NOT NULL COMMENT '登录页显示名称',
    icon         VARCHAR(512) COMMENT '图标URL',
    config       JSON COMMENT '协议配置(ClientID/Secret/URL等)',
    auto_create  TINYINT DEFAULT 1 COMMENT '自动创建用户: 1=是 0=否',
    default_role VARCHAR(32) DEFAULT 'viewer' COMMENT '自动创建时的默认角色',
    status       TINYINT DEFAULT 1 COMMENT '状态: 1=启用 0=禁用',
    sort_order   INT DEFAULT 0 COMMENT '排序',
    created_at   DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at   DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='SSO提供商配置表';

-- SSO会话记录表
CREATE TABLE IF NOT EXISTS fs_sso_session (
    id            BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '会话ID',
    user_id       BIGINT NOT NULL COMMENT '关联的本地用户ID',
    provider_id   BIGINT NOT NULL COMMENT 'SSO提供商ID',
    external_id   VARCHAR(256) NOT NULL COMMENT '外部系统用户ID',
    access_token  VARCHAR(1024) COMMENT 'SSO Access Token',
    refresh_token VARCHAR(1024) COMMENT 'SSO Refresh Token',
    expires_at    DATETIME COMMENT 'Token过期时间',
    last_login_at DATETIME COMMENT '最近登录时间',
    created_at    DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user (user_id),
    INDEX idx_provider_external (provider_id, external_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='SSO会话记录表';

-- ========== 文件管理 ==========

-- 文件夹表
CREATE TABLE IF NOT EXISTS fs_folder (
    id         BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '文件夹ID',
    name       VARCHAR(256) NOT NULL COMMENT '文件夹名称',
    parent_id  BIGINT DEFAULT 0 COMMENT '父文件夹ID, 0=根目录',
    owner_id   BIGINT NOT NULL COMMENT '所属用户ID',
    path       VARCHAR(1024) NOT NULL COMMENT '物化路径, 如 /0/1/5/',
    status     TINYINT DEFAULT 1 COMMENT '状态: 1=正常 0=回收站',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    INDEX idx_parent (parent_id),
    INDEX idx_owner (owner_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文件夹表';

-- 文件表
CREATE TABLE IF NOT EXISTS fs_file (
    id              BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '文件ID',
    name            VARCHAR(256) NOT NULL COMMENT '文件名',
    extension       VARCHAR(32) COMMENT '文件扩展名',
    folder_id       BIGINT NOT NULL COMMENT '所属文件夹ID',
    owner_id        BIGINT NOT NULL COMMENT '所属用户ID',
    size            BIGINT DEFAULT 0 COMMENT '文件大小(字节)',
    md5             VARCHAR(32) COMMENT '文件MD5指纹',
    storage_key     VARCHAR(512) NOT NULL COMMENT '存储引擎中的唯一标识',
    mime_type       VARCHAR(128) COMMENT 'MIME类型',
    is_favorite     TINYINT DEFAULT 0 COMMENT '是否收藏: 1=是 0=否',
    status          TINYINT DEFAULT 1 COMMENT '状态: 1=正常 0=回收站',
    download_count  INT DEFAULT 0 COMMENT '下载次数',
    created_at      DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at      DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    INDEX idx_folder (folder_id),
    INDEX idx_owner (owner_id),
    INDEX idx_md5 (md5)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文件表';

-- 分享表
CREATE TABLE IF NOT EXISTS fs_share (
    id              BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '分享ID',
    file_id         BIGINT NOT NULL COMMENT '文件ID',
    owner_id        BIGINT NOT NULL COMMENT '分享者用户ID',
    share_code      VARCHAR(32) UNIQUE NOT NULL COMMENT '分享码',
    password        VARCHAR(64) COMMENT '提取密码',
    expire_at       DATETIME COMMENT '过期时间, NULL=永不过期',
    max_download    INT DEFAULT 0 COMMENT '最大下载次数, 0=不限制',
    download_count  INT DEFAULT 0 COMMENT '已下载次数',
    permissions     VARCHAR(32) DEFAULT 'preview,download' COMMENT '权限',
    status          TINYINT DEFAULT 1 COMMENT '状态: 1=有效 0=已取消',
    created_at      DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='分享表';

-- 存储策略表
CREATE TABLE IF NOT EXISTS fs_storage_policy (
    id         BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '策略ID',
    name       VARCHAR(64) NOT NULL COMMENT '策略名称',
    type       VARCHAR(32) NOT NULL COMMENT '类型: local/minio/s3/oss',
    config     JSON COMMENT '配置JSON',
    status     TINYINT DEFAULT 1 COMMENT '状态: 1=启用 0=禁用',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='存储策略表';

-- 业务文件关联表 (兼容OA系统)
CREATE TABLE IF NOT EXISTS fs_file_association (
    id         BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '关联ID',
    biz_id     VARCHAR(128) NOT NULL COMMENT '业务单据ID',
    biz_type   VARCHAR(64) NOT NULL COMMENT '业务类型',
    file_id    BIGINT NOT NULL COMMENT '文件ID',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    INDEX idx_biz (biz_id, biz_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='业务文件关联表';

-- ========== 初始数据 ==========

-- 插入默认管理员 (密码: admin123)
INSERT INTO fs_user (username, password, nickname, role, storage_quota)
VALUES ('admin', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '管理员', 'admin', 107374182400)
ON DUPLICATE KEY UPDATE id=id;

-- 插入默认本地存储策略
INSERT INTO fs_storage_policy (name, type, config)
VALUES ('本地存储', 'local', '{"base_path":"./data/storage"}')
ON DUPLICATE KEY UPDATE id=id;

-- 插入默认权限
INSERT INTO fs_permission (code, name, resource, action) VALUES
    ('file:create', '创建文件/文件夹', 'file', 'create'),
    ('file:read', '查看文件', 'file', 'read'),
    ('file:update', '修改文件', 'file', 'update'),
    ('file:delete', '删除文件', 'file', 'delete'),
    ('file:upload', '上传文件', 'file', 'upload'),
    ('share:create', '创建分享', 'share', 'create'),
    ('share:manage', '管理分享', 'share', 'manage'),
    ('user:manage', '用户管理', 'user', 'manage'),
    ('role:manage', '角色管理', 'role', 'manage'),
    ('sso:manage', 'SSO管理', 'sso', 'manage'),
    ('system:manage', '系统管理', 'system', 'manage')
ON DUPLICATE KEY UPDATE id=id;

-- 插入默认角色
INSERT INTO fs_role (name, display_name, description, is_system) VALUES
    ('admin', '管理员', '系统管理员, 拥有所有权限', 1),
    ('editor', '编辑者', '可以上传、修改、删除文件', 1),
    ('viewer', '查看者', '只能查看和下载文件', 1)
ON DUPLICATE KEY UPDATE id=id;

-- 管理员角色分配所有权限
INSERT INTO fs_role_permission (role_id, permission_id)
SELECT r.id, p.id FROM fs_role r, fs_permission p WHERE r.name = 'admin'
ON DUPLICATE KEY UPDATE role_id=role_id;

-- 编辑者角色分配文件和分享权限
INSERT INTO fs_role_permission (role_id, permission_id)
SELECT r.id, p.id FROM fs_role r, fs_permission p
WHERE r.name = 'editor' AND p.code IN ('file:create', 'file:read', 'file:update', 'file:delete', 'file:upload', 'share:create')
ON DUPLICATE KEY UPDATE role_id=role_id;

-- 查看者角色分配只读权限
INSERT INTO fs_role_permission (role_id, permission_id)
SELECT r.id, p.id FROM fs_role r, fs_permission p
WHERE r.name = 'viewer' AND p.code = 'file:read'
ON DUPLICATE KEY UPDATE role_id=role_id;

-- 管理员用户分配admin角色
INSERT INTO fs_user_role (user_id, role_id)
SELECT u.id, r.id FROM fs_user u, fs_role r WHERE u.username = 'admin' AND r.name = 'admin'
ON DUPLICATE KEY UPDATE user_id=user_id;
