CREATE TABLE IF NOT EXISTS messages
(
    id                 int auto_increment comment '自增主键ID'
        primary key,
    group_id           varchar(20)  null comment '群ID',
    timestamp          varchar(20)  not null comment '消息时间戳',
    sender             varchar(255) not null comment '发送者微信ID',
    content            text         null comment '消息内容',
    message_type       varchar(50)  null comment '消息类型（文本、图片、视频等）',
    attachment_url     text         null comment '附件URL（图片、视频链接）',
    message_id         varchar(32)  null comment '消息 id',
    message_xml        text         null comment '消息 xml 部分',
    raw_payload        longtext     null comment 'API 原始消息完整负载（完整序列化数据）',
    mentioned_user_ids longtext     null comment '消息中被@用户ID清单（JSON数组字符串）',
    message_thumb      longtext     null comment '视频或图片消息的缩略图路径',
    image_path         varchar(255) null comment '图片URL路径'
)
    comment '微信群消息存储表，记录所有群聊消息';

CREATE INDEX IF NOT EXISTS idx_date_timestamp
    on messages (timestamp);

CREATE INDEX IF NOT EXISTS idx_group_sender_timestamp
    on messages (group_id, sender, timestamp);

CREATE INDEX IF NOT EXISTS idx_group_timestamp
    on messages (group_id, timestamp);

CREATE INDEX IF NOT EXISTS idx_group_type_timestamp
    on messages (group_id, message_type, timestamp);

CREATE INDEX IF NOT EXISTS idx_media_pending_lookup
    on messages (message_type, image_path, timestamp, group_id);

CREATE INDEX IF NOT EXISTS idx_message_sender
    on messages (sender);

CREATE INDEX IF NOT EXISTS idx_message_type
    on messages (message_type);

CREATE INDEX IF NOT EXISTS messages_message_id_index
    on messages (message_id);

CREATE TABLE IF NOT EXISTS speech_counts
(
    id       int auto_increment comment '自增主键ID'
        primary key,
    group_id text null comment '群聊ID',
    wx_id    text null comment '用户微信ID',
    date     text null comment '统计日期（YYYY-MM-DD格式）',
    count    int  null comment '发言次数',
    constraint speech_counts_group_id_wx_id_date_uindex
        unique (group_id, wx_id, date) using hash
)
    comment '群成员每日发言统计表';

CREATE TABLE IF NOT EXISTS t_admin_accounts
(
    id            bigint auto_increment
        primary key,
    username      varchar(64)                          not null comment '登录用户名',
    password_hash varchar(255)                         not null comment '口令哈希',
    display_name  varchar(64)                          null comment '展示名称',
    status        tinyint  default 1                   not null comment '状态：1启用，0禁用',
    last_login_at datetime                             null comment '最近登录时间',
    last_login_ip varchar(64)                          null comment '最近登录IP',
    create_time   datetime default current_timestamp() null comment '创建时间',
    update_time   datetime default current_timestamp() null on update current_timestamp() comment '更新时间',
    constraint uk_admin_username
        unique (username)
)
    comment '后台管理员账号表';

CREATE TABLE IF NOT EXISTS t_chatroom_member
(
    id                 int auto_increment
        primary key,
    chatroom_id        varchar(64)                            not null comment '群聊ID',
    wxid               varchar(64)                            not null comment '成员微信ID',
    nick_name          varchar(128)                           null comment '成员昵称',
    display_name       varchar(128)                           null comment '群内显示名称',
    inviter_user_name  varchar(64)                            null comment '邀请人微信ID',
    member_flag        int                                    null comment '成员标志，2049表示管理员',
    big_head_img_url   text                                   null comment '大头像URL',
    small_head_img_url text                                   null comment '小头像URL',
    is_owner           tinyint(1) default 0                   null comment '是否群主：0否，1是',
    is_admin           tinyint(1) default 0                   null comment '是否管理员：0否，1是',
    sex                tinyint                                null comment '性别：1男，2女，0未知',
    signature          text                                   null comment '个性签名',
    alias              varchar(128)                           null comment '微信号',
    country            varchar(64)                            null comment '国家',
    province           varchar(64)                            null comment '省份',
    city               varchar(64)                            null comment '城市',
    label_list         text                                   null comment '标签列表',
    phone_num_list     text                                   null comment '电话号码列表',
    py_initial         varchar(128)                           null comment '拼音首字母',
    quan_pin           varchar(256)                           null comment '全拼',
    remark_py_initial  varchar(128)                           null comment '备注拼音首字母',
    remark_quan_pin    varchar(256)                           null comment '备注全拼',
    create_time        datetime   default current_timestamp() not null comment '创建时间',
    update_time        datetime   default current_timestamp() not null on update current_timestamp() comment '更新时间',
    latest_active_time datetime                               null comment '最后活跃时间',
    status             tinyint    default 1                   null comment '1-在群里，2-已退群',
    constraint idx_chatroom_member
        unique (chatroom_id, wxid)
)
    comment '微信群成员信息表';

