import { VALID_UUID_PREFIXES } from "#lib/constants.js";
import {
	Aufnahme,
	BedarfsausweisWohnen,
	Benutzer,
	Enums,
	Bild,
	Objekt,
	Rechnung,
	Tickets,
	Unterlage,
	VerbrauchsausweisGewerbe,
	VerbrauchsausweisWohnen,
	GEGNachweisWohnen,
} from "#lib/client/prisma";
import { z, ZodSchema } from "zod";

export type OmitKeys<T, K extends keyof T> = Omit<T, K>;

export type UploadedGebaeudeBild = OmitKeys<Bild, "id" | "aufnahme_id"> & {
	data: string
}

/**
 * Das ist der Typescript Type für den Verbrauchsausweis Wohnen mit allen Feldern die
 * von der API erwartet werden. Das Backend wird dem Client nur diese Daten zur Verfügung stellen.
 * Hiermit kann sichergestellt werden, dass eine Funktion auf dem Client mit den richtigen Daten
 * ausgeführt werden kann.
 * @date 1/14/2024 - 3:33:33 PM
 *
 * @export
 * @typedef {VerbrauchsausweisWohnenClient}
 */
export type VerbrauchsausweisWohnenClient = OmitKeys<
	VerbrauchsausweisWohnen,
	"id" | "aufnahme_id" | "benutzer_id"
> & {
	uid_objekt: string,
	uid_aufnahme: string,
	uid_benutzer?: string
};

/**
 * Das ist der Typescript Type für den Verbrauchsausweis Gewerbe mit allen Feldern die
 * von der API erwartet werden. Das Backend wird dem Client nur diese Daten zur Verfügung stellen.
 * Hiermit kann sichergestellt werden, dass eine Funktion auf dem Client mit den richtigen Daten
 * ausgeführt werden kann.
 * @date 1/14/2024 - 3:33:33 PM
 *
 * @export
 * @typedef {VerbrauchsausweisWohnenClient}
 */
export type VerbrauchsausweisGewerbeClient = OmitKeys<
	VerbrauchsausweisGewerbe,
	"id" | "aufnahme_id" | "benutzer_id"
> & {
	uid_objekt: string,
	uid_aufnahme: string,
	uid_benutzer?: string
};

/**
 * Das ist der Typescript Type für den Verbrauchsausweis Gewerbe mit allen Feldern die
 * von der API erwartet werden. Das Backend wird dem Client nur diese Daten zur Verfügung stellen.
 * Hiermit kann sichergestellt werden, dass eine Funktion auf dem Client mit den richtigen Daten
 * ausgeführt werden kann.
 * @date 1/14/2024 - 3:33:33 PM
 *
 * @export
 * @typedef {VerbrauchsausweisWohnenClient}
 */
export type BedarfsausweisWohnenClient = OmitKeys<
	BedarfsausweisWohnen,
	"id" | "aufnahme_id" | "benutzer_id"
> & {
	uid_objekt: string,
	uid_aufnahme: string,
	uid_benutzer?: string
};

/**
 * Das ist der Typescript Type für die Gebäude Stammdaten mit allen Feldern die
 * von der API erwartet werden. Das Backend wird dem Client nur diese Daten zur Verfügung stellen.
 * Hiermit kann sichergestellt werden, dass eine Funktion auf dem Client mit den richtigen Daten
 * ausgeführt werden kann.
 * @date 1/14/2024 - 3:33:33 PM
 *
 * @export
 * @typedef {ObjektClient}
 */
export type ObjektClient = OmitKeys<Objekt, "benutzer_id" | "id">;

export type AufnahmeClient = OmitKeys<
	Aufnahme,
	"id" | "objekt_id" | "benutzer_id"
> & {
	uid_objekt: string
};

export type TicketClient = OmitKeys<Tickets, "bearbeiter_id" | "benutzer_id" | "id">

export type BenutzerClient = OmitKeys<Benutzer, "id" | "passwort">;

export type RechnungClient = OmitKeys<Rechnung, "aufnahme_id" | "benutzer_id" | "id">

export function ZodOverlap<T, S = z.ZodType<T, z.ZodTypeDef, T>>(arg: S): S {
	return arg;
}

type PickNullable<T> = {
	[P in keyof T as null extends T[P] ? P : never]: T[P]
}

type PickNotNullable<T> = {
	[P in keyof T as null extends T[P] ? never : P]: T[P]
}

export type OptionalNullable<T> = T extends object ? {
	[K in keyof PickNullable<T>]?: OptionalNullable<T[K]>
} & {
	[K in keyof PickNotNullable<T>]: OptionalNullable<T[K]>
} : T;

export const UUidWithPrefix = z.string().refine((value) => {
	const prefixedUUidRegex = /^([0-9a-z]+)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i

	const match = value.match(prefixedUUidRegex)

	if (match && match[1] in VALID_UUID_PREFIXES) {
		return true;
	}

	return false;
})

export function getAusweisartFromUUID(uid: string): Enums.Ausweisart | null {
	if (!UUidWithPrefix.safeParse(uid).success) {
		return null
	}

	if (uid.startsWith("vaw")) {
		return Enums.Ausweisart.VerbrauchsausweisWohnen
	} else if (uid.startsWith("vag")) {
		return Enums.Ausweisart.VerbrauchsausweisGewerbe
	} else if (uid.startsWith("baw")) {
		return Enums.Ausweisart.BedarfsausweisWohnen
	} else if (uid.startsWith("bag")) {
		return Enums.Ausweisart.BedarfsausweisGewerbe
	} else if (uid.startsWith("gnw")) {
		return Enums.Ausweisart.GEGNachweisWohnen
	} else if (uid.startsWith("gng")) {
		return Enums.Ausweisart.GEGNachweisGewerbe
	}

	return null;
} 

export type UnterlageClient = Omit<Unterlage, "id" | "aufnahme_id">
export type BildClient = Omit<Bild, "id" | "aufnahme_id">

export type ObjektKomplettClient = ObjektClient & {
	aufnahmen: AufnahmeKomplettClient[]
}

export type AufnahmeKomplettClient = AufnahmeClient & {
	bilder: BildClient[],
	unterlagen: UnterlageClient[],
	bedarfsausweise_wohnen: BedarfsausweisWohnenClient[],
	verbrauchsausweise_wohnen: VerbrauchsausweisWohnenClient[],
	verbrauchsausweise_gewerbe: VerbrauchsausweisGewerbeClient[],
	geg_nachweise_wohnen: GEGNachweisWohnenClient[]
}

export type GEGNachweisWohnenClient = Omit<GEGNachweisWohnen, "id" | "aufnahme_id" | "benutzer_id"> & {
	uid_objekt: string,
	uid_aufnahme: string,
	uid_benutzer?: string
}