-- PostgreSQL Database Schema for iMeeting (Multi-tenant)
-- 0 为系统预留租户 ID

-- ----------------------------
-- 0. 租户与组织
-- ----------------------------

-- 租户表
CREATE TABLE sys_tenant (
                            id              BIGSERIAL PRIMARY KEY,
                            tenant_code     VARCHAR(64) NOT NULL UNIQUE,
                            tenant_name     VARCHAR(128) NOT NULL,
                            status          SMALLINT NOT NULL DEFAULT 1,
                            expire_time     TIMESTAMP(6),
                            contact_name    VARCHAR(64),
                            contact_phone   VARCHAR(32),
                            remark          VARCHAR(255),
                            created_at      TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
                            updated_at      TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
                            is_deleted      SMALLINT DEFAULT 0
);
CREATE UNIQUE INDEX uk_tenant_code ON sys_tenant (tenant_code) WHERE is_deleted = FALSE;

-- 组织架构表
DROP TABLE IF EXISTS sys_org CASCADE;

CREATE TABLE sys_org (
                         id          BIGSERIAL PRIMARY KEY,
                         tenant_id   BIGINT NOT NULL,
                         parent_id   BIGINT,
                         org_name    VARCHAR(128) NOT NULL,
                         org_code    VARCHAR(64),
                         org_path    VARCHAR(512),
                         sort_order  INTEGER DEFAULT 0,
                         status      SMALLINT DEFAULT 1,
                         created_at  TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
                         updated_at  TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
                         is_deleted  SMALLINT DEFAULT 0,
                         CONSTRAINT fk_org_parent FOREIGN KEY (parent_id)
                             REFERENCES sys_org(id),
                         CONSTRAINT fk_org_tenant FOREIGN KEY (tenant_id)
                             REFERENCES sys_tenant(id)
);

CREATE INDEX idx_org_tenant ON sys_org (tenant_id);

-- ----------------------------
-- 1. 用户与角色
-- ----------------------------

-- 用户表
DROP TABLE IF EXISTS sys_user CASCADE;

CREATE TABLE sys_user (
                          user_id            BIGSERIAL PRIMARY KEY,
                          username           VARCHAR(50) NOT NULL UNIQUE,
                          display_name       VARCHAR(50) NOT NULL,
                          email              VARCHAR(100),
                          phone              VARCHAR(30) UNIQUE,
                          password_hash      VARCHAR(255) NOT NULL,
                          status             SMALLINT NOT NULL DEFAULT 1,
                          is_deleted         SMALLINT NOT NULL DEFAULT 0,
                          pwd_reset_required SMALLINT DEFAULT 1,
                          created_at         TIMESTAMP(6) NOT NULL DEFAULT now(),
                          updated_at         TIMESTAMP(6) NOT NULL DEFAULT now(),
                          is_platform_admin  BOOLEAN DEFAULT false
);
CREATE UNIQUE INDEX uk_user_username ON sys_user (username) WHERE is_deleted = FALSE;

-- 角色表
DROP TABLE IF EXISTS sys_role CASCADE;

CREATE TABLE sys_role (
                          role_id    BIGSERIAL PRIMARY KEY,
                          tenant_id  BIGINT,
                          role_code  VARCHAR(50) NOT NULL UNIQUE,
                          role_name  VARCHAR(50) NOT NULL,
                          status     SMALLINT NOT NULL DEFAULT 1,
                          remark     TEXT,
                          is_deleted SMALLINT NOT NULL DEFAULT 0,
                          created_at TIMESTAMP(6) NOT NULL DEFAULT now(),
                          updated_at TIMESTAMP(6) NOT NULL DEFAULT now()
);

CREATE INDEX idx_sys_role_tenant ON sys_role (tenant_id);
CREATE UNIQUE INDEX uk_role_code ON sys_role (tenant_id, role_code) WHERE is_deleted = FALSE;

