import {
  int,
  json,
  mysqlTable,
  text,
  timestamp,
  varchar,
} from "drizzle-orm/mysql-core";
import type { OutboxRecord, OutboxStatus } from "./types.js";

/**
 * 创建 outbox 表的 Drizzle schema。
 *
 * 表名由调用方通过 OutboxConfig.tableName 提供（每服务独立 outbox 表），
 * 因此以工厂函数形式返回，避免多服务共用同一表名常量。
 *
 * 字段与 OutboxRecord 接口一一对齐：
 * - id：cuid2（varchar(32)），作为 event id 与 Kafka 消息 key
 * - status：通过 $type<OutboxStatus> 收窄为联合类型
 * - metadata：通过 $type<Record<string,string> | null> 收窄
 */
export function createOutboxTable(tableName: string) {
  return mysqlTable(tableName, {
    id: varchar("id", { length: 32 }).notNull().primaryKey(),
    eventType: varchar("event_type", { length: 100 }).notNull(),
    payload: text("payload").notNull(),
    aggregateId: varchar("aggregate_id", { length: 32 }).notNull(),
    status: varchar("status", { length: 20 })
      .notNull()
      .default("pending")
      .$type<OutboxStatus>(),
    retryCount: int("retry_count").notNull().default(0),
    maxRetryCount: int("max_retry_count").notNull().default(5),
    nextRetryAt: timestamp("next_retry_at"),
    createdAt: timestamp("created_at").notNull().defaultNow(),
    publishedAt: timestamp("published_at"),
    lastError: text("last_error"),
    metadata: json("metadata").$type<Record<string, string> | null>(),
  });
}

/** outbox 表类型 */
export type OutboxTable = ReturnType<typeof createOutboxTable>;

/** select 推断行类型（应结构兼容 OutboxRecord） */
export type OutboxRow = OutboxTable["$inferSelect"];

/** insert 推断类型 */
export type NewOutboxRow = OutboxTable["$inferInsert"];

/**
 * 编译期断言：OutboxRow 与 OutboxRecord 结构兼容。
 * 若 schema 与接口偏离，此处会在严格模式下编译失败。
 */
const _assertOutboxRow: OutboxRow extends OutboxRecord ? true : never = true;
void _assertOutboxRow;