CREATE TABLE IF NOT EXISTS t_chatrooms
(
    id                     int auto_increment
        primary key,
    chatroom_id            varchar(64)                          not null comment '群聊ID',
    nick_name              varchar(128)                         null comment '群昵称',
    py_initial             varchar(128)                         null comment '群昵称拼音首字母',
    quan_pin               varchar(256)                         null comment '群昵称全拼',
    sex                    tinyint                              null comment '性别',
    remark                 varchar(128)                         null comment '备注',
    remark_py_initial      varchar(128)                         null comment '备注拼音首字母',
    remark_quan_pin        varchar(256)                         null comment '备注全拼',
    chat_room_notify       tinyint                              null comment '群通知',
    chat_room_owner        varchar(64)                          null comment '群主微信ID',
    small_head_img_url     text                                 null comment '群头像URL',
    member_list            text                                 null comment '成员列表(JSON)',
    create_time            datetime default current_timestamp() not null comment '创建时间',
    update_time            datetime default current_timestamp() not null on update current_timestamp() comment '更新时间',
    chat_room_announcement text                                 null comment '群公告内容',
    constraint idx_chatroom_id
        unique (chatroom_id)
)
    comment '微信群信息表';

CREATE TABLE IF NOT EXISTS t_emoji_assets
(
    md5               varchar(64)                              not null
        primary key,
    total_length      int          default 0                   not null,
    semantic_text     varchar(255) default ''                  null comment '主语义文本',
    semantic_aliases  longtext                                 null comment '语义别名列表(JSON数组)',
    semantic_source   varchar(64)  default ''                  null comment '语义来源字段，如 desc/emojiattr',
    preview_url       varchar(255) default ''                  null comment '本地预览图路径',
    sample_message_id varchar(32)  default ''                  null comment '示例消息ID',
    sample_group_id   varchar(100) default ''                  null comment '示例群ID',
    sample_sender     varchar(100) default ''                  null comment '示例发送者',
    first_seen_at     datetime     default current_timestamp() null,
    last_seen_at      datetime     default current_timestamp() null on update current_timestamp(),
    created_at        datetime     default current_timestamp() null,
    updated_at        datetime     default current_timestamp() null on update current_timestamp()
);

CREATE INDEX IF NOT EXISTS idx_emoji_last_seen
    on t_emoji_assets (last_seen_at);

CREATE INDEX IF NOT EXISTS idx_emoji_preview
    on t_emoji_assets (preview_url);

CREATE TABLE IF NOT EXISTS t_encyclopedia_active_tasks
(
    active_task_id int auto_increment comment '任务ID'
        primary key,
    group_id       varchar(50)                                               not null comment '群聊ID',
    question       varchar(255)                                              not null comment '问题内容',
    answer         varchar(256)                                              not null comment '正确答案',
    score          int                                                       not null comment '答对可获得的分数',
    description    text                                                      null comment '问题描述或提示',
    holder_id      varchar(50)                                               not null comment '出题人ID',
    assigned_at    datetime                      default current_timestamp() null comment '任务分配时间',
    status         enum ('pending', 'completed') default 'pending'           null comment '任务状态',
    question_id    int                                                       null comment '问题ID'
)
    comment '百科答题游戏活跃任务表';

CREATE INDEX IF NOT EXISTS group_id
    on t_encyclopedia_active_tasks (group_id);

CREATE INDEX IF NOT EXISTS question_id
    on t_encyclopedia_active_tasks (question_id);

CREATE TABLE IF NOT EXISTS t_encyclopedia_groups
(
    group_id   varchar(50)                          not null comment '群聊ID'
        primary key,
    created_at datetime default current_timestamp() null comment '记录创建时间'
)
    comment '百科答题游戏群聊表';

CREATE TABLE IF NOT EXISTS t_encyclopedia_players
(
    player_id   varchar(50)                          not null comment '玩家ID（微信ID）',
    group_id    varchar(50)                          not null comment '群聊ID',
    player_name varchar(50)                          not null comment '玩家名称',
    points      int      default 0                   null comment '玩家积分',
    created_at  datetime default current_timestamp() null comment '记录创建时间',
    primary key (player_id, group_id)
)
    comment '百科答题游戏玩家表';

CREATE TABLE IF NOT EXISTS t_encyclopedia_task_history
(
    history_id     int auto_increment comment '历史记录ID'
        primary key,
    group_id       varchar(50)                            not null comment '群聊ID',
    active_task_id int                                    not null comment '关联的任务ID',
    player_id      varchar(50)                            not null comment '回答者ID',
    answer         varchar(256)                           not null comment '玩家的回答',
    is_correct     tinyint(1) default 0                   null comment '是否回答正确',
    points_earned  int        default 0                   null comment '获得的积分',
    completed_at   datetime   default current_timestamp() null comment '完成时间'
)
    comment '百科答题游戏任务历史表';

CREATE INDEX IF NOT EXISTS group_id
    on t_encyclopedia_task_history (group_id);

CREATE TABLE IF NOT EXISTS t_error_logs
(
    id            bigint auto_increment
        primary key,
    plugin_name   varchar(50)                          not null comment '插件名称',
    command       varchar(50)                          not null comment '触发的命令',
    user_id       varchar(50)                          not null comment '用户ID',
    group_id      varchar(50)                          null comment '群组ID，私聊为NULL',
    error_message text                                 not null comment '错误信息',
    stack_trace   text                                 null comment '堆栈跟踪',
    created_at    datetime default current_timestamp() not null comment '创建时间'
)
    comment '错误日志表';

CREATE INDEX IF NOT EXISTS idx_created_at
    on t_error_logs (created_at);

CREATE INDEX IF NOT EXISTS idx_plugin_name
    on t_error_logs (plugin_name);

