import { getDb } from '../client'
import { imPairingRequests } from '../schema'
import { eq, and, sql } from 'drizzle-orm'
import { nowExpr, addMinutesExpr } from '../shared/dialect-helpers'
import { PairingStatus } from '../shared/enums'

/**
 * IM Pairing Request Repository。
 *
 * 封装 im_pairing_requests 表的所有查询。每行表示一条 DM 配对请求：
 * 用户向 bot 发送首条消息时生成 6 位 code，admin / user 在另一渠道回复
 * code 后由 verifyPairingCode 标记为 approved 并加入 sender_whitelist。
 *
 * 设计约定：
 * - 返回类型由 drizzle 推断，消费方无需 cast
 * - expires_at 用 addMinutesExpr() 在 INSERT 时按当前时间 + 分钟数生成
 *   （与 schema 默认行为一致；这里显式传入以便灵活指定时长）
 * - 无独立删除——其生命周期跟随 im_channel，由 imChannelRepo.deleteById
 *   事务级联清理
 */

export const imPairingRequestRepo = {
  /**
   * 查 sender 是否已经有 approved 配对（DM policy=pairing 准入检查）。
   * 返回 { id } 或 undefined；不存在则返回 undefined。
   */
  findApproved(channelId: string, senderId: string) {
    return getDb()
      .select({ id: imPairingRequests.id })
      .from(imPairingRequests)
      .where(
        and(
          eq(imPairingRequests.channelId, channelId),
          eq(imPairingRequests.senderId, senderId),
          eq(imPairingRequests.status, PairingStatus.APPROVED),
        ),
      )
      .limit(1)
      .get()
  },

  /**
   * 查 pending 且未过期的配对（verifyPairingCode 输入校验）。
   * expires_at > datetime('now') 用 SQL 原生比较，确保未被 10 分钟到期线影响。
   */
  findPendingForCode(channelId: string, senderId: string, code: string) {
    return getDb()
      .select({ id: imPairingRequests.id })
      .from(imPairingRequests)
      .where(
        and(
          eq(imPairingRequests.channelId, channelId),
          eq(imPairingRequests.senderId, senderId),
          eq(imPairingRequests.code, code),
          eq(imPairingRequests.status, PairingStatus.PENDING),
          sql`${imPairingRequests.expiresAt} > datetime('now')`,
        ),
      )
      .get()
  },

  /** 把 sender 的全部 pending 请求标记为 expired（创建新 pairing 时清理旧请求） */
  expirePendingForSender(channelId: string, senderId: string) {
    getDb()
      .update(imPairingRequests)
      .set({ status: PairingStatus.EXPIRED })
      .where(
        and(
          eq(imPairingRequests.channelId, channelId),
          eq(imPairingRequests.senderId, senderId),
          eq(imPairingRequests.status, PairingStatus.PENDING),
        ),
      )
      .run()
  },

  /**
   * 创建 pairing 请求。
   * 默认 expires_at = now + 10 minutes（与 schema DEFAULT 行为一致）。
   * 调用方传入新生成的 id（crypto.randomUUID）。
   */
  create(data: {
    id: string
    channelId: string
    senderId: string
    code: string
    expiresInMinutes?: number
  }) {
    getDb()
      .insert(imPairingRequests)
      .values({
        id: data.id,
        channelId: data.channelId,
        senderId: data.senderId,
        code: data.code,
        status: PairingStatus.PENDING,
        expiresAt: addMinutesExpr(data.expiresInMinutes ?? 10),
      })
      .run()
  },

  /** 标记单个 pairing 请求为 approved（verifyPairingCode 校验通过后调用） */
  approve(id: string) {
    getDb()
      .update(imPairingRequests)
      .set({ status: PairingStatus.APPROVED, verifiedAt: nowExpr() })
      .where(eq(imPairingRequests.id, id))
      .run()
  },
}
