-- ============================================================
-- Msg 服务数据库初始化脚本（v1.0 完整实现）
-- 对齐 services/msg/src/notifications/notifications.schema.ts
--      services/msg/src/shared/outbox/outbox.schema.ts
-- 仲裁依据：02-architecture-design.md §3.1 + G11（cuid2 varchar(32)）
-- ============================================================

-- 数据库已由 docker-compose 创建（msg_db），此处仅建表
-- 若需切换数据库：USE msg_db;

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ============================================================
-- 1. msg_notifications（通知主表 · 扩展）
-- ============================================================
CREATE TABLE IF NOT EXISTS `msg_notifications` (
  `id` VARCHAR(32) NOT NULL COMMENT 'cuid2 主键',
  `user_id` VARCHAR(32) NOT NULL COMMENT '接收用户 ID',
  `type` VARCHAR(32) NOT NULL COMMENT '通知类型: system/exam/homework/grade/attendance/mastery',
  `title` VARCHAR(255) NOT NULL COMMENT '通知标题',
  `content` TEXT NOT NULL COMMENT '通知正文',
  `channel` VARCHAR(32) NOT NULL COMMENT '渠道: in_app/email/sms/push/wechat',
  `is_read` BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否已读',
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `status` VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '状态: pending/sent/delivered/read/recalled/failed',
  `metadata` JSON NULL COMMENT '扩展元数据',
  `related_entity_type` VARCHAR(64) NULL COMMENT '关联实体类型(exam/homework/grade/attendance/mastery)',
  `related_entity_id` VARCHAR(32) NULL COMMENT '关联实体 ID',
  `group_id` VARCHAR(32) NULL COMMENT '群组 ID（批量发送/撤回用）',
  `sender_id` VARCHAR(32) NULL COMMENT '发送者 ID',
  `template_id` VARCHAR(32) NULL COMMENT '使用的模板 ID',
  `event_id` VARCHAR(64) NULL COMMENT '幂等键（Kafka event_id 或自生成）',
  `read_at` TIMESTAMP NULL COMMENT '已读时间',
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_notifications_event_id` (`event_id`),
  KEY `idx_notifications_user_id` (`user_id`),
  KEY `idx_notifications_is_read` (`is_read`),
  KEY `idx_notifications_created_at` (`created_at`),
  KEY `idx_notifications_user_read` (`user_id`, `is_read`),
  KEY `idx_notifications_group_id` (`group_id`),
  KEY `idx_notifications_related` (`related_entity_type`, `related_entity_id`),
  KEY `idx_notifications_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='msg 通知主表';

-- ============================================================
-- 2. msg_notification_preferences（用户偏好 · 扩展）
-- ============================================================
CREATE TABLE IF NOT EXISTS `msg_notification_preferences` (
  `id` VARCHAR(32) NOT NULL COMMENT 'cuid2 主键',
  `user_id` VARCHAR(32) NOT NULL COMMENT '用户 ID',
  `type` VARCHAR(32) NOT NULL COMMENT '通知类型',
  `channels` JSON NOT NULL COMMENT '启用的渠道数组,如 ["in_app","email"]',
  `frequency_limit` INT NULL COMMENT '频率限制(每小时最大通知数)',
  `quiet_hours_start` VARCHAR(8) NULL COMMENT '免打扰开始(HH:MM)',
  `quiet_hours_end` VARCHAR(8) NULL COMMENT '免打扰结束(HH:MM)',
  `quiet_hours_timezone` VARCHAR(64) NULL DEFAULT 'Asia/Shanghai',
  `enabled` BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否启用该类型偏好',
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_preferences_user_type` (`user_id`, `type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='msg 用户通知偏好';

-- ============================================================
-- 3. msg_notification_templates（通知模板）
-- ============================================================
CREATE TABLE IF NOT EXISTS `msg_notification_templates` (
  `id` VARCHAR(32) NOT NULL COMMENT 'cuid2 主键',
  `code` VARCHAR(64) NOT NULL COMMENT '模板编码(业务可读)',
  `type` VARCHAR(32) NOT NULL COMMENT '通知类型',
  `title_template` VARCHAR(255) NOT NULL COMMENT '标题模板(含 {{var}})',
  `content_template` TEXT NOT NULL COMMENT '正文模板(含 {{var}})',
  `default_channels` JSON NOT NULL COMMENT '默认渠道数组',
  `variables` JSON NOT NULL COMMENT '变量声明数组,如 ["userName","examTitle"]',
  `locale` VARCHAR(16) NOT NULL DEFAULT 'zh-CN',
  `status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '状态: draft/active/archived',
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_templates_code` (`code`),
  KEY `idx_templates_type` (`type`),
  KEY `idx_templates_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='msg 通知模板';

-- ============================================================
-- 4. msg_notification_deliveries（投递记录）
-- ============================================================
CREATE TABLE IF NOT EXISTS `msg_notification_deliveries` (
  `id` VARCHAR(32) NOT NULL COMMENT 'cuid2 主键',
  `notification_id` VARCHAR(32) NOT NULL COMMENT '关联通知 ID',
  `channel` VARCHAR(32) NOT NULL COMMENT '投递渠道',
  `status` VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '状态: pending/sent/delivered/failed/retrying',
  `external_id` VARCHAR(128) NULL COMMENT '外部服务返回的消息 ID',
  `attempt_count` INT NOT NULL DEFAULT 0,
  `max_retry` INT NOT NULL DEFAULT 3,
  `last_error` TEXT NULL,
  `next_retry_at` TIMESTAMP NULL,
  `delivered_at` TIMESTAMP NULL,
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_deliveries_notification_id` (`notification_id`),
  KEY `idx_deliveries_status` (`status`),
  KEY `idx_deliveries_next_retry` (`next_retry_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='msg 通知投递记录';

-- ============================================================
-- 5. msg_outbox_events（事务性 Outbox）
-- ============================================================
CREATE TABLE IF NOT EXISTS `msg_outbox_events` (
  `event_id` VARCHAR(64) NOT NULL COMMENT '事件 ID(Kafka 幂等键)',
  `aggregate_type` VARCHAR(64) NOT NULL COMMENT '聚合类型: notification',
  `aggregate_id` VARCHAR(32) NOT NULL COMMENT '聚合 ID(通知 ID)',
  `event_type` VARCHAR(64) NOT NULL COMMENT '事件类型: notification.sent/read/recalled/failed',
  `topic` VARCHAR(128) NOT NULL COMMENT '目标 Kafka topic',
  `payload` JSON NOT NULL COMMENT '事件 payload',
  `status` VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT '状态: pending/published/failed',
  `retry_count` INT NOT NULL DEFAULT 0,
  `max_retry_count` INT NOT NULL DEFAULT 5,
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `published_at` TIMESTAMP NULL,
  `next_retry_at` TIMESTAMP NULL,
  `last_error` TEXT NULL,
  `metadata` JSON NULL,
  PRIMARY KEY (`event_id`),
  KEY `idx_outbox_status_next_retry` (`status`, `next_retry_at`),
  KEY `idx_outbox_topic` (`topic`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='msg Outbox 事务性事件';

-- ============================================================
-- 6. processed_events（消费幂等 · Redis 降级表）
-- ============================================================
CREATE TABLE IF NOT EXISTS `processed_events` (
  `event_id` VARCHAR(64) NOT NULL COMMENT '事件 ID(幂等键)',
  `topic` VARCHAR(128) NOT NULL COMMENT '来源 topic',
  `processed_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`event_id`),
  KEY `idx_processed_topic` (`topic`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='msg 消费幂等记录';

SET FOREIGN_KEY_CHECKS = 1;

-- ============================================================
-- 初始化数据：默认通知模板（可选）
-- ============================================================
INSERT INTO `msg_notification_templates` (`id`, `code`, `type`, `title_template`, `content_template`, `default_channels`, `variables`, `locale`, `status`)
SELECT * FROM (SELECT
  'tmpl_welcome_001' AS id,
  'welcome' AS code,
  'system' AS type,
  '欢迎加入 Edu 云课堂' AS title_template,
  '你好 {{userName}}，欢迎加入 Edu 云课堂！开始你的学习之旅吧。' AS content_template,
  JSON_ARRAY('in_app') AS default_channels,
  JSON_ARRAY('userName') AS variables,
  'zh-CN' AS locale,
  'active' AS status
) AS tmp
WHERE NOT EXISTS (SELECT 1 FROM `msg_notification_templates` WHERE `code` = 'welcome');

INSERT INTO `msg_notification_templates` (`id`, `code`, `type`, `title_template`, `content_template`, `default_channels`, `variables`, `locale`, `status`)
SELECT * FROM (SELECT
  'tmpl_exam_published_001' AS id,
  'exam_published' AS code,
  'exam' AS type,
  '新考试通知' AS title_template,
  '「{{className}}」班级发布了新考试：{{examTitle}}' AS content_template,
  JSON_ARRAY('in_app') AS default_channels,
  JSON_ARRAY('className', 'examTitle') AS variables,
  'zh-CN' AS locale,
  'active' AS status
) AS tmp
WHERE NOT EXISTS (SELECT 1 FROM `msg_notification_templates` WHERE `code` = 'exam_published');

INSERT INTO `msg_notification_templates` (`id`, `code`, `type`, `title_template`, `content_template`, `default_channels`, `variables`, `locale`, `status`)
SELECT * FROM (SELECT
  'tmpl_grade_recorded_001' AS id,
  'grade_recorded' AS code,
  'grade' AS type,
  '成绩录入通知' AS title_template,
  '你的{{subject}}成绩已录入{{score}}' AS content_template,
  JSON_ARRAY('in_app') AS default_channels,
  JSON_ARRAY('subject', 'score') AS variables,
  'zh-CN' AS locale,
  'active' AS status
) AS tmp
WHERE NOT EXISTS (SELECT 1 FROM `msg_notification_templates` WHERE `code` = 'grade_recorded');
