import { UUidWithPrefix, getAusweisartFromUUID } from "#components/Ausweis/types.js"
import { Enums } from "#lib/client/prisma.js"
import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js"
import { mollieClient } from "#lib/mollie.js"
import { prisma } from "#lib/server/prisma.js"
import { PaymentMethod } from "@mollie/api-client"
import { defineApiRoute, APIError } from "astro-typesafe-api/server"
import { RechnungSchema } from "src/generated/zod/rechnung.js"
import { z } from "zod"

export const PATCH = defineApiRoute({
	input: RechnungSchema.pick({
		bezahlmethode: true,
		ort: true,
		plz: true,
		strasse: true,
		telefon: true,
		empfaenger: true,
		versand_empfaenger: true,
		versand_ort: true,
		versand_plz: true,
		versand_strasse: true,
		versand_zusatzzeile: true,
		abweichende_versand_adresse: true
	}),
	output: z.object({
		checkout_url: z.string().optional(),
		uid: UUidWithPrefix,
	}),
	middleware: authorizationMiddleware,
	headers: authorizationHeaders,
	async fetch(input, context, user) {
		// Wir holen uns die Rechnung
		const rechnung = await prisma.rechnung.findUnique({
			where: {
				uid: context.params.uid,
				benutzer: {
					id: user.id
				}
			},
			include: {
				bedarfsausweis_gewerbe: true,
				bedarfsausweis_wohnen: true,
				geg_nachweis_gewerbe: true,
				geg_nachweis_wohnen: true,
				verbrauchsausweis_gewerbe: true,
				verbrauchsausweis_wohnen: true
			}
		})

		if (!rechnung) {
			throw new APIError({
				code: "NOT_FOUND",
				message: "Rechnung konnte nicht gefunden werden oder gehört einem anderen Benutzer."
			})
		}

		await prisma.rechnung.update({
			where: {
				id: rechnung.id
			},
			data: {
				bezahlmethode: input.bezahlmethode,
				ort: input.ort,
				plz: input.plz,
				strasse: input.strasse,
				telefon: input.telefon,
				empfaenger: input.empfaenger,
				versand_empfaenger: input.versand_empfaenger,
				versand_ort: input.versand_ort,
				versand_plz: input.versand_plz,
				versand_strasse: input.versand_strasse,
				versand_zusatzzeile: input.versand_zusatzzeile,
				abweichende_versand_adresse: input.abweichende_versand_adresse,
			}
		})

		if (input.bezahlmethode === Enums.Bezahlmethoden.rechnung) {
			return { uid: rechnung.uid }
		}

		const ausweis = rechnung.verbrauchsausweis_gewerbe || rechnung.verbrauchsausweis_wohnen || rechnung.bedarfsausweis_gewerbe || rechnung.bedarfsausweis_wohnen || rechnung.geg_nachweis_gewerbe || rechnung.geg_nachweis_wohnen;

		if (!ausweis) {
			throw new APIError({
				code: "NOT_FOUND",
				message: "Rechnung hat keinen verknüpften Ausweis"
			})
		}

		const ausweisart = getAusweisartFromUUID(ausweis.uid)

		if (!ausweisart) {
			throw new APIError({
				code: "INTERNAL_SERVER_ERROR",
				message: "Ausweis ist ungültig."
			})
		}

		const description = getPaymentDescription(ausweisart);

		// Wir erstellen eine Mollie Payment Referenz.
		const payment = await mollieClient.payments.create({
			amount: {
				value: rechnung.betrag.toFixed(2),
				currency: "EUR",
			},
			metadata: {
				rechnung_uid: rechnung.uid,
			},
			method: input.bezahlmethode as PaymentMethod,
			description,
			redirectUrl: `https://ibcornelsen.de/payment/success?a=${ausweis.uid}&r=${rechnung.uid}`,
			webhookUrl: `http://ibcornelsen.de/api/webhooks/mollie?uid=${rechnung.uid}`,
		});

		const checkoutUrl = payment.getCheckoutUrl();

		if (!checkoutUrl) {
			throw new APIError({
				code: "INTERNAL_SERVER_ERROR",
				message: "Checkout URL konnte nicht erstellt werden.",
			});
		}

		return {
			uid: rechnung.uid,
			checkout_url: checkoutUrl,
		};
	},
})

function getPaymentDescription(ausweisart: Enums.Ausweisart) {
	switch(ausweisart) {
		case "BedarfsausweisWohnen":
			return "Bedarfsausweis Wohngebäude"
		case "BedarfsausweisGewerbe":
			return "Bedarfsausweis Gewerbegebäude"
		case "VerbrauchsausweisGewerbe":
			return "Verbrauchsausweis Gewerbegebäude"
		case "VerbrauchsausweisWohnen":
			return "Verbrauchsausweis Wohngebäude"
		case "BedarfsausweisGewerbe":
		case "GEGNachweisGewerbe":
		case "GEGNachweisWohnen":
			return "GEG Nachweis"
		default:
			return ""
	}
}