-- ============================================================
-- AI 智能客服系统 - 数据库初始化脚本（完整版）
-- 适用环境: PostgreSQL 12+ 且已安装 pgvector 扩展
-- 表数量: 14 张（基础 8 张 + P0 阶段新增 6 张）
--
-- ⚠️ 开发规范：任何涉及建表、增删改列、初始数据的变更，
-- 必须同时更新本脚本和 DatabaseInitConfig.java（自动初始化），
-- 保持两者一致，否则新部署环境会丢失变更。
--
-- 使用方法:
--   方式一（psql 命令行）:
--     psql -U postgres -f init-database.sql
--   方式二（DataGrip / DBeaver / IntelliJ 等图形工具）:
--     先在 postgres 库中执行第 1 步（CREATE DATABASE），
--     然后切换到 support_bot 库，注释掉第 1 步，执行剩余部分。
-- ============================================================

-- 1. 创建数据库（需在 postgres 默认库下执行）
--    如果已在目标库中，注释掉下面这行
CREATE DATABASE support_bot ENCODING 'UTF8' LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0;

-- ============================================================
-- ★ 第 1 步结束 ★
-- Navicat / DataGrip / DBeaver 用户：请在此处停止，
-- 手动切换到 support_bot 数据库，再执行第 2 步及后续 SQL。
-- ============================================================

-- 2. 安装必要扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS vector;

-- ============================================================
-- 表 1: chat_message — 聊天消息表
-- ============================================================
CREATE TABLE IF NOT EXISTS chat_message (
    id              BIGINT PRIMARY KEY,
    conversation_id VARCHAR(64)  NOT NULL,
    message_type    VARCHAR(20)  NOT NULL,
    content         TEXT         NOT NULL,
    metadata        JSONB        NOT NULL DEFAULT '{}',
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE,
    CONSTRAINT chk_message_type CHECK (message_type IN ('USER', 'ASSISTANT', 'SYSTEM'))
);

CREATE INDEX IF NOT EXISTS idx_chat_message_conversation_id ON chat_message (conversation_id);
CREATE INDEX IF NOT EXISTS idx_chat_message_create_time     ON chat_message (create_time DESC);
CREATE INDEX IF NOT EXISTS idx_chat_message_type            ON chat_message (message_type);
CREATE INDEX IF NOT EXISTS idx_chat_message_not_deleted      ON chat_message (conversation_id) WHERE is_delete = FALSE;

COMMENT ON TABLE  chat_message             IS '聊天消息表';
COMMENT ON COLUMN chat_message.id          IS '主键（雪花算法生成）';
COMMENT ON COLUMN chat_message.conversation_id IS '会话ID';
COMMENT ON COLUMN chat_message.message_type    IS '消息类型: USER / ASSISTANT / SYSTEM';
COMMENT ON COLUMN chat_message.content     IS '消息内容';
COMMENT ON COLUMN chat_message.metadata    IS '元数据（JSON）';
COMMENT ON COLUMN chat_message.create_time IS '创建时间';
COMMENT ON COLUMN chat_message.update_time IS '更新时间';
COMMENT ON COLUMN chat_message.is_delete   IS '逻辑删除: FALSE=正常 TRUE=已删除';

-- ============================================================
-- 表 2: knowledge_category — 知识库分类表
-- ============================================================
CREATE TABLE IF NOT EXISTS knowledge_category (
    id              BIGSERIAL    PRIMARY KEY,
    name            VARCHAR(100) NOT NULL,
    description     TEXT,
    parent_id       BIGINT       NOT NULL DEFAULT 0,
    sort_order      INTEGER      NOT NULL DEFAULT 0,
    document_count  INTEGER      NOT NULL DEFAULT 0,
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE
);

CREATE INDEX IF NOT EXISTS idx_knowledge_category_parent ON knowledge_category (parent_id);

COMMENT ON TABLE  knowledge_category              IS '知识库分类表';
COMMENT ON COLUMN knowledge_category.id           IS '主键';
COMMENT ON COLUMN knowledge_category.name         IS '分类名称';
COMMENT ON COLUMN knowledge_category.description  IS '分类描述';
COMMENT ON COLUMN knowledge_category.parent_id    IS '父分类ID（0 表示顶级分类）';
COMMENT ON COLUMN knowledge_category.sort_order   IS '排序权重';
COMMENT ON COLUMN knowledge_category.document_count IS '关联文档数（冗余字段）';
COMMENT ON COLUMN knowledge_category.create_time  IS '创建时间';
COMMENT ON COLUMN knowledge_category.is_delete    IS '逻辑删除';

