import { z } from "zod";
import moment from "moment";
import { prisma } from "#lib/server/prisma";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";

export const GET = defineApiRoute({
	input: z.object({
		plz: z.string().min(4).max(5),
		startdatum: z.coerce.date(),
		enddatum: z.coerce.date(),
		genauigkeit: z.enum(["months", "years"]),
	}),

	output: z.array(
		z.object({
			month: z.number(),
			year: z.number(),
			klimafaktor: z.number(),
		})
	),

	async fetch(input, ctx) {
		const start = moment(input.startdatum);
		const end = moment(input.enddatum);

		if (start.isSameOrAfter(end)) {
			throw new APIError({
				code: "PRECONDITION_FAILED",
				message: "Das Startdatum kann nicht vor dem Enddatum liegen.",
			});
		}

		const intervals = [];

		let currentDate = start.clone();
		while (currentDate.isSameOrBefore(end)) {
			let copy = currentDate.clone();
			intervals.push(copy);
			currentDate.add(1, input.genauigkeit);
		}

		let klimafaktoren = await prisma.klimafaktoren.findMany({
			where: {
				plz: input.plz,
				month: intervals[0].month(),
				OR: intervals.map((date) => {
					return {
						year: date.year(),
					};
				}),
			},
		});

		if (!klimafaktoren) {
			throw new APIError({
				code: "NOT_FOUND",
				message:
					"Die Klimafaktoren konnten nicht geladen werden. Das kann daran liegen, dass sie für diesen Zeitraum oder Ort nicht verfügbar sind.",
			});
		}

		// NOTE: Sollten wir hier lieber den Output padden und trotzdem die gefundenen zurückgeben?
		if (klimafaktoren.length !== intervals.length) {
			throw new APIError({
				code: "NOT_FOUND",
				message:
					"Für diesen Zeitraum konnten nicht alle Klimafaktoren gefunden werden.",
			});
		}

		return klimafaktoren.map((klimafaktor) => ({
			month: klimafaktor.month,
			year: klimafaktor.year,
			klimafaktor: klimafaktor.klimafaktor,
		}));
	},
});
