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

type ClaimTokenRow = {
  [column: string]: unknown
  id: number
  task_id: number
  token: string
  status: string
  expired_at: string | null
  used_at: string | null
  max_use_count: number
  used_count: number
  created_at: string
  updated_at: string
}

type ClaimTokenCreateInput = {
  taskId: number
  token: string
  status: string
  expiredAt: string | null
  usedAt?: string | null
  maxUseCount: number
  usedCount: number
  createdAt: string
  updatedAt: string
}

type ClaimTokenPatch = Partial<
  Pick<
    ClaimTokenRow,
    'status' | 'expired_at' | 'used_at' | 'max_use_count' | 'used_count' | 'updated_at'
  >
>

export async function createClaimToken(
  input: ClaimTokenCreateInput,
): Promise<ClaimTokenRow | null> {
  const result = await query<ClaimTokenRow>(
    `
      INSERT INTO claim_tokens (
        task_id,
        token,
        status,
        expired_at,
        used_at,
        max_use_count,
        used_count,
        created_at,
        updated_at
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
      ON CONFLICT (task_id) DO UPDATE
      SET
        token = EXCLUDED.token,
        status = EXCLUDED.status,
        expired_at = EXCLUDED.expired_at,
        used_at = EXCLUDED.used_at,
        max_use_count = EXCLUDED.max_use_count,
        used_count = EXCLUDED.used_count,
        created_at = EXCLUDED.created_at,
        updated_at = EXCLUDED.updated_at
      RETURNING *
    `,
    [
      input.taskId,
      input.token,
      input.status,
      input.expiredAt,
      input.usedAt || null,
      input.maxUseCount,
      input.usedCount,
      input.createdAt,
      input.updatedAt,
    ],
  )

  return result.rows[0] || null
}

export async function getClaimTokenById(tokenId: number | string): Promise<ClaimTokenRow | null> {
  const result = await query<ClaimTokenRow>('SELECT * FROM claim_tokens WHERE id = $1 LIMIT 1', [
    Number(tokenId),
  ])
  return result.rows[0] || null
}

export async function findClaimTokenByToken(token: string): Promise<ClaimTokenRow | null> {
  const result = await query<ClaimTokenRow>('SELECT * FROM claim_tokens WHERE token = $1 LIMIT 1', [
    String(token || '').trim(),
  ])
  return result.rows[0] || null
}

export async function updateClaimToken(
  tokenId: number | string,
  patch: ClaimTokenPatch,
): Promise<ClaimTokenRow | null> {
  const current = await getClaimTokenById(tokenId)
  if (!current) {
    return null
  }

  const next = { ...current, ...patch }
  const result = await query<ClaimTokenRow>(
    `
      UPDATE claim_tokens
      SET
        status = $1,
        expired_at = $2,
        used_at = $3,
        max_use_count = $4,
        used_count = $5,
        updated_at = $6
      WHERE id = $7
      RETURNING *
    `,
    [
      next.status,
      next.expired_at,
      next.used_at,
      next.max_use_count,
      next.used_count,
      next.updated_at,
      Number(tokenId),
    ],
  )

  return result.rows[0] || null
}
