import { query } from '../db/client.js'
import type { ShortLinkCreateInput } from '../types/repository/inputs.js'
import type { ShortLinkRow } from '../types/repository/rows.js'

export async function createShortLink(input: ShortLinkCreateInput): Promise<ShortLinkRow | null> {
  const result = await query<ShortLinkRow>(
    `
      INSERT INTO short_links (
        code,
        target_url,
        target_url_hash,
        source,
        task_id,
        expires_at,
        created_at,
        updated_at
      )
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
      ON CONFLICT (source, task_id, target_url_hash) DO UPDATE
      SET
        target_url = EXCLUDED.target_url,
        expires_at = EXCLUDED.expires_at,
        updated_at = EXCLUDED.updated_at
      RETURNING *
    `,
    [
      input.code,
      input.targetUrl,
      input.targetUrlHash,
      input.source || '',
      normalizeNullableId(input.taskId),
      input.expiresAt || null,
      input.createdAt,
      input.updatedAt,
    ],
  )

  return result.rows[0] || null
}

export async function findShortLinkByCode(code: string): Promise<ShortLinkRow | null> {
  const normalizedCode = String(code || '').trim()
  if (!normalizedCode) {
    return null
  }

  const result = await query<ShortLinkRow>(
    `
      SELECT *
      FROM short_links
      WHERE code = $1
      LIMIT 1
    `,
    [normalizedCode],
  )

  return result.rows[0] || null
}

export async function markShortLinkVisited(
  code: string,
  visitedAt: string,
): Promise<ShortLinkRow | null> {
  const normalizedCode = String(code || '').trim()
  if (!normalizedCode) {
    return null
  }

  const result = await query<ShortLinkRow>(
    `
      UPDATE short_links
      SET
        visit_count = visit_count + 1,
        last_visited_at = $2,
        updated_at = $2
      WHERE code = $1
      RETURNING *
    `,
    [normalizedCode, visitedAt],
  )

  return result.rows[0] || null
}

function normalizeNullableId(value: unknown): number | null {
  if (value === null || value === undefined || value === '') {
    return null
  }

  const parsed = Number(value)
  return Number.isFinite(parsed) && parsed > 0 ? parsed : null
}
