import { authorizationMiddleware } from "#lib/middleware/authorization.js";
import { prisma } from "#lib/server/prisma.js";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
import { z } from "zod";
import isBase64 from "is-base64";
import { fileURLToPath } from "url";
import { writeFileSync } from "fs";
import { UUidWithPrefix } from "#components/Ausweis/types.js";
import sharp from "sharp"
import { BildSchema } from "src/generated/zod/bild.js";
import { PERSISTENT_DIR } from "#lib/server/constants.js";

export const PATCH = defineApiRoute({
	input: BildSchema.pick({
		kategorie: true,
	}).merge(z.object({
		data: z.string()
	})),
	output: z.void(),
	middleware: authorizationMiddleware,
	async fetch(input, ctx, user) {
		if (!UUidWithPrefix.safeParse(ctx.params.uid).success) {
			throw new APIError({
				code: "BAD_REQUEST",
				message: "UID konnte nicht verifiziert werden."
			})
		}

		const image = await prisma.bild.findUnique({
			where: {
				uid: ctx.params.uid,
				aufnahme: {
					benutzer_id: user.id
				}
			}
		})

		if (!image) {
			throw new APIError({
				code: "BAD_REQUEST",
				message: "Bild existiert nicht oder gehört einem anderen Benutzer."
			})
		}

		const data = input.data;

		if (!isBase64(data, { mimeRequired: true })) {
			throw new APIError({
				code: "BAD_REQUEST",
				message: "Das Bild ist nicht base64.",
			});
		}

		const dataWithoutPrefix = data.replace(
			/^data:image\/\w+;base64,/,
			""
		);
		const buffer = Buffer.from(dataWithoutPrefix, "base64");

		if (input.kategorie !== image.kategorie) {
			await prisma.bild.update({
				where: {
					id: image.id
				},
				data: {
					kategorie: input.kategorie
				}
			});
		}

		const filePath = fileURLToPath(new URL(`${PERSISTENT_DIR}/images/${image.uid}.jpg`, import.meta.url));

		try {
			// Wir optimieren das Bild und konvertieren es in WebP
			// TODO: Sharp scheint nicht zu funktionieren, wir müssen das nochmal testen
			const optimizedBuffer = await sharp(buffer).jpeg({ quality: 80 }).toBuffer();

			writeFileSync(filePath, optimizedBuffer)
		} catch(e) {
			// Und geben einen Fehler zurück
			throw new APIError({
				code: "INTERNAL_SERVER_ERROR",
				message: "Bild konnte nicht gespeichert werden.",
			});
		}
	},
})