import { call, os } from "@orpc/server";
import { z } from "zod";
import { randomUUID } from "crypto";
import { createKV } from "../lib/create-kv.js";
import { assertOwner } from "../lib/auth.js";
// Schema Definition
const GalleryPhotoSchema = z.object({
    id: z.string(),
    base64Data: z.string(),
    title: z.string().optional().default(""),
    order: z.number().int(),
    createdAt: z.string(),
    cover: z.boolean().optional().default(false),
});
// KV Storage
const galleryPhotosKV = createKV("galleryPhotos");
// Authentication centralized in ../lib/auth.ts
// CRUD Endpoints
const uploadPhoto = os
    .input(z.object({
    sessionId: z.string(),
    base64Data: z
        .string()
        .regex(/^data:image\/(png|jpe?g|webp|gif);base64,/i, 'Unsupported image format'),
    title: z.string().optional().default(""),
}))
    .handler(async ({ input }) => {
    try {
        await assertOwner(input.sessionId);
        const id = randomUUID();
        const existing = await galleryPhotosKV.getAllItems();
        const maxOrder = existing.length > 0 ? Math.max(...existing.map((p) => p.order)) : -1;
        const nextOrder = maxOrder + 1;
        const photo = {
            id,
            base64Data: input.base64Data,
            title: input.title ?? "",
            order: nextOrder,
            createdAt: new Date().toISOString(),
            cover: false,
        };
        await galleryPhotosKV.setItem(id, photo);
        return photo;
    }
    catch (err) {
        console.error("gallery.uploadPhoto error", err);
        throw err;
    }
});
const setCoverPhoto = os
    .input(z.object({ sessionId: z.string(), id: z.string() }))
    .handler(async ({ input }) => {
    await assertOwner(input.sessionId);
    const all = await galleryPhotosKV.getAllItems();
    let updatedCover = null;
    for (const p of all) {
        const isCover = p.id === input.id;
        const next = { ...p, cover: isCover };
        await galleryPhotosKV.setItem(p.id, next);
        if (isCover)
            updatedCover = next;
    }
    return updatedCover;
});
const deletePhoto = os
    .input(z.object({ sessionId: z.string(), id: z.string() }))
    .handler(async ({ input }) => {
    await assertOwner(input.sessionId);
    await galleryPhotosKV.removeItem(input.id);
});
const updatePhotoOrder = os
    .input(z.object({
    sessionId: z.string(),
    photoOrders: z.array(z.object({ id: z.string(), order: z.number().int() })),
}))
    .handler(async ({ input }) => {
    await assertOwner(input.sessionId);
    const updated = [];
    for (const { id, order } of input.photoOrders) {
        const existing = await galleryPhotosKV.getItem(id);
        if (!existing)
            continue;
        const updatedPhoto = { ...existing, order };
        await galleryPhotosKV.setItem(id, updatedPhoto);
        updated.push(updatedPhoto);
    }
    const all = await galleryPhotosKV.getAllItems();
    return all.sort((a, b) => (a.order - b.order) || a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
});
const listPhotos = os.handler(async () => {
    const all = await galleryPhotosKV.getAllItems();
    return all.sort((a, b) => (a.order - b.order) || a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
});
const adminListPhotos = os
    .input(z.object({ sessionId: z.string() }))
    .handler(async ({ input }) => {
    await assertOwner(input.sessionId);
    const all = await galleryPhotosKV.getAllItems();
    return all.sort((a, b) => (a.order - b.order) || a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
});
// Live Queries
const live = {
    listPhotos: os.handler(async function* ({ signal }) {
        yield call(listPhotos, {}, { signal });
        for await (const _ of galleryPhotosKV.subscribe()) {
            yield call(listPhotos, {}, { signal });
        }
    }),
    adminListPhotos: os
        .input(z.object({ sessionId: z.string() }))
        .handler(async function* ({ input, signal }) {
        await assertOwner(input.sessionId);
        const all = await galleryPhotosKV.getAllItems();
        const sorted = all.sort((a, b) => (a.order - b.order) || a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
        yield sorted;
        for await (const _ of galleryPhotosKV.subscribe()) {
            const updated = await galleryPhotosKV.getAllItems();
            const sortedUpdated = updated.sort((a, b) => (a.order - b.order) || a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
            yield sortedUpdated;
        }
    }),
};
export const router = {
    uploadPhoto,
    deletePhoto,
    updatePhotoOrder,
    listPhotos,
    adminListPhotos,
    setCoverPhoto,
    live,
};