CREATE TABLE IF NOT EXISTS t_fun_command_rule
(
    id               bigint auto_increment
        primary key,
    rule_name        varchar(128)                             not null,
    scope_type       varchar(20)  default 'global'            not null,
    scope_id         varchar(100) default ''                  not null,
    trigger_type     varchar(20)  default 'exact'             not null,
    trigger_text     varchar(500) default ''                  not null,
    event_key        varchar(64)  default ''                  not null,
    responses_json   longtext collate utf8mb4_bin             not null
        check (json_valid(`responses_json`)),
    priority         int          default 100                 not null,
    cooldown_seconds int          default 0                   not null,
    enabled          tinyint(1)   default 1                   not null,
    updated_by       varchar(100) default 'system'            not null,
    created_at       datetime     default current_timestamp() null,
    updated_at       datetime     default current_timestamp() null on update current_timestamp()
);

CREATE INDEX IF NOT EXISTS idx_event_key
    on t_fun_command_rule (event_key);

CREATE INDEX IF NOT EXISTS idx_scope_enabled_priority
    on t_fun_command_rule (scope_type, scope_id, enabled, priority);

CREATE INDEX IF NOT EXISTS idx_trigger_type
    on t_fun_command_rule (trigger_type);

CREATE TABLE IF NOT EXISTS t_group_command_user_stats
(
    id            bigint auto_increment
        primary key,
    group_id      varchar(50) not null comment '群组ID',
    plugin_name   varchar(50) not null comment '插件名称',
    command       varchar(50) not null comment '触发命令',
    user_id       varchar(50) not null comment '用户ID',
    first_used_at datetime    not null comment '首次触发时间',
    last_used_at  datetime    not null comment '最近触发时间',
    constraint uk_group_plugin_command_user
        unique (group_id, plugin_name, command, user_id)
)
    comment '群命令用户去重追踪表';

CREATE INDEX IF NOT EXISTS idx_group_plugin_command
    on t_group_command_user_stats (group_id, plugin_name, command);

CREATE INDEX IF NOT EXISTS idx_last_used_at
    on t_group_command_user_stats (last_used_at);

CREATE TABLE IF NOT EXISTS t_group_plugin_config
(
    id          bigint auto_increment
        primary key,
    group_id    varchar(100)                             not null,
    plugin_name varchar(128)                             not null,
    config_key  varchar(128) default 'default'           not null,
    config_json longtext collate utf8mb4_bin             not null
        check (json_valid(`config_json`)),
    enabled     tinyint(1)   default 1                   not null,
    version     int          default 1                   not null,
    updated_by  varchar(100) default 'system'            not null,
    created_at  datetime     default current_timestamp() null,
    updated_at  datetime     default current_timestamp() null on update current_timestamp(),
    constraint uk_group_plugin_key
        unique (group_id, plugin_name, config_key)
);

CREATE INDEX IF NOT EXISTS idx_group_plugin
    on t_group_plugin_config (group_id, plugin_name);

CREATE INDEX IF NOT EXISTS idx_plugin_name
    on t_group_plugin_config (plugin_name);

CREATE TABLE IF NOT EXISTS t_group_profile_snapshot
(
    id                          int auto_increment
        primary key,
    chatroom_id                 varchar(64)                              not null comment '群聊ID',
    group_name                  varchar(128) default ''                  null comment '群名称',
    profile_json                longtext                                 null comment '群画像快照JSON',
    source_summary_latest_at    datetime                                 null comment '构建时参考的最近群总结更新时间',
    source_message_latest_at    datetime                                 null comment '构建时参考的最近群消息时间',
    source_summary_count        int          default 0                   not null comment '构建时参考的群总结条数',
    source_message_sample_count int          default 0                   not null comment '构建时参考的消息样本数',
    last_generated_at           datetime     default current_timestamp() not null comment '最后一次生成时间',
    create_time                 datetime     default current_timestamp() not null comment '创建时间',
    update_time                 datetime     default current_timestamp() not null on update current_timestamp() comment '更新时间',
    constraint idx_group_profile_snapshot
        unique (chatroom_id)
)
    comment '群画像快照表';

CREATE INDEX IF NOT EXISTS idx_group_profile_generated_at
    on t_group_profile_snapshot (last_generated_at);

CREATE TABLE IF NOT EXISTS t_group_stats
(
    id            bigint auto_increment
        primary key,
    group_id      varchar(50)   not null comment '群组ID',
    plugin_name   varchar(50)   not null comment '插件名称',
    command       varchar(512)  not null comment '触发的命令',
    total_calls   int default 0 not null comment '总调用次数',
    success_calls int default 0 not null comment '成功调用次数',
    failed_calls  int default 0 not null comment '失败调用次数',
    unique_users  int default 0 not null comment '唯一用户数',
    first_used_at datetime      not null comment '首次使用时间',
    last_used_at  datetime      not null comment '最后使用时间',
    constraint uk_group_plugin_command
        unique (group_id, plugin_name, command)
)
    comment '群组使用统计表';

CREATE INDEX IF NOT EXISTS idx_group_id
    on t_group_stats (group_id);

CREATE INDEX IF NOT EXISTS idx_last_used_at
    on t_group_stats (last_used_at);

CREATE TABLE IF NOT EXISTS t_llm_backends
(
    name        varchar(128)                           not null
        primary key,
    config_json longtext collate utf8mb4_bin           not null
        check (json_valid(`config_json`)),
    enabled     tinyint(1) default 1                   not null,
    created_at  datetime   default current_timestamp() null,
    updated_at  datetime   default current_timestamp() null on update current_timestamp()
);

