CREATE TABLE user_verifications
(
    id            BIGINT PRIMARY KEY,
    user_id       BIGINT      NOT NULL REFERENCES users (id),
    role          VARCHAR(20) NOT NULL,
    status        VARCHAR(20) NOT NULL DEFAULT 'pending',
    materials     JSONB       NOT NULL,
    reject_reason TEXT,
    reviewed_by   BIGINT,
    reviewed_at   TIMESTAMPTZ,
    created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at    TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    CONSTRAINT chk_verification_status CHECK (status IN ('pending', 'approved', 'rejected')),
    UNIQUE (user_id, role) -- 每个角色只有一条最新的认证记录
);

-- Note：Auto update verification_status of users table
CREATE OR REPLACE FUNCTION sync_user_verification_status()
    RETURNS TRIGGER AS
$$
DECLARE
    status_json JSONB;
BEGIN
    SELECT jsonb_object_agg(role, status)
    INTO status_json
    FROM user_verifications
    WHERE user_id = NEW.user_id;

    UPDATE users SET verification_status = status_json WHERE id = NEW.user_id;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_sync_verifications
    AFTER INSERT OR UPDATE
    ON user_verifications
    FOR EACH ROW
EXECUTE FUNCTION sync_user_verification_status();


-- | 字段名 | 类型 | 技术含义 | 业务目的与设计思考 |
-- | :--- | :--- | :--- | :--- |
-- | **`id`** | BIGINT | **主键 (Primary Key)** | **这张认证申请单的唯一编号**。<br>后端代码在处理“审核通过”这个动作时，操作的是这个 ID（例如：`Approve(verificationId)`）。 |
-- | **`user_id`** | BIGINT | **外键 (Foreign Key)** | **谁在申请？**<br>关联到 `users` 表。通过这个字段，我们可以查到申请人的昵称、手机号等信息。 |
-- | **`role`** | VARCHAR | 普通字段 | **申请什么身份？**<br>枚举值：`player` (打手), `owner` (店长)。<br>因为一个用户可以同时是打手和店长，所以需要区分这条记录是申请哪个身份的。 |
-- | **`status`** | VARCHAR | 状态字段 | **当前进度如何？**<br>枚举值：`pending` (待审核), `approved` (已通过), `rejected` (已驳回)。 |
-- | **`materials`** | **JSONB** | **非结构化数据** | **提交了什么证明材料？**<br>**精华设计**：这里不使用多张表或多个字段，而是用 JSON 存。因为打手需要传“身份证+段位图”，店长需要传“营业执照”。不同角色的材料结构不同，用 JSONB 最灵活，以后改规则不需要改表结构。 |
-- | **`reject_reason`** | TEXT | 文本 | **驳回理由**。<br>只有当 `status` = 'rejected' 时才有值，告诉用户哪里填错了。 |
-- | **`reviewed_by`** | BIGINT | 审计字段 | **谁审核的？**<br>记录是哪个管理员（Admin ID）点击了通过或拒绝。用于内部追责和审计。 |
-- | **`reviewed_at`** | TIMESTAMPTZ | 时间字段 | **什么时候审核的？**<br>用于统计管理员的工作效率，或者展示给用户“审核耗时”。 |
-- | **`created_at`** | TIMESTAMPTZ | 时间字段 | **申请提交时间**。 |
-- | **`updated_at`** | TIMESTAMPTZ | 时间字段 | **最后更新时间**。<br>比如用户重新上传了图片，这个时间会变。 |