import { PrismaClient } from '@prisma/client';

/**
 * Outbox Pattern 触发器函数 + 性能索引
 *
 * 当业务表发生 INSERT/UPDATE/DELETE 时，触发器将事件写入 t_workflow_event_outbox。
 * Worker 的 outbox-poller 定时扫描未处理事件，匹配并触发对应的 workflow。
 *
 * 表结构由 Prisma 模型 WorkflowEventOutbox 维护（见 config/prisma/workflow.prisma）。
 * 本 seed 负责 Prisma 无法 declarative 维护的两个对象：
 *   1. 通用触发器函数 notify_workflow_event() — Prisma 完全不管 PG function
 *   2. 部分索引 idx_outbox_unprocessed — Prisma schema 不支持 WHERE 子句的 partial index
 *
 * 两者均幂等（CREATE OR REPLACE / IF NOT EXISTS）。
 *
 * 使用示例（在业务表上挂载触发器，由各业务模块自行声明）：
 *   CREATE TRIGGER trg_order_workflow
 *     AFTER INSERT OR UPDATE OR DELETE ON t_order
 *     FOR EACH ROW EXECUTE FUNCTION notify_workflow_event();
 */
export async function seedWorkflowEventTrigger(prisma: PrismaClient) {
  console.log('Seeding workflow event trigger function...');

  await prisma.$executeRawUnsafe(`
    CREATE OR REPLACE FUNCTION notify_workflow_event() RETURNS trigger AS $$
    DECLARE
      event_payload jsonb;
      event_name text;
    BEGIN
      -- 拼接事件名：表名.操作 (e.g. "t_order.insert")
      event_name := TG_TABLE_NAME || '.' || lower(TG_OP);

      -- 构建 payload
      IF (TG_OP = 'DELETE') THEN
        event_payload = row_to_json(OLD)::jsonb;
      ELSE
        event_payload = row_to_json(NEW)::jsonb;
      END IF;

      -- 写入 outbox（与业务操作同一事务，保证不丢）
      INSERT INTO t_workflow_event_outbox (event_name, payload)
      VALUES (event_name, event_payload);

      RETURN COALESCE(NEW, OLD);
    END;
    $$ LANGUAGE plpgsql;
  `);

  console.log('Seeding workflow outbox partial index...');

  // 部分索引：只索引未处理事件，poller 扫描时索引体积保持很小，
  // 即使 outbox 表积累几百万历史事件也不影响 poller 性能。
  await prisma.$executeRawUnsafe(`
    CREATE INDEX IF NOT EXISTS idx_outbox_unprocessed
      ON t_workflow_event_outbox (created_at)
      WHERE processed = FALSE;
  `);

  console.log('Workflow event trigger function & index seeded.');
}