CREATE TABLE IF NOT EXISTS t_llm_catalog_meta
(
    meta_key   varchar(64)                          not null
        primary key,
    meta_value varchar(255)                         not null,
    updated_at datetime default current_timestamp() null on update current_timestamp()
);

CREATE TABLE IF NOT EXISTS t_llm_dify_apps
(
    name                varchar(128)                             not null
        primary key,
    provider_template   varchar(128)                             not null,
    app_key             varchar(255)                             not null,
    workflow_output_key varchar(128) default 'text'              null,
    config_json         longtext collate utf8mb4_bin             not null
        check (json_valid(`config_json`)),
    enabled             tinyint(1)   default 1                   not null,
    created_at          datetime     default current_timestamp() null,
    updated_at          datetime     default current_timestamp() null on update current_timestamp()
);

CREATE INDEX IF NOT EXISTS idx_provider_template
    on t_llm_dify_apps (provider_template);

CREATE TABLE IF NOT EXISTS t_llm_provider_templates
(
    name          varchar(128)                           not null
        primary key,
    provider_type varchar(64)                            not null,
    config_json   longtext collate utf8mb4_bin           not null
        check (json_valid(`config_json`)),
    enabled       tinyint(1) default 1                   not null,
    created_at    datetime   default current_timestamp() null,
    updated_at    datetime   default current_timestamp() null on update current_timestamp()
);

CREATE TABLE IF NOT EXISTS t_llm_scenes
(
    name        varchar(128)                           not null
        primary key,
    target_type varchar(32)                            not null,
    target_ref  varchar(128)                           not null,
    enabled     tinyint(1) default 1                   not null,
    created_at  datetime   default current_timestamp() null,
    updated_at  datetime   default current_timestamp() null on update current_timestamp()
);

CREATE INDEX IF NOT EXISTS idx_target
    on t_llm_scenes (target_type, target_ref);

CREATE TABLE IF NOT EXISTS t_member_context
(
    id                   int auto_increment
        primary key,
    chatroom_id          varchar(64)                               not null comment '群聊ID',
    wxid                 varchar(64)                               not null comment '成员微信ID',
    display_name         varchar(128)                              null comment '成员展示名',
    activity_level       varchar(32)                               null comment '活跃等级',
    message_pattern      varchar(255)                              null comment '发言模式',
    response_style_hint  varchar(255)                              null comment '回复建议',
    topics_of_interest   text                                      null comment '兴趣主题(JSON)',
    recent_focus         text                                      null comment '近期关注(JSON)',
    summary_text         text                                      null comment '交互摘要',
    confidence           decimal(4, 2) default 0.00                null comment '摘要置信度',
    source_message_count int           default 0                   null comment '样本消息数',
    source_days          int           default 30                  null comment '采样天数',
    meta_json            longtext                                  null comment '附加元数据(JSON)',
    last_profiled_at     datetime      default current_timestamp() not null comment '最后生成时间',
    create_time          datetime      default current_timestamp() not null comment '创建时间',
    update_time          datetime      default current_timestamp() not null on update current_timestamp() comment '更新时间',
    interaction_style    varchar(255)                              null comment '互动风格',
    constraint idx_member_context
        unique (chatroom_id, wxid)
)
    comment '群成员交互摘要表';

CREATE TABLE IF NOT EXISTS t_member_digest
(
    id                int auto_increment
        primary key,
    chatroom_id       varchar(64)                          not null comment '群聊ID',
    wxid              varchar(64)                          not null comment '成员微信ID',
    digest_type       varchar(16)                          not null comment '摘要类型 daily|weekly|monthly',
    period_key        varchar(32)                          not null comment '周期主键',
    period_start      datetime                             null comment '周期开始时间',
    period_end        datetime                             null comment '周期结束时间',
    display_name      varchar(128)                         null comment '成员展示名',
    source_count      int      default 0                   null comment '源数据条数',
    summary_text      text                                 null comment '摘要说明',
    structured_json   longtext                             null comment '结构化摘要JSON',
    meta_json         longtext                             null comment '附加元数据JSON',
    last_generated_at datetime default current_timestamp() not null comment '最后生成时间',
    create_time       datetime default current_timestamp() not null comment '创建时间',
    update_time       datetime default current_timestamp() not null on update current_timestamp() comment '更新时间',
    constraint idx_member_digest
        unique (chatroom_id, wxid, digest_type, period_key)
)
    comment '成员分层摘要表';

CREATE INDEX IF NOT EXISTS idx_digest_lookup
    on t_member_digest (chatroom_id, wxid, digest_type, period_end);

CREATE TABLE IF NOT EXISTS t_member_digest_group_state
(
    id                   int auto_increment
        primary key,
    chatroom_id          varchar(64)                             not null comment '群聊ID',
    bootstrap_status     varchar(16) default 'pending'           not null comment '初始化状态 pending|done|empty',
    last_bootstrap_at    datetime                                null comment '最近一次初始化尝试时间',
    bootstrap_days       int         default 0                   not null comment '最近一次初始化窗口天数',
    built_daily_count    int         default 0                   not null comment '最近一次初始化生成的日摘要数量',
    touched_member_count int         default 0                   not null comment '最近一次初始化触达的成员数量',
    extra_json           longtext                                null comment '附加状态信息',
    create_time          datetime    default current_timestamp() not null comment '创建时间',
    update_time          datetime    default current_timestamp() not null on update current_timestamp() comment '更新时间',
    constraint idx_digest_group_state
        unique (chatroom_id)
)
    comment '成员分层摘要群级状态表';

