import { AufnahmeClient, ObjektClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
import { getKlimafaktoren } from "#lib/Klimafaktoren.js";
import { getHeizwertfaktor } from "#lib/server/Heizwertfaktor.js";
import { Enums } from "#lib/client/prisma";
import moment from "moment";

export function energetischeNutzflaecheVerbrauchsausweisWohnen_2016(
	ausweis: VerbrauchsausweisWohnenClient,
	aufnahme: AufnahmeClient
): number {
	let faktorKeller = 1.2;
	// Falls das Gebäude einen Keller besitzt der Beheizt ist erhöhen wir die Nutzfläche um 15%
	if (aufnahme.keller == Enums.Heizungsstatus.BEHEIZT && (aufnahme.einheiten || 1) <= 2) {
		faktorKeller = 1.35;
	}

	if ((aufnahme.nutzflaeche || 0) > (aufnahme.flaeche || 0)) {
		return aufnahme.nutzflaeche || 0;
	} else {
		return (aufnahme.flaeche || 0) * faktorKeller;	
	}
}

export async function endEnergieVerbrauchVerbrauchsausweis_2016(
	ausweis: VerbrauchsausweisWohnenClient,
	aufnahme: AufnahmeClient,
	objekt: ObjektClient
) {
	if (!aufnahme || !objekt || !ausweis) {
		return null;
	}

	let startdatum = moment(ausweis.startdatum);

	let klimafaktoren: Awaited<ReturnType<typeof getKlimafaktoren>> = [{
		month: startdatum.month(),
		year: startdatum.year(),
		klimafaktor: 1
	},
	{
		month: startdatum.month(),
		year: startdatum.year() + 1,
		klimafaktor: 1
	},
	{
		month: startdatum.month(),
		year: startdatum.year() + 2,
		klimafaktor: 1
	}];

	try {
		const response = await getKlimafaktoren(ausweis.startdatum, objekt.plz)
		
		if (response) {
			klimafaktoren = response
		}
	} catch (e) {
		// TODO: Entweder setzen wir hier mit falschen Klimafaktoren fort, oder wir geben null zurück.
		// Im Moment setzen wir einfach fort, aber das ist nicht unbedingt die beste Lösung.
		// return null
	}
	

	// Endenergieverbrauch
	// Um den EEV auszurechnen, müssen die Verbräuche zu kWh konvertiert werden.
	let brennstoff_1 = getHeizwertfaktor(
		aufnahme.brennstoff_1 as string,
		ausweis.einheit_1 as string
	);
	let brennstoff_2 = getHeizwertfaktor(
		aufnahme.brennstoff_2 as string,
		ausweis.einheit_2 as string
	);

	const energetischeNutzflaeche =
		energetischeNutzflaecheVerbrauchsausweisWohnen_2016(ausweis, aufnahme);

	let energieVerbrauchGesamt_1 =
		((ausweis.verbrauch_1 || 0) +
			(ausweis.verbrauch_2 || 0) +
			(ausweis.verbrauch_3 || 0)) *
		brennstoff_1.umrechnungsfaktor;
	let energieVerbrauchGesamt_2 =
		((ausweis.verbrauch_4 || 0) +
			(ausweis.verbrauch_5 || 0) +
			(ausweis.verbrauch_6 || 0)) *
		brennstoff_2.umrechnungsfaktor;

	let energieVerbrauchWarmwasser_1 = 0;
	let energieVerbrauchWarmwasser_2 = 0;
	let leerstandsZuschlagWarmwasser = 0;
	// Leerstand wird in Prozent angegeben, muss hier aber in eine Zahl zwischen 0 und 1 umgerechnet werden.
	let leerstand = (aufnahme.leerstand || 0) / 100;

	if (ausweis.warmwasser_enthalten && ausweis.warmwasser_anteil_bekannt) {
		if (aufnahme.solarsystem_warmwasser) {
			// Wenn Warmwasser enthalten und Anteil bekannt und Solarsystem
			energieVerbrauchWarmwasser_1 =
				energieVerbrauchGesamt_1 *
				((ausweis.anteil_warmwasser_1 || 0) / 100) *
				0.6;
			energieVerbrauchWarmwasser_2 =
				energieVerbrauchGesamt_2 *
				((ausweis.anteil_warmwasser_2 || 0) / 100) *
				0.6;
		} else {
			// Wenn Warmwasser enthalten und Anteil bekannt und **kein** Solarsystem
			energieVerbrauchWarmwasser_1 =
				energieVerbrauchGesamt_1 *
				((ausweis.anteil_warmwasser_1 || 0) / 100);
			energieVerbrauchWarmwasser_2 =
				energieVerbrauchGesamt_2 *
				((ausweis.anteil_warmwasser_2 || 0) / 100);
		}
		leerstandsZuschlagWarmwasser =
			leerstand *
			(energieVerbrauchWarmwasser_1 + energieVerbrauchWarmwasser_2);
	} else {
		if (aufnahme.solarsystem_warmwasser) {
			// Wenn Warmwasser Anteil unbekannt und Solarsystem
			energieVerbrauchWarmwasser_1 = energetischeNutzflaeche * 12 * 3;
			energieVerbrauchWarmwasser_2 = 0;
		} else {
			// Wenn Warmwasser Anteil unbekannt und **kein** Solarsystem
			energieVerbrauchWarmwasser_1 = energetischeNutzflaeche * 20 * 3;
			energieVerbrauchWarmwasser_2 = 0;
		}
	}

	let energieVerbrauchHeizung_1 = energieVerbrauchGesamt_1;
	let energieVerbrauchHeizung_2 = energieVerbrauchGesamt_2;

	// TODO: Im aktuellen Skript vom Live System kommt hier etwas anderes raus,
	// vielleicht ist da etwas kaputt? Da scheint es so, als wäre
	// warmwasser_enthalten immer true...
	// NOTE: Das hier müsste die richtige Version sein...
	if (ausweis.warmwasser_enthalten) {
		energieVerbrauchHeizung_1 -= energieVerbrauchWarmwasser_1;
		energieVerbrauchHeizung_2 -= energieVerbrauchWarmwasser_2;
	}

	let durchschnittsKlimafaktor =
		(klimafaktoren[0].klimafaktor + klimafaktoren[1].klimafaktor + klimafaktoren[2].klimafaktor) / 3 || 1;

	let energieVerbrauchHeizungBereinigt_1 =
		energieVerbrauchHeizung_1 * durchschnittsKlimafaktor;
	let energieVerbrauchHeizungBereinigt_2 =
		energieVerbrauchHeizung_2 * durchschnittsKlimafaktor;

	let kuehlungsZuschlag = 0;
	if (aufnahme.kuehlung) {
		kuehlungsZuschlag = 6 * 3 * energetischeNutzflaeche;
	}

	let durchschnittsEnergieVerbrauchHeizungBereingt =
		(energieVerbrauchHeizungBereinigt_1 +
			energieVerbrauchHeizungBereinigt_2) /
		(3 * energetischeNutzflaeche);

	let faktorDurchschnittsEnergieVerbrauchHeizungBereinigt =
		-0.0028 * durchschnittsEnergieVerbrauchHeizungBereingt + 0.9147;

	if (faktorDurchschnittsEnergieVerbrauchHeizungBereinigt <= 0.25) {
		faktorDurchschnittsEnergieVerbrauchHeizungBereinigt = 0.25;
	} else if (faktorDurchschnittsEnergieVerbrauchHeizungBereinigt >= 1.0) {
		faktorDurchschnittsEnergieVerbrauchHeizungBereinigt = 1.0;
	}

	let leerstandsZuschlagHeizung =
		faktorDurchschnittsEnergieVerbrauchHeizungBereinigt *
		leerstand *
		(energieVerbrauchHeizungBereinigt_1 +
			energieVerbrauchHeizungBereinigt_2);

	let endEnergieVerbrauch_1 =
		(energieVerbrauchHeizungBereinigt_1 + energieVerbrauchWarmwasser_1) /
		(3 * energetischeNutzflaeche);
	let endEnergieVerbrauch_2 =
		(energieVerbrauchHeizungBereinigt_2 + energieVerbrauchWarmwasser_2) /
		(3 * energetischeNutzflaeche);

	let endEnergieVerbrauchLeerstandsZuschlag =
		(leerstandsZuschlagHeizung + leerstandsZuschlagWarmwasser) /
		(3 * energetischeNutzflaeche);
	let endEnergieVerbrauchKuehlungsZuschlag =
		kuehlungsZuschlag / (3 * energetischeNutzflaeche);

	let primaerfaktorww = 0;
	let primaerfaktorww_1 = 0;

	if (!ausweis.warmwasser_enthalten && aufnahme.durchlauf_erhitzer) {
		primaerfaktorww = 1.8;
		primaerfaktorww_1 = 1.8;
	} else {
		primaerfaktorww = brennstoff_1.primaerenergiefaktor;
		primaerfaktorww_1 = brennstoff_2.primaerenergiefaktor;
	}

	let primaerEnergieVerbrauch_1 =
		(energieVerbrauchHeizungBereinigt_1 *
			brennstoff_1.primaerenergiefaktor +
			energieVerbrauchWarmwasser_1 * primaerfaktorww) /
		(3 * energetischeNutzflaeche);
	let primaerEnergieVerbrauch_2 =
		(energieVerbrauchHeizungBereinigt_2 *
			brennstoff_2.primaerenergiefaktor +
			energieVerbrauchWarmwasser_2 * primaerfaktorww_1) /
		(3 * energetischeNutzflaeche);

	let primaerEnergieVerbrauchLeerstandsZuschlag =
		endEnergieVerbrauchLeerstandsZuschlag *
		brennstoff_1.primaerenergiefaktor;
	let primaerEnergieVerbrauchKuehlungsZuschlag =
		endEnergieVerbrauchKuehlungsZuschlag * 1.8;

	let co2Emissionen_1 = endEnergieVerbrauch_1 * brennstoff_1.coe;
	let co2Emissionen_2 = endEnergieVerbrauch_2 * brennstoff_2.coe;

	let co2EmissionenLeerstandsZuschlag =
		endEnergieVerbrauchLeerstandsZuschlag * brennstoff_1.coe;
	let co2EmissionenKuehlungsZuschlag =
		endEnergieVerbrauchKuehlungsZuschlag * brennstoff_2.coe;

	let endEnergieVerbrauchGesamt =
		endEnergieVerbrauch_1 +
		endEnergieVerbrauch_2 +
		endEnergieVerbrauchLeerstandsZuschlag +
		endEnergieVerbrauchKuehlungsZuschlag;
	let primaerEnergieVerbrauchGesamt =
		primaerEnergieVerbrauch_1 +
		primaerEnergieVerbrauch_2 +
		primaerEnergieVerbrauchLeerstandsZuschlag +
		primaerEnergieVerbrauchKuehlungsZuschlag;
	let co2EmissionenGesamt =
		co2Emissionen_1 +
		co2Emissionen_2 +
		co2EmissionenLeerstandsZuschlag +
		co2EmissionenKuehlungsZuschlag;

		// Energieeffizienzklasse
		let energieEffizienzKlasse = "";
		if (endEnergieVerbrauchGesamt < 30) {
			energieEffizienzKlasse = 'A+';
		}else if (endEnergieVerbrauchGesamt < 50) {
			energieEffizienzKlasse = 'A';
		}else if (endEnergieVerbrauchGesamt < 75) {
			energieEffizienzKlasse = 'B';
		}else if (endEnergieVerbrauchGesamt < 100) {
			energieEffizienzKlasse = 'C';
		}else if (endEnergieVerbrauchGesamt < 130) {
			energieEffizienzKlasse = 'D';
		}else if (endEnergieVerbrauchGesamt < 160) {
			energieEffizienzKlasse = 'E';
		}else if (endEnergieVerbrauchGesamt < 200) {
			energieEffizienzKlasse = 'F';
		}else if (endEnergieVerbrauchGesamt < 250) {
			energieEffizienzKlasse = 'G';
		}else if (endEnergieVerbrauchGesamt >= 250) {
			energieEffizienzKlasse = 'H';
		}


	return {
		brennstoff_1: brennstoff_1,
		brennstoff_2: brennstoff_2,
		klimafaktoren: klimafaktoren,
		kuehlungsZuschlag: Math.round(kuehlungsZuschlag),
		durchschnittsKlimafaktor: Math.round(durchschnittsKlimafaktor),
		ausweis: ausweis,

		anteil_heizung_1: 1 - (ausweis.anteil_warmwasser_1 || 0) / 100,
		anteil_heizung_2: 1 - (ausweis.anteil_warmwasser_2 || 0) / 100,

		verbrauch_1_kwh: Math.round(
			(ausweis.verbrauch_1 || 0) * brennstoff_1.umrechnungsfaktor
		),
		verbrauch_2_kwh: Math.round(
			(ausweis.verbrauch_2 || 0) * brennstoff_1.umrechnungsfaktor
		),
		verbrauch_3_kwh: Math.round(
			(ausweis.verbrauch_3 || 0) * brennstoff_1.umrechnungsfaktor
		),
		verbrauch_4_kwh: Math.round(
			(ausweis.verbrauch_4 || 0) * brennstoff_2.umrechnungsfaktor
		),
		verbrauch_5_kwh: Math.round(
			(ausweis.verbrauch_5 || 0) * brennstoff_2.umrechnungsfaktor
		),
		verbrauch_6_kwh: Math.round(
			(ausweis.verbrauch_6 || 0) * brennstoff_2.umrechnungsfaktor
		),

		energetischeNutzflaeche: energetischeNutzflaeche,
		leerstand: leerstand,
		leerstandsZuschlagHeizung: Math.round(leerstandsZuschlagHeizung),
		leerstandsZuschlagWarmwasser: Math.round(leerstandsZuschlagWarmwasser),
		endEnergieVerbrauchLeerstandsZuschlag: Math.round(
			endEnergieVerbrauchLeerstandsZuschlag
		),
		endEnergieVerbrauchKuehlungsZuschlag: Math.round(
			endEnergieVerbrauchKuehlungsZuschlag
		),
		coeeffkg: co2EmissionenGesamt,
		energieVerbrauchGesamt_1: Math.round(energieVerbrauchGesamt_1),
		energieVerbrauchGesamt_2: Math.round(energieVerbrauchGesamt_2),
		energieVerbrauchWarmwasser_1: Math.round(energieVerbrauchWarmwasser_1),
		energieVerbrauchWarmwasser_2: Math.round(energieVerbrauchWarmwasser_2),
		energieVerbrauchHeizung_1: energieVerbrauchHeizung_1,
		energieVerbrauchHeizung_2: energieVerbrauchHeizung_2,
		anteil_warmwasser_1: (ausweis.anteil_warmwasser_1 || 0) / 100,
		anteil_warmwasser_2: (ausweis.anteil_warmwasser_2 || 0) / 100,

		energieVerbrauchHeizungBereinigt_1: Math.round(
			energieVerbrauchHeizungBereinigt_1
		),
		energieVerbrauchHeizungBereinigt_2: Math.round(
			energieVerbrauchHeizungBereinigt_2
		),
		durchschnittsEnergieVerbrauchHeizungBereingt: Math.round(
			durchschnittsEnergieVerbrauchHeizungBereingt
		),
		faktorDurchschnittsEnergieVerbrauchHeizungBereinigt: Math.round(
			faktorDurchschnittsEnergieVerbrauchHeizungBereinigt
		),

		endEnergieVerbrauch_1: Math.round(endEnergieVerbrauch_1),
		endEnergieVerbrauch_2: Math.round(endEnergieVerbrauch_2),

		primaerEnergieVerbrauch_1: Math.round(primaerEnergieVerbrauch_1),
		primaerEnergieVerbrauch_2: Math.round(primaerEnergieVerbrauch_2),

		primaerEnergieVerbrauchLeerstandsZuschlag: Math.round(
			primaerEnergieVerbrauchLeerstandsZuschlag
		),
		primaerEnergieVerbrauchKuehlungsZuschlag: Math.round(
			primaerEnergieVerbrauchKuehlungsZuschlag
		),

		primaerfaktorww,
		primaerfaktorww_1,

		co2Emissionen_1: co2Emissionen_1,
		co2Emissionen_2: co2Emissionen_2,

		co2EmissionenLeerstandsZuschlag: co2EmissionenLeerstandsZuschlag,
		co2EmissionenKuehlungsZuschlag: co2EmissionenKuehlungsZuschlag,

		co2EmissionenGesamt: Math.round(co2EmissionenGesamt),

		endEnergieVerbrauchGesamt: Math.round(endEnergieVerbrauchGesamt),
		primaerEnergieVerbrauchGesamt: Math.round(
			primaerEnergieVerbrauchGesamt
		),
		energieEffizienzKlasse
	};
}