-- 用户-角色关联表 (无 tenant_id, 随 User/Role 隔离)
DROP TABLE IF EXISTS sys_user_role CASCADE;

CREATE TABLE sys_user_role (
                               id         BIGSERIAL PRIMARY KEY,
                               tenant_id  BIGINT,
                               user_id    BIGINT NOT NULL,
                               role_id    BIGINT NOT NULL,
                               is_deleted SMALLINT NOT NULL DEFAULT 0,
                               created_at TIMESTAMP(6) NOT NULL DEFAULT now(),
                               updated_at TIMESTAMP(6) NOT NULL DEFAULT now(),
                               UNIQUE (user_id, role_id)
);

-- ----------------------------
-- 2. 权限/字典/参数 (全局共享, 无 tenant_id)
-- ----------------------------

DROP TABLE IF EXISTS sys_permission CASCADE;

CREATE TABLE sys_permission (
                                perm_id     BIGSERIAL PRIMARY KEY,
                                parent_id   BIGINT,
                                name        VARCHAR(100) NOT NULL,
                                code        VARCHAR(100) NOT NULL UNIQUE,
                                perm_type   VARCHAR(20) NOT NULL,
                                level       INTEGER NOT NULL,
                                path        VARCHAR(255),
                                component   VARCHAR(255),
                                icon        VARCHAR(100),
                                sort_order  INTEGER NOT NULL DEFAULT 0,
                                is_visible  SMALLINT NOT NULL DEFAULT 1,
                                status      SMALLINT NOT NULL DEFAULT 1,
                                description TEXT,
                                meta        JSONB,
                                is_deleted  SMALLINT NOT NULL DEFAULT 0,
                                created_at  TIMESTAMP(6) NOT NULL DEFAULT now(),
                                updated_at  TIMESTAMP(6) NOT NULL DEFAULT now()
);

DROP TABLE IF EXISTS sys_tenant_user CASCADE;

CREATE TABLE sys_tenant_user (
                                 id         BIGSERIAL PRIMARY KEY,
                                 user_id    BIGINT NOT NULL,
                                 tenant_id  BIGINT NOT NULL,
                                 org_id     BIGINT,
                                 status     SMALLINT DEFAULT 1,
                                 is_deleted SMALLINT DEFAULT 0,
                                 created_at TIMESTAMP(6) NOT NULL DEFAULT now(),
                                 updated_at TIMESTAMP(6) NOT NULL DEFAULT now()
);

CREATE UNIQUE INDEX uk_tenant_user
    ON sys_tenant_user (user_id, tenant_id)
    WHERE is_deleted = 0;
CREATE TABLE sys_dict_type (
    dict_type_id BIGSERIAL PRIMARY KEY,
    type_code VARCHAR(50) UNIQUE NOT NULL,
    type_name VARCHAR(50) NOT NULL,
    status SMALLINT DEFAULT 1,
    remark TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
    is_deleted SMALLINT DEFAULT 0
);

CREATE TABLE sys_dict_item (
    dict_item_id BIGSERIAL PRIMARY KEY,
    type_code VARCHAR(50) NOT NULL,
    item_label VARCHAR(100) NOT NULL,
    item_value VARCHAR(100) NOT NULL,
    sort_order INT DEFAULT 0,
    status SMALLINT DEFAULT 1,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
    is_deleted SMALLINT DEFAULT 0
);
CREATE INDEX idx_dict_item_type ON sys_dict_item (type_code);
CREATE UNIQUE INDEX uk_dict_item_value ON sys_dict_item (type_code, item_value);

CREATE TABLE sys_param (
    id BIGSERIAL PRIMARY KEY,
    param_key VARCHAR(100) UNIQUE NOT NULL,
    param_value TEXT NOT NULL,
    param_type VARCHAR(20) NOT NULL,
    is_system SMALLINT DEFAULT 0,
    status SMALLINT DEFAULT 1,
    description TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
    is_deleted SMALLINT DEFAULT 0
);