CREATE TABLE IF NOT EXISTS t_message_mentions
(
    id                bigint auto_increment
        primary key,
    message_id        varchar(32)                          not null comment '原始消息ID',
    group_id          varchar(100)                         not null comment '群ID',
    sender_id         varchar(100)                         not null comment '发送者ID（@发起人）',
    mentioned_user_id varchar(100)                         not null comment '被@用户ID',
    stat_date         date                                 not null comment '统计日期',
    msg_time          datetime                             not null comment '消息时间',
    create_time       datetime default current_timestamp() null comment '创建时间',
    constraint uk_message_sender_mentioned
        unique (message_id, sender_id, mentioned_user_id)
)
    comment '消息@关系明细表';

CREATE INDEX IF NOT EXISTS idx_group_date
    on t_message_mentions (group_id, stat_date);

CREATE INDEX IF NOT EXISTS idx_mentioned_group_date
    on t_message_mentions (mentioned_user_id, group_id, stat_date);

CREATE TABLE IF NOT EXISTS t_message_summary
(
    id                   int auto_increment
        primary key,
    chatroom_id          varchar(64)                              not null comment '群聊ID',
    group_name           varchar(128) default ''                  null comment '群名称',
    summary_type         varchar(16)                              not null comment '总结类型 daily|manual',
    period_key           varchar(32)                              not null comment '周期主键，如 2026-04-01',
    period_start         datetime                                 null comment '总结周期开始时间',
    period_end           datetime                                 null comment '总结周期结束时间',
    source_message_count int          default 0                   not null comment '源消息数量',
    summary_text         longtext                                 null comment '总结文本',
    image_path           varchar(255)                             null comment '总结图片路径',
    meta_json            longtext                                 null comment '附加元数据JSON',
    last_generated_at    datetime     default current_timestamp() not null comment '最后生成时间',
    create_time          datetime     default current_timestamp() not null comment '创建时间',
    update_time          datetime     default current_timestamp() not null on update current_timestamp() comment '更新时间',
    constraint idx_message_summary
        unique (chatroom_id, summary_type, period_key)
)
    comment '群消息总结表';

CREATE INDEX IF NOT EXISTS idx_message_summary_lookup
    on t_message_summary (chatroom_id, period_end);

CREATE TABLE IF NOT EXISTS t_plugin_point_config
(
    id              int auto_increment
        primary key,
    plugin_name     varchar(100)         not null,
    points_required int        default 0 null,
    is_enabled      tinyint(1) default 1 null,
    description     text                 null,
    constraint plugin_name
        unique (plugin_name)
);

CREATE TABLE IF NOT EXISTS t_plugin_schedule_logs
(
    id           bigint auto_increment
        primary key,
    schedule_id  bigint                                   not null,
    triggered_at datetime     default current_timestamp() null,
    status       varchar(32)                              not null,
    summary      varchar(255) default ''                  null,
    detail_json  longtext collate utf8mb4_bin             null
        check (json_valid(`detail_json`))
);

CREATE INDEX IF NOT EXISTS idx_schedule_time
    on t_plugin_schedule_logs (schedule_id, triggered_at);

CREATE TABLE IF NOT EXISTS t_plugin_schedules
(
    id             bigint auto_increment
        primary key,
    plugin_name    varchar(128)                              not null,
    action_key     varchar(64)                               not null,
    action_name    varchar(128)                              not null,
    description    varchar(255) default ''                   null,
    trigger_type   varchar(64)                               not null,
    trigger_config longtext collate utf8mb4_bin              not null
        check (json_valid(`trigger_config`)),
    target_scope   varchar(64)  default 'all_enabled_groups' not null,
    target_config  longtext collate utf8mb4_bin              null
        check (json_valid(`target_config`)),
    payload        longtext collate utf8mb4_bin              null
        check (json_valid(`payload`)),
    enabled        tinyint(1)   default 0                    not null,
    created_at     datetime     default current_timestamp()  null,
    updated_at     datetime     default current_timestamp()  null on update current_timestamp(),
    constraint uk_plugin_action
        unique (plugin_name, action_key)
);

CREATE TABLE IF NOT EXISTS t_plugin_stats
(
    id               bigint auto_increment
        primary key,
    plugin_name      varchar(50)                          not null comment '插件名称',
    command          varchar(512)                         not null comment '触发的命令',
    stat_date        date                                 not null comment '统计日期',
    total_calls      int      default 0                   not null comment '总调用次数',
    success_calls    int      default 0                   not null comment '成功调用次数',
    failed_calls     int      default 0                   not null comment '失败调用次数',
    group_calls      int      default 0                   not null comment '群聊调用次数',
    private_calls    int      default 0                   not null comment '私聊调用次数',
    avg_process_time float    default 0                   not null comment '平均处理时间(毫秒)',
    created_at       datetime default current_timestamp() not null comment '创建时间',
    updated_at       datetime default current_timestamp() not null on update current_timestamp() comment '更新时间',
    constraint uk_plugin_command_date
        unique (plugin_name, command, stat_date)
)
    comment '插件统计汇总表';

CREATE INDEX IF NOT EXISTS idx_stat_date
    on t_plugin_stats (stat_date);

