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

export const PUT = defineApiRoute({
	input: BildSchema.pick({
		kategorie: true,
	}).merge(z.object({
		data: z.string()
	})),
	output: z.object({
		uid: z.string({ description: "Die UID des Bildes." })
	}),
	async fetch(input) {
		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");

		const bild = await prisma.bild.create({
			data: {
				kategorie: input.kategorie
			},
			select: {
				uid: true,
			},
		});

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

		try {
			// Wir optimieren das Bild und konvertieren es in JPEG
			const optimizedBuffer = await sharp(buffer).jpeg({ quality: 80 }).toBuffer();

			writeFileSync(filePath, optimizedBuffer)
		} catch(e) {
			// Bild wurde nicht gespeichert, wir löschen den Eintrag wieder
			await prisma.bild.delete({
				where: {
					uid: bild.uid
				}
			})
			// Und geben einen Fehler zurück
			throw new APIError({
				code: "INTERNAL_SERVER_ERROR",
				message: "Bild konnte nicht gespeichert werden.",
			});
		}

		return {
			uid: bild.uid
		};
	},
})

export const DELETE = defineApiRoute({
	input: z.object({
		uid: UUidWithPrefix
	}),
	middleware: maybeAuthorizationMiddleware,
	async fetch(input, context, user) {
		try {
			if (user) {
				await prisma.bild.delete({
					where: {
						uid: input.uid,
						aufnahme: {
							benutzer: {
								id: user.id
							}
						}
					}
				})
			} else {
				await prisma.bild.delete({
					where: {
						uid: input.uid,
						aufnahme_id: null
					}
				})
			}
		} catch(e) {
			throw new APIError({
				code: "INTERNAL_SERVER_ERROR",
				message: "Bild konnte nicht gelöscht werden."
			})
		}
	},
})