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.js";
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,  "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
	}

	switch(uid.split("-")[0]) {
		case "vaw":
			return Enums.Ausweisart.VerbrauchsausweisWohnen
		case "vag":
			return Enums.Ausweisart.VerbrauchsausweisGewerbe
		case "baw":
			return Enums.Ausweisart.BedarfsausweisWohnen
		case "bag":
			return Enums.Ausweisart.BedarfsausweisGewerbe
		case "gnw":
			return Enums.Ausweisart.GEGNachweisWohnen
		case "gng":
			return Enums.Ausweisart.GEGNachweisGewerbe
		default:
			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 & { rechnung: RechnungClient })[],
	verbrauchsausweise_wohnen: (VerbrauchsausweisWohnenClient & { rechnung: RechnungClient })[],
	verbrauchsausweise_gewerbe: (VerbrauchsausweisGewerbeClient & { rechnung: RechnungClient })[],
	geg_nachweise_wohnen: (GEGNachweisWohnenClient & { rechnung: RechnungClient })[]
}

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