CREATE TABLE IF NOT EXISTS t_point_transactions
(
    id               int auto_increment
        primary key,
    user_id          varchar(100)                          not null,
    group_id         varchar(100)                          not null,
    transaction_type varchar(20)                           not null,
    points           int                                   not null,
    source           varchar(50)                           not null,
    description      text                                  null,
    created_at       timestamp default current_timestamp() null
);

CREATE TABLE IF NOT EXISTS t_prison_records
(
    id              int auto_increment
        primary key,
    user_id         varchar(100)                          not null,
    group_id        varchar(100)                          not null,
    start_time      timestamp default current_timestamp() null,
    end_time        timestamp                             not null,
    reason          varchar(255)                          null,
    status          tinyint   default 1                   null comment '1:在押 0:已释放',
    bailout_user_id varchar(100)                          null,
    bailout_time    timestamp                             null,
    created_at      timestamp default current_timestamp() null
);

CREATE TABLE IF NOT EXISTS t_push_feedback
(
    feedback_id varchar(36)                          not null
        primary key,
    task_id     varchar(36)                          not null,
    user_id     varchar(50)                          not null,
    content     text                                 not null,
    timestamp   datetime default current_timestamp() null
);

CREATE TABLE IF NOT EXISTS t_push_previews
(
    preview_id varchar(36)                                                        not null
        primary key,
    task_id    varchar(36)                                                        not null,
    content    longtext collate utf8mb4_bin                                       not null
        check (json_valid(`content`)),
    recipients longtext collate utf8mb4_bin                                       not null
        check (json_valid(`recipients`)),
    validation longtext collate utf8mb4_bin                                       null
        check (json_valid(`validation`)),
    status     enum ('sent', 'confirmed', 'modified') default 'sent'              null,
    created_at datetime                               default current_timestamp() null
);

CREATE TABLE IF NOT EXISTS t_push_task_logs
(
    log_id    varchar(36)                                            not null
        primary key,
    task_id   varchar(36)                                            not null,
    action    enum ('create', 'update', 'delete', 'pause', 'resume') not null,
    user_id   varchar(50)                                            not null,
    changes   longtext collate utf8mb4_bin                           null
        check (json_valid(`changes`)),
    timestamp datetime default current_timestamp()                   null
);

CREATE TABLE IF NOT EXISTS t_push_tasks
(
    task_id             varchar(36)                                                                                         not null
        primary key,
    name                varchar(50)                                                                                         not null,
    schedule_type       enum ('once', 'recurring')                                                                          not null,
    schedule_time       datetime                                                                                            not null,
    recurring_interval  enum ('daily', 'weekly', 'monthly')                                                                 null,
    recurring_end       datetime                                                                                            null,
    recurring_time      time                                                                                                null,
    weekly_days         longtext collate utf8mb4_bin                                                                        null
        check (json_valid(`weekly_days`)),
    monthly_day         int                                                                                                 null,
    content_text        text                                                                                                null,
    content_image       varchar(255)                                                                                        null,
    content_link        longtext collate utf8mb4_bin                                                                        null
        check (json_valid(`content_link`)),
    content_voice       varchar(255)                                                                                        null comment '语音消息文件路径',
    content_video       varchar(255)                                                                                        null comment '视频消息文件路径',
    content_miniprogram longtext collate utf8mb4_bin                                                                        null
        check (json_valid(`content_miniprogram`)),
    groups              longtext collate utf8mb4_bin                                                                        null
        check (json_valid(`groups`)),
    priority            enum ('high', 'medium', 'low')                                          default 'medium'            null,
    status              enum ('draft', 'scheduled', 'running', 'completed', 'failed', 'paused') default 'draft'             null,
    creator_id          varchar(50)                                                                                         not null,
    preview_recipients  longtext collate utf8mb4_bin                                                                        null
        check (json_valid(`preview_recipients`)),
    created_at          datetime                                                                default current_timestamp() null,
    updated_at          datetime                                                                default current_timestamp() null on update current_timestamp()
);

CREATE TABLE IF NOT EXISTS t_sign_history
(
    id            bigint auto_increment comment '历史记录ID'
        primary key,
    wx_id         varchar(100)                           not null comment '用户微信ID',
    group_id      varchar(100)                           not null comment '群聊ID',
    sign_date     date                                   not null comment '签到日期',
    sign_time     datetime                               not null comment '签到时间',
    is_makeup     tinyint(1) default 0                   null comment '是否为补签',
    points_earned int        default 0                   null comment '获得的积分',
    streak_count  int        default 1                   null comment '当时的连签天数',
    create_time   datetime   default current_timestamp() null comment '记录创建时间'
)
    comment '用户签到历史记录表';

CREATE INDEX IF NOT EXISTS idx_sign_date
    on t_sign_history (sign_date);

CREATE INDEX IF NOT EXISTS idx_user_group
    on t_sign_history (wx_id, group_id);

CREATE TABLE IF NOT EXISTS t_sign_record
(
    id                     bigint auto_increment comment '自增主键ID'
        primary key,
    wx_id                  varchar(100)                         not null comment '用户微信ID',
    group_id               varchar(100)                         not null comment '群聊ID',
    wx_nick_name           varchar(100)                         not null comment '用户昵称',
    points                 int      default 0                   null comment '积分数量',
    sign_stat              datetime                             null comment '最近签到时间',
    signin_streak          int      default 0                   null comment '连续签到天数',
    create_time            datetime default current_timestamp() null comment '记录创建时间',
    update_time            datetime default current_timestamp() null on update current_timestamp() comment '记录更新时间',
    last_sign_date         datetime                             null comment '上一次签到日期',
    streak_start_sign_date datetime                             null comment '连续签到第一天日期',
    last_continuous_days   int      default 0                   null comment '历史最长连续签到天数',
    total_sign_days        int      default 0                   null comment '总签到天数',
    previous_streak        int      default 0                   null comment '断签前的连签天数',
    constraint unique_sign
        unique (wx_id, group_id)
)
    comment '用户群内签到记录表';

