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

import { queryAlbums, queryPhotos } from '@/features/iphoto';
import { readBlob } from '@/features/iphoto/storage';
import { getDb, pgGet } from '@/shared/db';
import { notFound } from '@/shared/http/errors';

const limitParam = z.coerce.number().int().positive().max(500).default(100);
const sinceParam = z.string().optional();
const deviceIdParam = z.string().optional();
const albumIdParam = z.string().min(1);
const sizeParam = z.enum(['original', 'thumbnail', 'preview']).default('original');

export const photosMyRouter = new Hono()
  .get('/', async (c) => {
    const limit = limitParam.parse(c.req.query('limit') ?? '100');
    const since = sinceParam.parse(c.req.query('since'));
    const deviceId = deviceIdParam.parse(c.req.query('deviceId'));
    return c.json(await queryPhotos({ limit, since, deviceId }));
  })
  .get('/albums', async (c) => {
    const deviceId = z.string().min(1).parse(c.req.query('deviceId'));
    return c.json(await queryAlbums(deviceId));
  })
  .get('/albums/:albumId', async (c) => {
    const albumId = albumIdParam.parse(c.req.param('albumId'));
    const limit = limitParam.parse(c.req.query('limit') ?? '100');
    return c.json(await queryPhotos({ albumId, limit }));
  })
  .get('/:id/blob', async (c) => {
    const id = z.string().uuid().parse(c.req.param('id'));
    const size = sizeParam.parse(c.req.query('size') ?? 'original');

    const row = await pgGet<{
      storage_key: string | null;
      thumbnail_key: string | null;
      preview_key: string | null;
      mime_type: string | null;
      media_type: string;
    }>(
      getDb(),
      `SELECT storage_key, thumbnail_key, preview_key, mime_type, media_type
         FROM macsync.photos WHERE id = $1`,
      [id],
    );
    if (!row) throw notFound('photo_not_found', `photo ${id} not found`);

    const key = size === 'thumbnail' ? row.thumbnail_key : size === 'preview' ? row.preview_key : row.storage_key;
    if (!key) throw notFound(`${size}_not_available`, `${size} not generated for photo ${id}`);

    const contentType = size === 'original' ? (row.mime_type ?? row.media_type) : 'image/webp';
    const buf = await readBlob(key);
    return c.body(new Uint8Array(buf), 200, {
      'Content-Type': contentType,
      'Content-Length': String(buf.byteLength),
      'Cache-Control': size === 'original' ? 'private, max-age=60' : 'private, max-age=86400, immutable',
    });
  });
