import { getDb } from '../client'
import { weixinSyncCursors } from '../schema'
import { eq } from 'drizzle-orm'
import { nowExpr } from '../shared/dialect-helpers'

/**
 * Weixin Sync Cursor Repository。
 *
 * 封装 weixin_sync_cursors 表的所有查询。每行保存一个 channel 长轮询游标
 * (get_updates_buf)，用于在进程重启后从正确的位置继续接收消息，不丢失/不
 * 重复处理。
 *
 * 设计约定：
 * - 返回类型由 drizzle 推断，消费方无需 cast
 * - UPDATE 显式刷新 updated_at 用 nowExpr()
 * - 无独立删除——其生命周期跟随 im_channel，由 imChannelRepo.deleteById
 *   事务级联清理
 */

export const weixinSyncCursorRepo = {
  /** 按 channel 查游标（adapter.start 时恢复长轮询位置） */
  findByChannel(channelId: string) {
    return getDb()
      .select({ getUpdatesBuf: weixinSyncCursors.getUpdatesBuf })
      .from(weixinSyncCursors)
      .where(eq(weixinSyncCursors.channelId, channelId))
      .get()
  },

  /**
   * Upsert：首次写入或刷新已有行的 get_updates_buf。
   * 原 SQL 用 `ON CONFLICT(channel_id) DO UPDATE` ——迁移到 drizzle 后由
   * 渠道事务等价实现：先 select 判存在再分支 insert/update，两条 SQL 由
   * db.transaction 保证原子性（与原 INSERT...ON CONFLICT 行为一致）。
   *
   * 原 race-condition 容忍语义：saveSyncCursor 自身 try/catch 失败不抛，
   * 此处保持同一行为——upsert 失败由调用方 try/catch 兜底。
   */
  upsert(channelId: string, buf: string) {
    getDb().transaction((tx) => {
      const existing = tx
        .select({ channelId: weixinSyncCursors.channelId })
        .from(weixinSyncCursors)
        .where(eq(weixinSyncCursors.channelId, channelId))
        .get()
      if (existing) {
        tx.update(weixinSyncCursors)
          .set({ getUpdatesBuf: buf, updatedAt: nowExpr() })
          .where(eq(weixinSyncCursors.channelId, channelId))
          .run()
      } else {
        tx.insert(weixinSyncCursors)
          .values({ channelId, getUpdatesBuf: buf })
          .run()
      }
    })
  },
}
