import { Hono } from 'hono';
import { z } from 'zod';

import {
  listIdentitiesByDevice,
  listPhotoIdsForIdentity,
  mergeIdentities,
  renameIdentity,
} from '@/entities/identity';
import { getDb, pgAll } from '@/shared/db';
import { notFound } from '@/shared/http/errors';

const deviceParam = z.string().uuid();
const identityIdParam = z.string().uuid();
const renameSchema = z.object({ name: z.string().min(1).max(120).nullable() });
const mergeSchema = z.object({ targetId: z.string().uuid(), sourceId: z.string().uuid() });

export const identitiesMyRouter = new Hono()
  .get('/', async (c) => {
    const deviceId = deviceParam.parse(c.req.query('deviceId'));
    const rows = await listIdentitiesByDevice(getDb(), deviceId);
    return c.json(rows);
  })
  .post('/:id/rename', async (c) => {
    const id = identityIdParam.parse(c.req.param('id'));
    const { name } = renameSchema.parse(await c.req.json());
    await renameIdentity(getDb(), id, name);
    return c.json({ ok: true });
  })
  .post('/merge', async (c) => {
    const { targetId, sourceId } = mergeSchema.parse(await c.req.json());
    if (targetId === sourceId) throw new Error('targetId and sourceId must differ');
    await mergeIdentities(getDb(), targetId, sourceId);
    return c.json({ ok: true });
  })
  .get('/:id/photos', async (c) => {
    const id = identityIdParam.parse(c.req.param('id'));
    const limit = z.coerce.number().int().positive().max(500).default(100).parse(c.req.query('limit') ?? '100');
    const photoIds = await listPhotoIdsForIdentity(getDb(), id, limit);
    if (photoIds.length === 0) return c.json([]);
    const rows = await pgAll<{
      id: string;
      thumbnail_key: string | null;
      preview_key: string | null;
      taken_at: string | null;
    }>(
      getDb(),
      `SELECT id, thumbnail_key, preview_key, taken_at FROM macsync.photos WHERE id = ANY($1) ORDER BY taken_at DESC NULLS LAST`,
      [photoIds],
    );
    if (rows.length === 0) throw notFound('identity_photos_missing', `no resolvable photos for identity ${id}`);
    return c.json(rows);
  });