-- ============================================================
-- 表 3: knowledge_document — 知识文档表
-- ============================================================
CREATE TABLE IF NOT EXISTS knowledge_document (
    id              BIGSERIAL    PRIMARY KEY,
    title           VARCHAR(500) NOT NULL,
    source_name     VARCHAR(500),
    file_type       VARCHAR(20)  NOT NULL,
    file_size       BIGINT       NOT NULL DEFAULT 0,
    content         TEXT,
    category_id     BIGINT       NOT NULL DEFAULT 0,
    tags            JSONB        NOT NULL DEFAULT '{}',
    chunk_count     INTEGER      NOT NULL DEFAULT 0,
    status          VARCHAR(20)  NOT NULL DEFAULT 'PROCESSING',
    error_message   TEXT,
    content_hash    VARCHAR(64),
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE
);

CREATE INDEX IF NOT EXISTS idx_knowledge_document_category     ON knowledge_document (category_id);
CREATE INDEX IF NOT EXISTS idx_knowledge_document_status       ON knowledge_document (status);
CREATE INDEX IF NOT EXISTS idx_knowledge_document_create_time  ON knowledge_document (create_time DESC);
CREATE INDEX IF NOT EXISTS idx_knowledge_document_content_hash ON knowledge_document (content_hash);

COMMENT ON TABLE  knowledge_document              IS '知识文档表';
COMMENT ON COLUMN knowledge_document.id           IS '主键';
COMMENT ON COLUMN knowledge_document.title        IS '文档标题';
COMMENT ON COLUMN knowledge_document.source_name  IS '原始文件名';
COMMENT ON COLUMN knowledge_document.file_type    IS '文件类型';
COMMENT ON COLUMN knowledge_document.file_size    IS '文件大小（字节）';
COMMENT ON COLUMN knowledge_document.content      IS '原文内容（截断预览）';
COMMENT ON COLUMN knowledge_document.category_id  IS '所属分类ID';
COMMENT ON COLUMN knowledge_document.tags         IS '标签（JSON）';
COMMENT ON COLUMN knowledge_document.chunk_count  IS '分块数量';
COMMENT ON COLUMN knowledge_document.status       IS '状态: PROCESSING / READY / FAILED';
COMMENT ON COLUMN knowledge_document.error_message IS '处理失败时的错误信息';
COMMENT ON COLUMN knowledge_document.content_hash IS '内容SHA-256哈希（用于去重）';
COMMENT ON COLUMN knowledge_document.create_time  IS '创建时间';
COMMENT ON COLUMN knowledge_document.update_time  IS '更新时间';
COMMENT ON COLUMN knowledge_document.is_delete    IS '逻辑删除';

-- ============================================================
-- 表 4: customer_service_role — 客服角色表
-- ============================================================
CREATE TABLE IF NOT EXISTS customer_service_role (
    id              BIGSERIAL    PRIMARY KEY,
    role_key        VARCHAR(64)  NOT NULL UNIQUE,
    name            VARCHAR(100) NOT NULL,
    description     TEXT,
    prompt          TEXT,
    sort_order      INTEGER      NOT NULL DEFAULT 0,
    enabled         BOOLEAN      NOT NULL DEFAULT TRUE,
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE
);

CREATE INDEX IF NOT EXISTS idx_customer_service_role_enabled ON customer_service_role (enabled, sort_order);

COMMENT ON TABLE  customer_service_role           IS '客服角色表';
COMMENT ON COLUMN customer_service_role.id        IS '主键';
COMMENT ON COLUMN customer_service_role.role_key  IS '角色标识符（唯一）';
COMMENT ON COLUMN customer_service_role.name      IS '角色名称';
COMMENT ON COLUMN customer_service_role.description IS '角色描述';
COMMENT ON COLUMN customer_service_role.prompt    IS '系统提示词';
COMMENT ON COLUMN customer_service_role.sort_order IS '排序权重';
COMMENT ON COLUMN customer_service_role.enabled   IS '是否启用';
COMMENT ON COLUMN customer_service_role.create_time IS '创建时间';
COMMENT ON COLUMN customer_service_role.update_time IS '更新时间';
COMMENT ON COLUMN customer_service_role.is_delete IS '逻辑删除';

