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

import { getDb, pgAll } from '@/shared/db';
import { enqueueThumbnailJob } from '@/features/iphoto/thumbnail-worker';
import { mediaKindFromMime } from '@/features/iphoto/service';
import type { PhotoMediaKind } from '@/entities/photo';

const backfillQuerySchema = z.object({
  force: z.coerce.boolean().optional(),
  limit: z.coerce.number().int().positive().max(10_000).optional(),
});

/**
 * Admin routes for the iphoto media pipeline.
 *
 * POST /admin/iphoto/processing/backfill[?force=true][&limit=N]
 *   Enqueues thumbnail-processing jobs for photos that have a storage_key but
 *   no thumbnail. With force=true, also re-enqueues completed photos (useful
 *   after a Sharp version change). Returns the count actually enqueued.
 */
export const iphotoAdminRouter = new Hono().post('/processing/backfill', async (c) => {
  const { force, limit } = backfillQuerySchema.parse({
    force: c.req.query('force'),
    limit: c.req.query('limit'),
  });

  const pool = getDb();
  const where = force
    ? `storage_key IS NOT NULL`
    : `storage_key IS NOT NULL AND processing_status IN ('pending', 'failed')`;
  const cap = limit ?? 1_000;

  const rows = await pgAll<{
    id: string;
    device_id: string;
    storage_key: string;
    mime_type: string | null;
    media_type: string;
    media_kind: string | null;
  }>(
    pool,
    `SELECT id, device_id, storage_key, mime_type, media_type, media_kind
       FROM macsync.photos
       WHERE ${where}
       ORDER BY taken_at DESC NULLS LAST
       LIMIT $1`,
    [cap],
  );

  for (const r of rows) {
    const mime = r.mime_type ?? r.media_type;
    const mediaKind: PhotoMediaKind =
      (r.media_kind as PhotoMediaKind | null) ?? mediaKindFromMime(mime);
    await enqueueThumbnailJob({
      photoId: r.id,
      deviceId: r.device_id,
      storageKey: r.storage_key,
      mimeType: mime,
      mediaKind,
    });
  }

  return c.json({ enqueued: rows.length, force: Boolean(force), limit: cap });
});
