import type { Pool } from 'pg';
import { pgGet, pgAll, pgRun } from '@/shared/db';
import { notFound } from '@/shared/http/errors';

import type { Album, AlbumDraft } from './types';

interface Row {
  id: string;
  device_id: string;
  external_id: string;
  name: string;
  photo_count: number;
  synced_at: string;
}

const hydrate = (r: Row): Album => ({
  id: r.id,
  deviceId: r.device_id,
  externalId: r.external_id,
  name: r.name,
  photoCount: r.photo_count,
  syncedAt: r.synced_at,
});

export async function upsertAlbum(pool: Pool, draft: AlbumDraft): Promise<Album> {
  await pgAll(
    pool,
    `INSERT INTO macsync.albums (id, device_id, external_id, name)
     VALUES ($1, $2, $3, $4)
     ON CONFLICT(device_id, external_id) DO UPDATE SET
       name = excluded.name,
       synced_at = now()`,
    [draft.id, draft.deviceId, draft.externalId, draft.name],
  );
  return getAlbum(pool, draft.id);
}

export async function getAlbum(pool: Pool, id: string): Promise<Album> {
  const row = await pgGet<Row>(pool, 'SELECT * FROM macsync.albums WHERE id = $1', [id]);
  if (!row) throw notFound('album_not_found', `album ${id} not found`);
  return hydrate(row);
}

export async function listAlbumsByDevice(pool: Pool, deviceId: string): Promise<readonly Album[]> {
  const rows = await pgAll<Row>(pool, 'SELECT * FROM macsync.albums WHERE device_id = $1 ORDER BY name ASC', [deviceId]);
  return rows.map(hydrate);
}

export async function incrementAlbumPhotoCount(pool: Pool, id: string): Promise<void> {
  await pgRun(pool, 'UPDATE macsync.albums SET photo_count = photo_count + 1 WHERE id = $1', [id]);
}
