import {
  boolean,
  int,
  json,
  mysqlTable,
  text,
  timestamp,
  varchar,
} from "drizzle-orm/mysql-core";

/**
 * msg 服务数据库 Schema。
 *
 * 仲裁依据：
 * - 02-architecture-design.md §3.1（表清单 + 字段 + 索引）
 * - G11：ID 用 cuid2（varchar(32)）
 * - proto msg.proto 字段对齐（Notification / NotificationPreference / NotificationTemplate）
 *
 * 表清单：
 * - msg_notifications（通知主表，扩展字段）
 * - msg_notification_preferences（用户偏好，扩展字段）
 * - msg_notification_templates（通知模板，新增）
 * - msg_notification_deliveries（投递记录，新增）
 *
 * 注：msg_outbox_events / processed_events 在 shared/outbox/outbox.schema.ts
 */

// ============================================================
// 通知状态 / 渠道 / 类型 枚举（字符串枚举，DB 存 varchar）
// ============================================================

export type NotificationStatus =
  "pending" | "sent" | "delivered" | "read" | "recalled" | "failed";

export type NotificationChannel =
  "in_app" | "email" | "sms" | "push" | "wechat";

export type NotificationType =
  "system" | "exam" | "homework" | "grade" | "attendance" | "mastery";

export type DeliveryStatus =
  "pending" | "sent" | "delivered" | "failed" | "retrying";

export type TemplateStatus = "draft" | "active" | "archived";

// ============================================================
// msg_notifications（通知主表 · 扩展）
// ============================================================

export const notifications = mysqlTable("msg_notifications", {
  id: varchar("id", { length: 32 }).notNull().primaryKey(),
  userId: varchar("user_id", { length: 32 }).notNull(),
  type: varchar("type", { length: 32 }).notNull().$type<NotificationType>(),
  title: varchar("title", { length: 255 }).notNull(),
  content: text("content").notNull(),
  channel: varchar("channel", { length: 32 })
    .notNull()
    .$type<NotificationChannel>(),
  isRead: boolean("is_read").notNull().default(false),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  // 扩展字段（P5）
  status: varchar("status", { length: 32 })
    .notNull()
    .default("pending")
    .$type<NotificationStatus>(),
  metadata: json("metadata").$type<Record<string, string> | null>(),
  relatedEntityType: varchar("related_entity_type", { length: 64 }),
  relatedEntityId: varchar("related_entity_id", { length: 32 }),
  groupId: varchar("group_id", { length: 32 }),
  senderId: varchar("sender_id", { length: 32 }),
  templateId: varchar("template_id", { length: 32 }),
  eventId: varchar("event_id", { length: 64 }),
  readAt: timestamp("read_at"),
  updatedAt: timestamp("updated_at").notNull().defaultNow().onUpdateNow(),
});

export type Notification = typeof notifications.$inferSelect;
export type NewNotification = typeof notifications.$inferInsert;

// ============================================================
// msg_notification_preferences（用户偏好 · 扩展）
// ============================================================

export const notificationPreferences = mysqlTable(
  "msg_notification_preferences",
  {
    id: varchar("id", { length: 32 }).notNull().primaryKey(),
    userId: varchar("user_id", { length: 32 }).notNull(),
    type: varchar("type", { length: 32 }).notNull().$type<NotificationType>(),
    channels: json("channels").notNull().$type<NotificationChannel[]>(),
    frequencyLimit: int("frequency_limit"),
    quietHoursStart: varchar("quiet_hours_start", { length: 8 }),
    quietHoursEnd: varchar("quiet_hours_end", { length: 8 }),
    quietHoursTimezone: varchar("quiet_hours_timezone", { length: 64 }).default(
      "Asia/Shanghai",
    ),
    enabled: boolean("enabled").notNull().default(true),
    createdAt: timestamp("created_at").notNull().defaultNow(),
    updatedAt: timestamp("updated_at").notNull().defaultNow().onUpdateNow(),
  },
);

export type NotificationPreference =
  typeof notificationPreferences.$inferSelect;
export type NewNotificationPreference =
  typeof notificationPreferences.$inferInsert;

// ============================================================
// msg_notification_templates（通知模板 · 新增）
// ============================================================

export const notificationTemplates = mysqlTable("msg_notification_templates", {
  id: varchar("id", { length: 32 }).notNull().primaryKey(),
  code: varchar("code", { length: 64 }).notNull(),
  type: varchar("type", { length: 32 }).notNull().$type<NotificationType>(),
  titleTemplate: varchar("title_template", { length: 255 }).notNull(),
  contentTemplate: text("content_template").notNull(),
  defaultChannels: json("default_channels")
    .notNull()
    .$type<NotificationChannel[]>(),
  variables: json("variables").notNull().$type<string[]>(),
  locale: varchar("locale", { length: 16 }).notNull().default("zh-CN"),
  status: varchar("status", { length: 32 })
    .notNull()
    .default("draft")
    .$type<TemplateStatus>(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow().onUpdateNow(),
});

export type NotificationTemplate = typeof notificationTemplates.$inferSelect;
export type NewNotificationTemplate = typeof notificationTemplates.$inferInsert;

// ============================================================
// msg_notification_deliveries（投递记录 · 新增）
// ============================================================

export const notificationDeliveries = mysqlTable(
  "msg_notification_deliveries",
  {
    id: varchar("id", { length: 32 }).notNull().primaryKey(),
    notificationId: varchar("notification_id", { length: 32 }).notNull(),
    channel: varchar("channel", { length: 32 })
      .notNull()
      .$type<NotificationChannel>(),
    status: varchar("status", { length: 32 })
      .notNull()
      .default("pending")
      .$type<DeliveryStatus>(),
    externalId: varchar("external_id", { length: 128 }),
    attemptCount: int("attempt_count").notNull().default(0),
    maxRetry: int("max_retry").notNull().default(3),
    lastError: text("last_error"),
    nextRetryAt: timestamp("next_retry_at"),
    deliveredAt: timestamp("delivered_at"),
    createdAt: timestamp("created_at").notNull().defaultNow(),
    updatedAt: timestamp("updated_at").notNull().defaultNow().onUpdateNow(),
  },
);

export type NotificationDelivery = typeof notificationDeliveries.$inferSelect;
export type NewNotificationDelivery =
  typeof notificationDeliveries.$inferInsert;