CREATE TABLE IF NOT EXISTS t_social_edges_daily
(
    id                bigint auto_increment
        primary key,
    stat_date         date                                       not null comment '统计日期',
    group_id          varchar(100)                               not null comment '群ID',
    from_user_id      varchar(100)                               not null comment '互动发起方',
    to_user_id        varchar(100)                               not null comment '互动接收方',
    mention_count     int            default 0                   not null comment '@次数',
    reply_count       int            default 0                   not null comment '回复次数（预留）',
    interaction_score decimal(10, 2) default 0.00                not null comment '互动强度分（可用于关系网权重）',
    create_time       datetime       default current_timestamp() null comment '创建时间',
    update_time       datetime       default current_timestamp() null on update current_timestamp() comment '更新时间',
    constraint uk_day_group_edge
        unique (stat_date, group_id, from_user_id, to_user_id)
)
    comment '社交关系日边表（用于关系网和搭子榜）';

CREATE INDEX IF NOT EXISTS idx_group_day_score
    on t_social_edges_daily (group_id, stat_date, interaction_score);

CREATE TABLE IF NOT EXISTS t_system_job_logs
(
    id           bigint auto_increment
        primary key,
    job_key      varchar(64)                              not null,
    triggered_at datetime     default current_timestamp() null,
    status       varchar(32)                              not null,
    summary      varchar(255) default ''                  null,
    detail_json  longtext collate utf8mb4_bin             null
        check (json_valid(`detail_json`)),
    duration_ms  int                                      null
);

CREATE INDEX IF NOT EXISTS idx_job_time
    on t_system_job_logs (job_key, triggered_at);

CREATE TABLE IF NOT EXISTS t_system_jobs
(
    job_key        varchar(64)                              not null
        primary key,
    name           varchar(128)                             not null,
    description    varchar(255) default ''                  null,
    trigger_type   varchar(64)                              not null,
    trigger_config longtext collate utf8mb4_bin             not null
        check (json_valid(`trigger_config`)),
    enabled        tinyint(1)   default 1                   not null,
    created_at     datetime     default current_timestamp() null,
    updated_at     datetime     default current_timestamp() null on update current_timestamp()
);

CREATE TABLE IF NOT EXISTS t_user_levels
(
    id             bigint auto_increment
        primary key,
    user_id        varchar(100)                         not null,
    group_id       varchar(100)                         not null,
    exp            bigint   default 0                   null,
    level          int      default 1                   null,
    last_calc      datetime default current_timestamp() null,
    last_active_at datetime default current_timestamp() null,
    constraint uniq_user_group
        unique (user_id, group_id)
);

CREATE TABLE IF NOT EXISTS t_user_points
(
    id             int auto_increment
        primary key,
    user_id        varchar(100)                          not null,
    group_id       varchar(100)                          not null,
    total_points   int       default 0                   null,
    checkin_points int       default 0                   null,
    game_points    int       default 0                   null,
    other_points   int       default 0                   null,
    last_updated   timestamp default current_timestamp() null on update current_timestamp(),
    constraint user_id
        unique (user_id, group_id)
);

CREATE TABLE IF NOT EXISTS t_user_stats
(
    id            bigint auto_increment
        primary key,
    user_id       varchar(50)   not null comment '用户ID',
    plugin_name   varchar(50)   not null comment '插件名称',
    command       varchar(256)  not null comment '触发的命令',
    total_calls   int default 0 not null comment '总调用次数',
    success_calls int default 0 not null comment '成功调用次数',
    failed_calls  int default 0 not null comment '失败调用次数',
    first_used_at datetime      not null comment '首次使用时间',
    last_used_at  datetime      not null comment '最后使用时间',
    constraint uk_user_plugin_command
        unique (user_id, plugin_name, command)
)
    comment '用户使用统计表';

CREATE INDEX IF NOT EXISTS idx_last_used_at
    on t_user_stats (last_used_at);

CREATE INDEX IF NOT EXISTS idx_user_id
    on t_user_stats (user_id);

CREATE TABLE IF NOT EXISTS t_value_rank_snapshot
(
    id                bigint auto_increment
        primary key,
    stat_date         date                                       not null comment '统计日期',
    group_id          varchar(100)                               not null comment '群ID',
    user_id           varchar(100)                               not null comment '用户ID',
    score             decimal(10, 2) default 0.00                not null comment '身价分',
    rank_no           int            default 0                   not null comment '排名',
    title             varchar(50)    default ''                  not null comment '称号',
    points_total      int            default 0                   not null comment '积分存量',
    msg_count_7d      int            default 0                   not null comment '7日发言数',
    active_days_30    int            default 0                   not null comment '30日活跃天数',
    inactive_days     int            default 0                   not null comment '距今未发言天数',
    score_detail_json longtext collate utf8mb4_bin               null comment '分项得分明细'
        check (json_valid(`score_detail_json`)),
    created_at        datetime       default current_timestamp() not null,
    updated_at        datetime       default current_timestamp() not null on update current_timestamp(),
    constraint uniq_day_group_user
        unique (stat_date, group_id, user_id)
)
    comment '身价日快照表';