-- ----------------------------
-- 3. 日志 (租户隔离)
-- ----------------------------

CREATE TABLE sys_log (
    id BIGSERIAL PRIMARY KEY,
    tenant_id BIGINT NOT NULL DEFAULT 0,
    user_id BIGINT,
    username VARCHAR(50),
    log_type VARCHAR(20), -- LOGIN, OPERATION
    operation VARCHAR(100) NOT NULL,
    method VARCHAR(200),
    params TEXT,
    status SMALLINT DEFAULT 1,
    ip VARCHAR(50),
    duration BIGINT,
    created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_log_tenant_type ON sys_log (tenant_id, log_type, created_at);

-- ----------------------------
-- 4. 平台配置 (系统品牌化)
-- ----------------------------
DROP TABLE IF EXISTS sys_platform_config CASCADE;
CREATE TABLE sys_platform_config (
    id                BIGINT PRIMARY KEY, -- 固定为 1
    project_name      VARCHAR(128) NOT NULL,
    logo_url          VARCHAR(512),
    icon_url          VARCHAR(512),
    login_bg_url      VARCHAR(512),
    icp_info          VARCHAR(128),
    copyright_info    VARCHAR(255),
    system_description TEXT,
    created_at        TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
    updated_at        TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
    is_deleted        SMALLINT DEFAULT 0
);

INSERT INTO sys_platform_config (id, project_name, copyright_info) 
VALUES (1, 'iMeeting 智能会议系统', '© 2026 iMeeting Team. All rights reserved.');

-- ----------------------------
-- 5. 基础初始化数据
-- ----------------------------

-- 字典初始化数据
-- sys_common_status
INSERT INTO sys_dict_type (type_code, type_name, remark) VALUES ('sys_common_status', '通用状态', '0=禁用, 1=启用');
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_common_status', '启用', '1', 1);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_common_status', '禁用', '0', 2);

-- sys_permission_type
INSERT INTO sys_dict_type (type_code, type_name, remark) VALUES ('sys_permission_type', '权限类型', 'directory=目录, menu=菜单, button=按钮');
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_permission_type', '目录', 'directory', 1);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_permission_type', '菜单', 'menu', 2);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_permission_type', '按钮', 'button', 3);

-- sys_common_visibility
INSERT INTO sys_dict_type (type_code, type_name, remark) VALUES ('sys_common_visibility', '可见性', '0=隐藏, 1=显示');
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_common_visibility', '显示', '1', 1);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_common_visibility', '隐藏', '0', 2);

-- sys_permission_level
INSERT INTO sys_dict_type (type_code, type_name, remark) VALUES ('sys_permission_level', '权限层级', '1=一级入口, 2=二级子项, 3=三级按钮');
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_permission_level', '一级入口', '1', 1);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_permission_level', '二级子项', '2', 2);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_permission_level', '三级按钮', '3', 3);

-- sys_log_type
INSERT INTO sys_dict_type (type_code, type_name, remark) VALUES ('sys_log_type', '日志类型', 'LOGIN=登录, OPERATION=操作');
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_log_type', '登录', 'LOGIN', 1);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_log_type', '操作', 'OPERATION', 2);

-- sys_param_type
INSERT INTO sys_dict_type (type_code, type_name, remark) VALUES ('sys_param_type', '参数类型', 'String, Number, Boolean, JSON');
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_param_type', 'String', 'String', 1);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_param_type', 'Number', 'Number', 2);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_param_type', 'Boolean', 'Boolean', 3);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_param_type', 'JSON', 'JSON', 4);

-- sys_log_status
INSERT INTO sys_dict_type (type_code, type_name, remark) VALUES ('sys_log_status', '操作状态', '1=成功, 0=失败');
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_log_status', '成功', '1', 1);
INSERT INTO sys_dict_item (type_code, item_label, item_value, sort_order) VALUES ('sys_log_status', '失败', '0', 2);
