import { AufnahmeClient, BenutzerClient, BildClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient } from "#components/Ausweis/types.js";
import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016 } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016.js";
import { getEmpfehlungen } from "#lib/XML/getEmpfehlungen.js";
import { Enums } from "#lib/server/prisma.js";
import * as fs from "fs"
import moment from "moment";
import { PDFDocument, PDFFont, PDFImage, PDFPage, StandardFonts } from "pdf-lib";
import { addCheckMark } from "./utils/checkbox.js";
import { addText } from "./utils/text.js";
import { addAnsichtsausweisLabel, addDatumGEG } from "./utils/helpers.js";
import { PERSISTENT_DIR } from "#lib/server/constants.js";
import { fileURLToPath } from "url";


export async function pdfVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewerbeClient, aufnahme: AufnahmeClient, objekt: ObjektClient, bilder: BildClient[], user: BenutzerClient) {
	const VerbrauchsausweisWohnenGEG2024PDF = fs.readFileSync(new URL("../../../public/pdf/templates/GEG24_Nichtwohngebaeude.pdf", import.meta.url), "base64");
	const pdf = await PDFDocument.load(VerbrauchsausweisWohnenGEG2024PDF)
	const pages = pdf.getPages()
	
	// const template = VerbrauchsausweisWohnen2016Template as Template;

	const berechnungen = await endEnergieVerbrauchVerbrauchsausweisGewerbe_2016(ausweis, aufnahme, objekt);
	
	const empfehlungen = getEmpfehlungen(ausweis, aufnahme, objekt)

	const height = pages[0].getHeight()

	const font = await pdf.embedFont(StandardFonts.Helvetica)
	const bold = await pdf.embedFont(StandardFonts.HelveticaBold)

	const form = pdf.getForm()
	form.updateFieldAppearances(font)

	pages[0].drawText(aufnahme.gebaeudetyp || "", {
		x: 211,
		y: height - 166,
		size: 10
	})

	pages[0].drawText(objekt.adresse || "", {
		x: 211,
		y: height - 194,
		size: 10
	})

	pages[0].drawText(aufnahme.gebaeudeteil || "", {
		x: 211,
		y: height - 214.5,
		size: 10
	})

	pages[0].drawText(aufnahme.baujahr_gebaeude?.toString() || "", {
		x: 211,
		y: height - 229.5,
		size: 10
	})

	pages[0].drawText(aufnahme.baujahr_heizung?.toString() || "", {
		x: 211,
		y: height - 250,
		size: 10
	})

	pages[0].drawText(aufnahme.nutzflaeche?.toString() || "", {
		x: 211,
		y: height - 271.5,
		size: 10
	})

	pages[0].drawText(`${aufnahme.brennstoff_1}, ${aufnahme.brennstoff_2 || ""}`, {
		x: 211,
		y: height - 285,
		size: 10
	})

	const erneuerbareEnergienVerwendung = []

	if (ausweis.alternative_heizung) {
		erneuerbareEnergienVerwendung.push("Heizung")
	}

	if (ausweis.alternative_kuehlung) {
		erneuerbareEnergienVerwendung.push("Kühlung")
	}

	if (ausweis.alternative_lueftung) {
		erneuerbareEnergienVerwendung.push("Lüftung")
	}

	if (ausweis.alternative_warmwasser) {
		erneuerbareEnergienVerwendung.push("Warmwasser")
	}

	pages[0].drawText(erneuerbareEnergienVerwendung.join(", "), {
		x: 358,
		y: height - 325,
		size: 8
	})

	if (ausweis.warmwasser_enthalten) {
		pages[0].drawText(`${aufnahme.brennstoff_1}, ${aufnahme.brennstoff_2 || ""}`, {
			x: 211,
			y: height - 299,
			size: 10
		})
	}


	if (aufnahme.lueftung === Enums.Lueftungskonzept.Fensterlueftung) {
		addCheckMark(pages[0], 213, height - 334)
	} else if (aufnahme.lueftung === Enums.Lueftungskonzept.Schachtlueftung) {
		addCheckMark(pages[0], 213, height - 345)
	} else if (aufnahme.lueftung === Enums.Lueftungskonzept.LueftungsanlageMitWaermerueckgewinnung) {
		addCheckMark(pages[0], 355, height - 334)
	} else if (aufnahme.lueftung === Enums.Lueftungskonzept.LueftungsanlageOhneWaermerueckgewinnung) {
		addCheckMark(pages[0], 355, height - 345)
	}

	// Kühlung
	if (aufnahme.kuehlung) {
		addCheckMark(pages[0], 213, height - 362.5)
	} else {
		addCheckMark(pages[0], 355, height - 373.5)
	}

	if (ausweis.ausstellgrund === Enums.Ausstellgrund.Neubau) {
		addCheckMark(pages[0], 213, height - 406)
	} else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Vermietung) {
		addCheckMark(pages[0], 213, height - 417)
	} else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Modernisierung) {
		addCheckMark(pages[0], 344.5, height - 406)
	} else if (ausweis.ausstellgrund === Enums.Ausstellgrund.Sonstiges) {
		addCheckMark(pages[0], 463, height - 417)
	}
	// Aushangpflicht
	// addCheckMark(pages[0], 463, height - 406)
	




	const bild = bilder && bilder.find(image => image.kategorie === Enums.BilderKategorie.Gebaeude);
	
		if (bild) {
			const path = `${PERSISTENT_DIR}/images/${bild.uid}.jpg`;
	
			if (fs.existsSync(path)) {
				const file = fs.readFileSync(fileURLToPath(new URL(path, import.meta.url)))
				let image: PDFImage;
				image = await pdf.embedJpg(file)
				pages[0].drawImage(image, {
					x: 460.5,
					y: height - 289,
					width: 111,
					height: 138
				})
			}
		}
	
		// Checkmark Angabe energetische Qualität des Gebäudes.
		addCheckMark(pages[0], 40, height - 550)
	
		// Datenerhebung durch Eigentümer
		addCheckMark(pages[0], 295, height - 580)
	
		// Ausstellungsdatum
		pages[0].drawText(moment().format("DD.MM.YYYY"), {
			font, 
			size: 10,
			x: 508,
			y: height - 752
		})
	
		// Gültig bis
		pages[0].drawText(moment().add(10, "years").format("DD.MM.YYYY"), {
			font: bold, 
			size: 10,
			x: 90,
			y: height - 113
		})
	
		// Stempel und Unterschrift
		if (ausweis.ausgestellt) {
			const stempel = await pdf.embedPng(fs.readFileSync(new URL("../../../public/pdf/images/stempel-unterschrift.png", import.meta.url), "base64"));
			const stempelHeight = 60
		
			pages[0].drawImage(stempel, {
				x: 450,
				y: height - 750,
				height: stempelHeight,
				width: stempel.width / (stempel.height / stempelHeight)
			})
		}
	
		
		// Aussteller
		const aussteller = await pdf.embedPng(fs.readFileSync(new URL("../../../public/pdf/images/aussteller.png", import.meta.url), "base64"));
		pages[0].drawImage(aussteller, {
			x: 40,
			y: height - 750,
			width: 100,
			height: 50
		})
	

	// /* -------------------------------- Seite 2 -------------------------------- */

	// const co2Emissionen = fillFormField("co2emissionen", berechnungen?.co2EmissionenGesamt.toString(), 8, TextAlignment.Center)

	const addEnergieverbrauchSkalaPfeile = async (page: PDFPage) => {
		const pfeilNachUnten = await pdf.embedPng(fs.readFileSync(new URL("../../../public/images/pfeil-nach-unten.png", import.meta.url), "base64"))

		// Wir müssen den berechneten Wert zwischen 0 und 1000 als Wert zwischen 0 und 1 festlegen
		const endenergieverbrauchTranslationPercentage = Math.min(1000, Math.max(0, berechnungen?.endEnergieVerbrauchGesamt || 0)) / 1000
		const stromVerbrauchTranslationPercentage = Math.min(1000, Math.max(0, berechnungen?.endEnergieVerbrauchStrom || 0)) / 1000

		const minTranslation = 78
		const maxTranslation = 512
		const endenergieverbrauchTranslationX = minTranslation + (maxTranslation - minTranslation) * endenergieverbrauchTranslationPercentage;
		const stromVerbrauchTranslationX = minTranslation + (maxTranslation - minTranslation) * stromVerbrauchTranslationPercentage;

		const pfeilWidth = 20
		const margin = 5;

		page.drawImage(pfeilNachUnten, {
			x: endenergieverbrauchTranslationX,
			y: height - 210,
			width: pfeilWidth,
			height: 30
		})

		const endEnergieVerbrauchGesamtText = `${berechnungen?.endEnergieVerbrauchGesamt.toString()}kWh/(m²a)`;
		const stromVerbrauchGesamtText = `${berechnungen?.endEnergieVerbrauchStrom.toString()}kWh/(m²a)`;

		if (endenergieverbrauchTranslationPercentage > 0.5) {
			page.drawText("Endenergieverbrauch Wärme", {
				x: endenergieverbrauchTranslationX - margin - font.widthOfTextAtSize("Endenergieverbrauch", 10),
				y: height - 191,
				size: 10
			})

			page.drawText(endEnergieVerbrauchGesamtText, {
				x: endenergieverbrauchTranslationX - margin - bold.widthOfTextAtSize(endEnergieVerbrauchGesamtText, 10),
				y: height - 205,
				size: 10,
				font: bold
			})
		} else {
			page.drawText("Endenergieverbrauch Wärme", {
				x: endenergieverbrauchTranslationX + pfeilWidth + margin,
				y: height - 191,
				size: 10
			})
			page.drawText(endEnergieVerbrauchGesamtText, {
				x: endenergieverbrauchTranslationX + pfeilWidth + margin,
				y: height - 205,
				size: 10,
				font: bold
			})
		}

		page.drawImage(pfeilNachUnten, {
			x: stromVerbrauchTranslationX,
			y: height - 354,
			width: pfeilWidth,
			height: 30
		})

		if (endenergieverbrauchTranslationPercentage > 0.5) {
			page.drawText("Endenergieverbrauch Strom", {
				x: stromVerbrauchTranslationX - margin - font.widthOfTextAtSize("Primärenergieverbrauch", 10),
				y: height - 335,
				size: 10
			})

			page.drawText(stromVerbrauchGesamtText, {
				x: stromVerbrauchTranslationX - margin - bold.widthOfTextAtSize(stromVerbrauchGesamtText, 10),
				y: height - 349,
				size: 10,
				font: bold
			})
		} else {
			page.drawText("Endenergieverbrauch Strom", {
				x: stromVerbrauchTranslationX + pfeilWidth + margin,
				y: height - 335,
				size: 10
			})
			page.drawText(stromVerbrauchGesamtText, {
				x: stromVerbrauchTranslationX + pfeilWidth + margin,
				y: height - 349,
				size: 10,
				font: bold
			})
		}
	}

	addEnergieverbrauchSkalaPfeile(pages[2])

	if (ausweis.warmwasser_enthalten) {
		addCheckMark(pages[2], 41, height - 269)
	}

	if (ausweis.kuehlung_enthalten) {
		addCheckMark(pages[2], 41, height - 281)
	}

	if (ausweis.stromverbrauch_enthaelt_heizung) {
		addCheckMark(pages[2], 41, height - 456)
	}	

	if (ausweis.stromverbrauch_enthaelt_warmwasser) {
		addCheckMark(pages[2], 131, height - 456)
	}

	if (ausweis.stromverbrauch_enthaelt_lueftung) {
		addCheckMark(pages[2], 218, height - 456)
	}

	if (ausweis.stromverbrauch_enthaelt_beleuchtung) {
		addCheckMark(pages[2], 281, height - 456)
	}

	if (ausweis.stromverbrauch_enthaelt_kuehlung) {
		addCheckMark(pages[2], 422, height - 456)
	}

	if (ausweis.stromverbrauch_enthaelt_sonstige) {
		addCheckMark(pages[2], 492, height - 456)
	}

	addText(pages[2], berechnungen?.primaerEnergieVerbrauchGesamt.toString() || "", 475, height - 637, 10, font)
	addText(pages[2], berechnungen?.co2EmissionenGesamt.toString() || "", 475, height - 656, 10, font)

	// const primaerenergiebedarfIst = fillFormField("primaerenergiebedarf_ist", berechnungen?.primaerEnergieVerbrauchGesamt.toString())
	

	/* -------------------------------- Seite 3 -------------------------------- */

	// Verbräuche

	const addVerbrauchGenerator = () => {
		let i = 0;
		let yOffset = 14.6;
		const initialHeight = 297
		const initialXOffset = 36;
		return (zeitraum_von?: string, zeitraum_bis?: string, energietraeger?: string, primaerfaktor?: string, energieverbrauch?: string, anteil_warmwasser?: string, anteil_kaelte?: number, anteil_heizung?: string, klimafaktor?: string, strom?: number) => {
			pages[2].drawText(zeitraum_von || "", {
				x: initialXOffset,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(zeitraum_bis || "", {
				x: initialXOffset + 47,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(energietraeger || "", {
				x: initialXOffset + 94,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(primaerfaktor || "", {
				x: initialXOffset + 232,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(energieverbrauch || "", {
				x: initialXOffset + 275,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(anteil_warmwasser || "", {
				x: initialXOffset + 325,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(anteil_kaelte?.toString() || "", {
				x: initialXOffset + 378,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(anteil_heizung || "", {
				x: initialXOffset + 430,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(klimafaktor || "", {
				x: initialXOffset + 464,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[2].drawText(strom?.toString() || "", {
				x: initialXOffset + 504,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})
			i++;
		}
	}

	const addVerbrauch = addVerbrauchGenerator();

	if (!ausweis.warmwasser_enthalten) {
		// Mit Warmwasserzuschlag
		addVerbrauch(
			moment(ausweis.startdatum).format("MM.YYYY"),
			moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"),
			aufnahme.brennstoff_1 || "",
			berechnungen?.brennstoff_1.primaerenergiefaktor.toString(),
			Math.round(berechnungen?.energieVerbrauchGesamt_1 || 0).toString(),
			"0",
			berechnungen?.endEnergieVerbrauchKuehlungsZuschlag_1,
			Math.round(berechnungen?.energieVerbrauchHeizung_1 || 0).toString(),
			berechnungen?.durchschnittsKlimafaktor.toString(),
			berechnungen?.energieVerbrauchStrom
		);
	} else {
		// Ohne Warmwasserzuschlag
		addVerbrauch(
			moment(ausweis.startdatum).format("MM.YYYY"),
			moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"),
			aufnahme.brennstoff_1 || "",
			berechnungen?.brennstoff_1.primaerenergiefaktor.toString(),
			Math.round(berechnungen?.energieVerbrauchGesamt_1 || 0).toString(),
			Math.round(berechnungen?.energieVerbrauchWarmwasser_1 || 0).toString(),
			berechnungen?.endEnergieVerbrauchKuehlungsZuschlag_1,
			Math.round(berechnungen?.energieVerbrauchHeizung_1 || 0).toString(),
			berechnungen?.durchschnittsKlimafaktor.toString(),
			berechnungen?.energieVerbrauchStrom
		);
	}

	if (ausweis.zusaetzliche_heizquelle) {
		addVerbrauch(
			moment(ausweis.startdatum).format("MM.YYYY"),
			moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"),
			aufnahme.brennstoff_2 || "",
			berechnungen?.brennstoff_2.primaerenergiefaktor.toString(),
			Math.round(berechnungen?.energieVerbrauchGesamt_2 || 0).toString(),
			Math.round(berechnungen?.energieVerbrauchWarmwasser_2 || 0).toString(),
			berechnungen?.endEnergieVerbrauchKuehlungsZuschlag_2,
			Math.round(berechnungen?.energieVerbrauchHeizung_2 || 0).toString(),
			berechnungen?.durchschnittsKlimafaktor.toString(),
			0
		);
	}


	// TODO
	if (!ausweis.warmwasser_enthalten) {
			/**
			 * Dezentrale Warmwasserversorgung - Pauschale Erhöhung um 20kWh/m²
			 * @link https://www.bundesanzeiger.de/pub/publication/MRYM4nI84Sdlr0EIvvW?2
			 */
			addVerbrauch(
				moment(ausweis.startdatum).format("MM.YYYY"),
				moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"),
				"Warmwasserzuschlag",
				berechnungen?.brennstoff_1.primaerenergiefaktor.toString(),
				Math.round(berechnungen?.energieVerbrauchWarmwasser_1 || 0).toString(),
				Math.round(berechnungen?.energieVerbrauchWarmwasser_1 || 0).toString(),
				0,
				"0"
			);
		}
	
		if (aufnahme.leerstand && aufnahme.leerstand > 0) {
			/**
			 * Leerstandszuschlag
			 * @link https://www.bundesanzeiger.de/pub/publication/MRYM4nI84Sdlr0EIvvW?2
			 */
			if (ausweis.warmwasser_enthalten && ausweis.warmwasser_anteil_bekannt) {
				addVerbrauch(
					moment(ausweis.startdatum).format("MM.YYYY"),
					moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"),
					"Leerstandszuschlag",
					berechnungen?.brennstoff_1.primaerenergiefaktor.toString(),
					Math.round((berechnungen?.leerstandsZuschlagHeizung || 0) + (berechnungen?.leerstandsZuschlagWarmwasser || 0)).toString(),
					Math.round((berechnungen?.leerstandsZuschlagWarmwasser || 0)).toString(),
					Math.round((berechnungen?.leerstandsZuschlagHeizung || 0)),
					berechnungen?.durchschnittsKlimafaktor.toString()
				);
			} else {
				addVerbrauch(
					moment(ausweis.startdatum).format("MM.YYYY"),
					moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"),
					"Leerstandszuschlag",
					berechnungen?.brennstoff_1.primaerenergiefaktor.toString(),
					Math.round((berechnungen?.leerstandsZuschlagHeizung || 0) + (berechnungen?.leerstandsZuschlagWarmwasser || 0)).toString(),
					"0",
					0,
					berechnungen?.durchschnittsKlimafaktor.toString()
				);
			}
		}
	
	if (aufnahme.kuehlung) {
		/**
		 * Kühlungszuschlag - Pauschale Erhöhung um 6kWh/m²
		 * Primärenergiefaktor Strom
		 * @link https://www.bundesanzeiger.de/pub/publication/MRYM4nI84Sdlr0EIvvW?2
		 */
		addVerbrauch(
			moment(ausweis.startdatum).format("MM.YYYY"),
			moment(ausweis.startdatum).add(3, "years").format("MM.YYYY"),
			"Kühlungszuschlag",
			"",
			// TODO
			// berechnungen?.primaerfaktorww.toString(),
			Math.round(berechnungen?.kuehlungsZuschlag_1 || 0).toString(),
			"0",
			0,
			""
		);
	}

	/* -------------------------------- Seite 4 -------------------------------- */

	const splitToSize = (text: string, size: number, font: PDFFont, fontSize: number) => {
		const lines = []

		let currentLine = ""
		for (const char of text) {
			if (font.widthOfTextAtSize(currentLine + char, fontSize) <= size) {
				currentLine += char;
			} else {
				lines.push(currentLine)
				currentLine = char;
			}
		}

		lines.push(currentLine)

		return lines.join("\n")
	}

	const addEmpfehlungenGenerator = () => {
		let i = 0;
		let yOffset = 43;
		const initialHeight = 562
		const initialXOffset = 36;
		return (bauteil?: string, beschreibung?: string, alsEinzelmassnahme?: boolean, amortisationszeit?: string, kosten?: string) => {
			pages[3].drawText((i + 1).toString(), {
				x: initialXOffset,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[3].drawText(splitToSize(bauteil || "", 70, font, 8), {
				x: initialXOffset + 25,
				y: initialHeight - (i * yOffset),
				size: 8,
				font,
				lineHeight: 10
			})

			pages[3].drawText(splitToSize(beschreibung || "", 230, font, 8), {
				x: initialXOffset + 98,
				y: initialHeight - (i * yOffset),
				size: 8,
				font,
				lineHeight: 10
			})

			

			pages[3].drawText(amortisationszeit || "", {
				x: initialXOffset + 403,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})

			pages[3].drawText(kosten || "", {
				x: initialXOffset + 451,
				y: initialHeight - (i * yOffset),
				size: 8,
				font
			})
			i++;
		}
	}

	const addEmpfehlung = addEmpfehlungenGenerator()

	for (const empfehlung of empfehlungen) {
		addEmpfehlung(empfehlung.anlagenteil, empfehlung.description, true, empfehlung.amortisationszeit, empfehlung.kosten)
	}
	

	for (const page of pages) {
		addAnsichtsausweisLabel(page, font)
		addDatumGEG(page, font)
	}
	

	
	// pdf.getForm().flatten()

	return pdf.save();
}