-- 默认角色种子数据
INSERT INTO customer_service_role (role_key, name, description, sort_order, enabled)
VALUES ('general', '客服', '通用客服角色', 0, TRUE)
ON CONFLICT (role_key) DO NOTHING;

INSERT INTO customer_service_role (role_key, name, description, sort_order, enabled)
VALUES ('finance', '财务', '财务相关客服角色', 1, TRUE)
ON CONFLICT (role_key) DO NOTHING;

INSERT INTO customer_service_role (role_key, name, description, sort_order, enabled)
VALUES ('administration', '行政', '行政相关客服角色', 2, TRUE)
ON CONFLICT (role_key) DO NOTHING;

-- ============================================================
-- 表 5: customer_service_role_category — 角色知识库关联表
-- ============================================================
CREATE TABLE IF NOT EXISTS customer_service_role_category (
    id              BIGSERIAL    PRIMARY KEY,
    role_id         BIGINT       NOT NULL,
    category_id     BIGINT       NOT NULL,
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE,
    CONSTRAINT uq_role_category UNIQUE (role_id, category_id)
);

CREATE INDEX IF NOT EXISTS idx_customer_service_role_category_role     ON customer_service_role_category (role_id);
CREATE INDEX IF NOT EXISTS idx_customer_service_role_category_category ON customer_service_role_category (category_id);

COMMENT ON TABLE  customer_service_role_category           IS '客服角色知识库关联表';
COMMENT ON COLUMN customer_service_role_category.id        IS '主键';
COMMENT ON COLUMN customer_service_role_category.role_id   IS '角色ID';
COMMENT ON COLUMN customer_service_role_category.category_id IS '分类ID';
COMMENT ON COLUMN customer_service_role_category.create_time IS '创建时间';
COMMENT ON COLUMN customer_service_role_category.is_delete IS '逻辑删除';

-- ============================================================
-- 表 6: customer_account — 客服账号表
-- ============================================================
CREATE TABLE IF NOT EXISTS customer_account (
    id              BIGSERIAL    PRIMARY KEY,
    account_key     VARCHAR(64)  NOT NULL UNIQUE,
    name            VARCHAR(100) NOT NULL,
    description     TEXT,
    role_id         BIGINT,
    enabled         BOOLEAN      NOT NULL DEFAULT TRUE,
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE
);

CREATE INDEX IF NOT EXISTS idx_customer_account_role    ON customer_account (role_id);
CREATE INDEX IF NOT EXISTS idx_customer_account_enabled ON customer_account (enabled, id);

COMMENT ON TABLE  customer_account              IS '客服账号表';
COMMENT ON COLUMN customer_account.id           IS '主键';
COMMENT ON COLUMN customer_account.account_key  IS '账号标识符（唯一）';
COMMENT ON COLUMN customer_account.name         IS '账号名称';
COMMENT ON COLUMN customer_account.description  IS '账号描述';
COMMENT ON COLUMN customer_account.role_id      IS '关联角色ID';
COMMENT ON COLUMN customer_account.enabled      IS '是否启用';
COMMENT ON COLUMN customer_account.create_time  IS '创建时间';
COMMENT ON COLUMN customer_account.update_time  IS '更新时间';
COMMENT ON COLUMN customer_account.is_delete    IS '逻辑删除';

-- 默认账号种子数据（引用角色表的 ID）
INSERT INTO customer_account (account_key, name, description, role_id, enabled)
SELECT 'service', '客服账号', '通用客服账号', id, TRUE
FROM customer_service_role WHERE role_key = 'general'
ON CONFLICT (account_key) DO NOTHING;

INSERT INTO customer_account (account_key, name, description, role_id, enabled)
SELECT 'finance', '财务账号', '财务客服账号', id, TRUE
FROM customer_service_role WHERE role_key = 'finance'
ON CONFLICT (account_key) DO NOTHING;