CREATE INDEX IF NOT EXISTS idx_group_day_rank
    on t_value_rank_snapshot (group_id, stat_date, rank_no);

CREATE TABLE IF NOT EXISTS t_value_rank_social_daily
(
    id                   bigint auto_increment
        primary key,
    stat_date            date                                       not null comment '统计日期',
    group_id             varchar(100)                               not null comment '群ID',
    user_id              varchar(100)                               not null comment '用户ID',
    mentioned_count      int            default 0                   not null comment '被@次数（入度）',
    mention_others_count int            default 0                   not null comment '@他人次数（出度）',
    unique_interactors   int            default 0                   not null comment '与其发生互动的去重人数',
    interaction_score    decimal(10, 2) default 0.00                not null comment '社交影响力分',
    create_time          datetime       default current_timestamp() null comment '创建时间',
    update_time          datetime       default current_timestamp() null on update current_timestamp() comment '更新时间',
    constraint uk_day_group_user
        unique (stat_date, group_id, user_id)
)
    comment 'Value Rank 社交日汇总表';

CREATE INDEX IF NOT EXISTS idx_group_day_score
    on t_value_rank_social_daily (group_id, stat_date, interaction_score);

CREATE TABLE IF NOT EXISTS t_wechat_contacts
(
    id                 int auto_increment
        primary key,
    user_name          varchar(64)                          not null comment '微信ID',
    nick_name          varchar(128)                         null comment '昵称',
    py_initial         varchar(128)                         null comment '拼音首字母',
    quan_pin           varchar(256)                         null comment '全拼',
    sex                tinyint                              null comment '性别：1男，2女，0未知',
    remark             varchar(128)                         null comment '备注',
    remark_py_initial  varchar(128)                         null comment '备注拼音首字母',
    remark_quan_pin    varchar(256)                         null comment '备注全拼',
    signature          text                                 null comment '个性签名',
    alias              varchar(128)                         null comment '微信号',
    sns_bg_img         text                                 null comment '朋友圈背景图',
    country            varchar(64)                          null comment '国家',
    province           varchar(64)                          null comment '省份',
    city               varchar(64)                          null comment '城市',
    big_head_img_url   text                                 null comment '大头像URL',
    small_head_img_url text                                 null comment '小头像URL',
    description        text                                 null comment '描述',
    card_img_url       text                                 null comment '名片图片URL',
    label_list         text                                 null comment '标签列表',
    phone_num_list     text                                 null comment '电话号码列表',
    type               enum ('friends', 'chatrooms', 'ghs') not null comment '联系人类型：好友、群聊、公众号',
    create_time        datetime default current_timestamp() not null comment '创建时间',
    update_time        datetime default current_timestamp() not null on update current_timestamp() comment '更新时间',
    constraint idx_user_name
        unique (user_name)
)
    comment '微信联系人信息表';

CREATE TABLE IF NOT EXISTS t_xiuxian_clan
(
    clan_id        bigint auto_increment comment '门派ID'
        primary key,
    clan_name      varchar(100) not null comment '门派名称',
    group_id       varchar(100) not null comment '所属群ID',
    leader_user_id varchar(100) not null comment '掌门ID',
    constraint uk_group_clan_name
        unique (group_id, clan_name)
)
    comment '门派表' collate = utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS t_xiuxian_item
(
    item_id     int auto_increment comment '物品ID'
        primary key,
    name        varchar(100) not null comment '物品名称',
    type        varchar(50)  not null comment '物品类型',
    description text         null comment '物品描述',
    constraint uk_name
        unique (name)
)
    comment '物品定义表' collate = utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS t_xiuxian_player
(
    user_id             varchar(100)                 not null comment '平台用户ID'
        primary key,
    group_id            varchar(100)                 not null comment '主要所在群ID',
    dao_name            varchar(100)                 not null comment '道号',
    realm               varchar(50) default '凡人'   null comment '境界',
    spirit_root         varchar(50) default '凡灵根' null comment '灵根天赋',
    clan_id             bigint                       null comment '所属门派ID',
    cultivation_points  bigint      default 0        null comment '修为',
    spirit_stone        bigint      default 0        null comment '灵石',
    status              varchar(20) default 'Idle'   null comment '玩家状态',
    status_until        datetime                     null comment '状态到期时间',
    last_cultivate_time datetime                     null comment '上次闭关开始时间',
    constraint fk_clan_id
        foreign key (clan_id) references t_xiuxian_clan (clan_id)
            on delete set null
)
    comment '玩家核心数据表' collate = utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS t_xiuxian_inventory
(
    id       bigint auto_increment comment '背包条目ID'
        primary key,
    user_id  varchar(100)  not null comment '玩家ID',
    item_id  int           not null comment '物品ID',
    quantity int default 0 not null comment '数量',
    constraint uk_user_item
        unique (user_id, item_id),
    constraint fk_inv_item
        foreign key (item_id) references t_xiuxian_item (item_id)
            on delete cascade,
    constraint fk_inv_user
        foreign key (user_id) references t_xiuxian_player (user_id)
            on delete cascade
)
    comment '玩家背包表' collate = utf8mb4_unicode_ci;

CREATE INDEX IF NOT EXISTS idx_clan_id
    on t_xiuxian_player (clan_id);

CREATE INDEX IF NOT EXISTS idx_realm
    on t_xiuxian_player (realm);

