import { query } from '../../db/client.js'

export type WorkerSmsCodeRow = {
  id: number
  phone: string
  purpose: string
  code_hash: string
  expires_at: string
  consumed_at: string | null
  failed_attempt_count: number
  created_at: string
}

export async function createWorkerSmsCode(input: {
  phone: string
  purpose: string
  codeHash: string
  expiresAt: string
  now: string
}): Promise<WorkerSmsCodeRow | null> {
  const result = await query<WorkerSmsCodeRow>(
    `
      INSERT INTO worker_sms_codes (phone, purpose, code_hash, expires_at, consumed_at, created_at)
      VALUES ($1, $2, $3, $4, NULL, $5)
      RETURNING *
    `,
    [input.phone, input.purpose, input.codeHash, input.expiresAt, input.now],
  )
  return result.rows[0] || null
}

export async function getLatestWorkerSmsCode(
  phone: string,
  purpose: string,
): Promise<WorkerSmsCodeRow | null> {
  const result = await query<WorkerSmsCodeRow>(
    `
      SELECT *
      FROM worker_sms_codes
      WHERE phone = $1 AND purpose = $2
      ORDER BY id DESC
      LIMIT 1
    `,
    [phone, purpose],
  )
  return result.rows[0] || null
}

export async function consumeWorkerSmsCode(
  codeId: number,
  now: string,
): Promise<WorkerSmsCodeRow | null> {
  const result = await query<WorkerSmsCodeRow>(
    `
      UPDATE worker_sms_codes
      SET consumed_at = $1
      WHERE id = $2 AND consumed_at IS NULL
      RETURNING *
    `,
    [now, codeId],
  )
  return result.rows[0] || null
}

/** 记录错误验证码尝试，达到上限后立即锁定该验证码。 */
export async function recordWorkerSmsCodeFailure(
  codeId: number,
  now: string,
  maxAttempts: number,
): Promise<WorkerSmsCodeRow | null> {
  const result = await query<WorkerSmsCodeRow>(
    `
      UPDATE worker_sms_codes
      SET
        failed_attempt_count = COALESCE(failed_attempt_count, 0) + 1,
        consumed_at = CASE
          WHEN COALESCE(failed_attempt_count, 0) + 1 >= $3 THEN $2
          ELSE consumed_at
        END
      WHERE id = $1 AND consumed_at IS NULL
      RETURNING *
    `,
    [codeId, now, Math.max(1, Math.floor(maxAttempts))],
  )
  return result.rows[0] || null
}

export async function countWorkerSmsCodesOnDay(
  phone: string,
  dayStartIso: string,
  dayEndIso: string,
): Promise<number> {
  const result = await query<{ total: number }>(
    `
      SELECT COUNT(*)::int AS total
      FROM worker_sms_codes
      WHERE phone = $1
        AND created_at >= $2
        AND created_at < $3
    `,
    [phone, dayStartIso, dayEndIso],
  )
  return Number(result.rows[0]?.total || 0)
}