INSERT INTO customer_account (account_key, name, description, role_id, enabled)
SELECT 'administration', '行政账号', '行政客服账号', id, TRUE
FROM customer_service_role WHERE role_key = 'administration'
ON CONFLICT (account_key) DO NOTHING;

-- ============================================================
-- 表 7: conversation_session — 会话归属表
-- ============================================================
CREATE TABLE IF NOT EXISTS conversation_session (
    conversation_id VARCHAR(64) PRIMARY KEY,
    account_id      BIGINT,
    external_account_id VARCHAR(128),
    role_id         BIGINT,
    create_time     TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_conversation_session_account ON conversation_session (account_id);
CREATE INDEX IF NOT EXISTS idx_conversation_session_external_account ON conversation_session (external_account_id);
CREATE INDEX IF NOT EXISTS idx_conversation_session_role    ON conversation_session (role_id);

COMMENT ON TABLE  conversation_session                IS '会话归属表';
COMMENT ON COLUMN conversation_session.conversation_id IS '会话ID（主键）';
COMMENT ON COLUMN conversation_session.account_id     IS '归属账号ID';
COMMENT ON COLUMN conversation_session.role_id        IS '归属角色ID';
COMMENT ON COLUMN conversation_session.create_time    IS '创建时间';
COMMENT ON COLUMN conversation_session.update_time    IS '更新时间';

-- ============================================================
-- 表 8: vector_store — 向量存储表
-- 注意: Spring AI PgVectorStore 配置了 initializeSchema(true)，
--       应用启动时会自动建表。此处手动建表作为备份方案。
--       向量维度默认 1024，如使用不同维度的 Embedding 模型
--       需修改下面的 VECTOR(1024) 并重建。
-- ============================================================
CREATE TABLE IF NOT EXISTS vector_store (
    id          UUID        PRIMARY KEY DEFAULT uuid_generate_v4(),
    content     TEXT        NOT NULL,
    metadata    JSONB       NOT NULL DEFAULT '{}',
    embedding   VECTOR(1024) NOT NULL,
    create_time TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- HNSW 向量索引（余弦距离）
CREATE INDEX IF NOT EXISTS idx_vector_store_embedding ON vector_store
    USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);

CREATE INDEX IF NOT EXISTS idx_vector_store_create_time ON vector_store (create_time DESC);

-- JSONB 元数据 GIN 索引
CREATE INDEX IF NOT EXISTS idx_vector_store_metadata ON vector_store USING gin (metadata);

COMMENT ON TABLE  vector_store          IS '向量存储表（RAG 知识库向量化数据）';
COMMENT ON COLUMN vector_store.id       IS '主键（UUID）';
COMMENT ON COLUMN vector_store.content  IS '文档内容';
COMMENT ON COLUMN vector_store.metadata IS '元数据（JSON）';
COMMENT ON COLUMN vector_store.embedding IS '向量嵌入（维度 1024）';
COMMENT ON COLUMN vector_store.create_time IS '创建时间';
COMMENT ON COLUMN vector_store.update_time IS '更新时间';

-- 全文检索列（混合检索 KEYWORD / HYBRID 模式使用）
ALTER TABLE vector_store ADD COLUMN IF NOT EXISTS content_tsvector tsvector;
CREATE INDEX IF NOT EXISTS idx_vector_store_tsvector ON vector_store USING gin(content_tsvector);

COMMENT ON COLUMN vector_store.content_tsvector IS '全文检索向量列（tsvector，由触发器自动维护）';

-- 全文检索触发器函数
CREATE OR REPLACE FUNCTION update_content_tsvector() RETURNS trigger AS $$
BEGIN
    NEW.content_tsvector := to_tsvector('simple', coalesce(NEW.content, ''));
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_update_content_tsvector ON vector_store;
CREATE TRIGGER trg_update_content_tsvector
    BEFORE INSERT OR UPDATE ON vector_store
    FOR EACH ROW EXECUTE FUNCTION update_content_tsvector();

-- ============================================================
-- 表 9: ai_model_config — AI 大模型配置表
-- ============================================================
CREATE TABLE IF NOT EXISTS ai_model_config (
    id              BIGINT       PRIMARY KEY,
    name            VARCHAR(100) NOT NULL,
    app_type        VARCHAR(32)  NOT NULL,
    provider        VARCHAR(64)  NOT NULL,
    api_key         VARCHAR(256),
    model_name      VARCHAR(128) NOT NULL,
    temperature     DOUBLE PRECISION DEFAULT 0.7,
    max_tokens      INTEGER      DEFAULT 2048,
    base_url        VARCHAR(256),
    extra_config    JSONB        DEFAULT '{}' NOT NULL,
    is_active       BOOLEAN      DEFAULT FALSE NOT NULL,
    priority        INTEGER      DEFAULT 0 NOT NULL,
    description     VARCHAR(500),
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE
);

CREATE INDEX IF NOT EXISTS idx_ai_model_config_app_type  ON ai_model_config (app_type);
CREATE INDEX IF NOT EXISTS idx_ai_model_config_active    ON ai_model_config (is_active) WHERE is_delete = FALSE;

COMMENT ON TABLE  ai_model_config              IS 'AI 大模型配置表（管理多套模型配置，按应用类型绑定）';
COMMENT ON COLUMN ai_model_config.id           IS '主键（雪花算法生成）';
COMMENT ON COLUMN ai_model_config.name         IS '配置名称';
COMMENT ON COLUMN ai_model_config.app_type     IS '应用类型: CHAT / EMBEDDING / RAG_REWRITE / RERANK';
COMMENT ON COLUMN ai_model_config.provider     IS '模型提供商: dashscope / openai / deepseek / moonshot / zhipu / volcengine 等';
COMMENT ON COLUMN ai_model_config.api_key      IS 'API Key（数据库加密存储，前端脱敏展示）';
COMMENT ON COLUMN ai_model_config.model_name   IS '模型名称（如 qwen-turbo、gpt-4o）';
COMMENT ON COLUMN ai_model_config.temperature  IS '温度参数（控制输出随机性，0.0~2.0）';
COMMENT ON COLUMN ai_model_config.max_tokens   IS '最大 Token 数（单次生成上限）';
COMMENT ON COLUMN ai_model_config.base_url     IS 'API 基础地址（可选，用于私有化部署或第三方厂商）';
COMMENT ON COLUMN ai_model_config.extra_config IS '扩展配置（JSONB，存储 topP、dimensions 等自定义参数）';
COMMENT ON COLUMN ai_model_config.is_active    IS '是否激活（每种 App 类型只能有一个激活配置）';
COMMENT ON COLUMN ai_model_config.priority     IS '优先级（数值越大越优先，多套配置时生效）';
COMMENT ON COLUMN ai_model_config.description  IS '配置描述说明';
COMMENT ON COLUMN ai_model_config.create_time  IS '创建时间';
COMMENT ON COLUMN ai_model_config.update_time  IS '更新时间';
COMMENT ON COLUMN ai_model_config.is_delete    IS '逻辑删除: FALSE=正常 TRUE=已删除';

-- ============================================================
-- 表 10: sensitive_word — 敏感词表（P0-004 内容安全过滤）
-- ============================================================
CREATE TABLE IF NOT EXISTS sensitive_word (
    id              BIGSERIAL    PRIMARY KEY,
    word            VARCHAR(256) NOT NULL,
    category        VARCHAR(64)  NOT NULL DEFAULT 'custom',
    level           INTEGER      NOT NULL DEFAULT 1,
    is_active       BOOLEAN      NOT NULL DEFAULT TRUE,
    remark          VARCHAR(512),
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE
);

-- 唯一索引：同一分类下敏感词不重复（仅对未删除记录生效）
CREATE UNIQUE INDEX IF NOT EXISTS uk_sensitive_word_word_category ON sensitive_word (word, category) WHERE is_delete = FALSE;
CREATE INDEX IF NOT EXISTS idx_sensitive_word_active ON sensitive_word (is_active) WHERE is_delete = FALSE;

COMMENT ON TABLE  sensitive_word            IS '敏感词表（DFA 引擎驱动的内容安全过滤）';
COMMENT ON COLUMN sensitive_word.id         IS '主键（雪花算法生成）';
COMMENT ON COLUMN sensitive_word.word       IS '敏感词内容';
COMMENT ON COLUMN sensitive_word.category   IS '分类: politics / porn / abuse / custom，默认 custom';
COMMENT ON COLUMN sensitive_word.level      IS '级别: 1=脱敏(MASK) / 2=拦截(BLOCK)';
COMMENT ON COLUMN sensitive_word.is_active  IS '是否启用';
COMMENT ON COLUMN sensitive_word.remark     IS '备注说明';
COMMENT ON COLUMN sensitive_word.create_time IS '创建时间';
COMMENT ON COLUMN sensitive_word.update_time IS '更新时间';
COMMENT ON COLUMN sensitive_word.is_delete  IS '逻辑删除: FALSE=正常 TRUE=已删除';

-- ============================================================
-- 表 11: content_audit_log — 内容审计日志表（P0-004，只追加不删除）
-- ============================================================
CREATE TABLE IF NOT EXISTS content_audit_log (
    id              BIGSERIAL    PRIMARY KEY,
    session_id      VARCHAR(64),
    direction       VARCHAR(16)  NOT NULL,
    original_text   TEXT         NOT NULL,
    hit_words       JSONB        NOT NULL DEFAULT '[]',
    action_taken    VARCHAR(32)  NOT NULL,
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_audit_log_created ON content_audit_log (create_time DESC);
CREATE INDEX IF NOT EXISTS idx_audit_log_session ON content_audit_log (session_id);

COMMENT ON TABLE  content_audit_log              IS '内容审计日志表（记录所有敏感词命中事件，只追加不删除）';
COMMENT ON COLUMN content_audit_log.id           IS '主键（雪花算法生成）';
COMMENT ON COLUMN content_audit_log.session_id   IS '会话ID（关联 conversation_session）';
COMMENT ON COLUMN content_audit_log.direction    IS '检测方向: INPUT(用户输入) / OUTPUT(AI 输出)';
COMMENT ON COLUMN content_audit_log.original_text IS '原始违规内容（截断至前 50 字）';
COMMENT ON COLUMN content_audit_log.hit_words    IS '命中词列表（JSON 数组，记录触发的敏感词）';
COMMENT ON COLUMN content_audit_log.action_taken IS '采取的动作: PASS(放行) / MASK(脱敏) / BLOCK(拦截)';
COMMENT ON COLUMN content_audit_log.create_time  IS '创建时间（事件发生时间）';

-- ============================================================
-- 表 12: message_feedback — 消息反馈表（P0-002 用户反馈系统）
-- ============================================================
CREATE TABLE IF NOT EXISTS message_feedback (
    id              BIGSERIAL    PRIMARY KEY,
    message_id      VARCHAR(128) NOT NULL,
    conversation_id VARCHAR(64)  NOT NULL,
    feedback_type   VARCHAR(16)  NOT NULL,
    reason_category VARCHAR(64),
    reason_comment  TEXT,
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete       BOOLEAN      NOT NULL DEFAULT FALSE
);

-- 唯一索引：每条消息只能有一条反馈（重复提交覆盖，upsert 语义）
CREATE UNIQUE INDEX IF NOT EXISTS uk_message_feedback_message ON message_feedback (message_id) WHERE is_delete = FALSE;
CREATE INDEX IF NOT EXISTS idx_feedback_conversation ON message_feedback (conversation_id);
CREATE INDEX IF NOT EXISTS idx_feedback_type         ON message_feedback (feedback_type) WHERE is_delete = FALSE;
CREATE INDEX IF NOT EXISTS idx_feedback_created      ON message_feedback (create_time DESC);

COMMENT ON TABLE  message_feedback                  IS '消息反馈表（用户对 AI 回复的点赞/点踩反馈）';
COMMENT ON COLUMN message_feedback.id               IS '主键（雪花算法生成）';
COMMENT ON COLUMN message_feedback.message_id       IS 'AI 消息ID（前端 msgId 或 UUID，唯一索引字段）';
COMMENT ON COLUMN message_feedback.conversation_id  IS '会话ID（关联 chat_message）';
COMMENT ON COLUMN message_feedback.feedback_type    IS '反馈类型: THUMBS_UP(有帮助) / THUMBS_DOWN(没帮助)';
COMMENT ON COLUMN message_feedback.reason_category  IS '点踩原因分类: inaccurate / irrelevant / incomplete / other（仅 THUMBS_DOWN 时可选）';
COMMENT ON COLUMN message_feedback.reason_comment   IS '自由文本补充说明（可选）';
COMMENT ON COLUMN message_feedback.create_time      IS '创建时间';
COMMENT ON COLUMN message_feedback.update_time      IS '更新时间（重复提交时覆盖）';
COMMENT ON COLUMN message_feedback.is_delete        IS '逻辑删除: FALSE=正常 TRUE=已删除';

-- ============================================================
-- 表 13: knowledge_faq — FAQ 知识库表（P0-003 意图识别 + FAQ 精准匹配）
-- ============================================================
CREATE TABLE IF NOT EXISTS knowledge_faq (
    id                  BIGSERIAL    PRIMARY KEY,
    question            TEXT         NOT NULL,
    answer              TEXT         NOT NULL,
    similar_questions   TEXT         NOT NULL DEFAULT '[]',
    category            VARCHAR(128),
    status              VARCHAR(20)  NOT NULL DEFAULT 'ENABLED',
    priority            INTEGER      NOT NULL DEFAULT 0,
    hit_count           BIGINT       NOT NULL DEFAULT 0,
    source              VARCHAR(64)  DEFAULT 'manual',
    create_time         TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time         TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
    is_delete           BOOLEAN      NOT NULL DEFAULT FALSE
);

CREATE INDEX IF NOT EXISTS idx_faq_status   ON knowledge_faq (status) WHERE is_delete = FALSE;
CREATE INDEX IF NOT EXISTS idx_faq_category ON knowledge_faq (category);
CREATE INDEX IF NOT EXISTS idx_faq_priority ON knowledge_faq (priority DESC);

COMMENT ON TABLE  knowledge_faq                      IS 'FAQ 知识库表（用于意图路由后的精准问答匹配）';
COMMENT ON COLUMN knowledge_faq.id                   IS '主键（雪花算法生成）';
COMMENT ON COLUMN knowledge_faq.question             IS '标准问题';
COMMENT ON COLUMN knowledge_faq.answer               IS '标准答案';
COMMENT ON COLUMN knowledge_faq.similar_questions    IS '相似问题列表（JSON 字符串数组，用于扩展匹配范围）';
COMMENT ON COLUMN knowledge_faq.category             IS 'FAQ 分类';
COMMENT ON COLUMN knowledge_faq.status               IS '状态: ENABLED(启用) / DISABLED(禁用)';
COMMENT ON COLUMN knowledge_faq.priority             IS '优先级（数值越大越优先匹配，默认 0）';
COMMENT ON COLUMN knowledge_faq.hit_count            IS '命中次数统计（用于分析高频问题）';
COMMENT ON COLUMN knowledge_faq.source               IS '来源: manual(手动录入) / import(批量导入)';
COMMENT ON COLUMN knowledge_faq.create_time          IS '创建时间';
COMMENT ON COLUMN knowledge_faq.update_time          IS '更新时间';
COMMENT ON COLUMN knowledge_faq.is_delete            IS '逻辑删除: FALSE=正常 TRUE=已删除';

-- ============================================================
-- 表 14: faq_embedding — FAQ 向量索引表（P0-003，FAQ 语义匹配用）
-- ============================================================
CREATE TABLE IF NOT EXISTS faq_embedding (
    id              BIGSERIAL    PRIMARY KEY,
    faq_id          BIGINT       NOT NULL,
    embedding       vector(1024) NOT NULL,
    model_name      VARCHAR(64)  NOT NULL,
    create_time     TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_faq_emb_faq_id ON faq_embedding (faq_id);

COMMENT ON TABLE  faq_embedding             IS 'FAQ 向量索引表（存储 FAQ 的语义向量，用于相似问题语义匹配）';
COMMENT ON COLUMN faq_embedding.id          IS '主键';
COMMENT ON COLUMN faq_embedding.faq_id      IS '关联 FAQ ID（对应 knowledge_faq.id）';
COMMENT ON COLUMN faq_embedding.embedding   IS '向量嵌入（维度由 knowledge.vector.dimension 配置，默认 1024）';
COMMENT ON COLUMN faq_embedding.model_name  IS '使用的 Embedding 模型名称（用于检测模型变更后重新计算）';
COMMENT ON COLUMN faq_embedding.create_time IS '创建时间';

-- ============================================================
-- 完成！
-- 共创建 14 张表及对应索引。
-- ============================================================
