/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";
import React, { useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { BellRing, BookmarkPlus } from "lucide-react";
import { KEYWORD_CATEGORY, Mission, missionType, Prisma } from "@repo/db";
import {
	JsonValueType,
	MissionOptionalDefaults,
	MissionOptionalDefaultsSchema,
} from "@repo/db/zod";
import { usePannelStore } from "_store/pannelStore";
import { useSession } from "next-auth/react";
import { toast } from "react-hot-toast";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
	createMissionAPI,
	editMissionAPI,
	sendMissionAPI,
	startHpgValidation,
} from "_querys/missions";
import { getKeywordsAPI } from "_querys/keywords";
import { useMapStore } from "_store/mapStore";
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
import { HPGValidationRequired } from "_helpers/hpgValidationRequired";
import { selectRandomHPGMissionSzenery } from "_helpers/selectRandomHPGMission";
import { AxiosError } from "axios";
import { cn } from "@repo/shared-components";
import { StationsSelect } from "(app)/dispatch/_components/StationSelect";
import { getUserAPI } from "_querys/user";

export const MissionForm = () => {
	const session = useSession();

	const { editingMissionId, setEditingMission } = usePannelStore();
	const queryClient = useQueryClient();
	const { setSearchElements, searchElements, setContextMenu } = useMapStore((s) => s);

	const { data: keywords } = useQuery({
		queryKey: ["keywords"],
		queryFn: () => getKeywordsAPI(),
	});

	const { data: aircrafts } = useQuery({
		queryKey: ["aircrafts"],
		queryFn: () => getConnectedAircraftsAPI(),
		refetchInterval: 10000,
	});
	const { data: user } = useQuery({
		queryKey: ["user", session.data?.user.id],
		queryFn: () => getUserAPI(session.data!.user.id),
	});

	const createMissionMutation = useMutation({
		mutationFn: createMissionAPI,
		mutationKey: ["missions"],
		onSuccess: () => {
			queryClient.invalidateQueries({
				queryKey: ["missions"],
			});
		},
	});

	const editMissionMutation = useMutation({
		mutationFn: ({ id, mission }: { id: number; mission: Partial<Prisma.MissionUpdateInput> }) =>
			editMissionAPI(id, mission),
		mutationKey: ["missions"],
		onSuccess: () => {
			queryClient.invalidateQueries({
				queryKey: ["missions"],
			});
		},
	});

	const sendAlertMutation = useMutation({
		mutationKey: ["missions"],
		mutationFn: (id: number) => sendMissionAPI(id, {}),
		onError: (error) => {
			console.error(error);
			toast.error("Fehler beim Alarmieren");
		},
		onSuccess: (data) => {
			toast.success(data.message);
			queryClient.invalidateQueries({
				queryKey: ["missions"],
			});
		},
	});

	const defaultFormValues = React.useMemo(
		() =>
			({
				createdUserId: session.data?.user.id,
				type: "primär",
				addressLat: 0,
				addressLng: 0,
				addressStreet: null,
				addressCity: null,
				addressZip: null,
				addressAdditionalInfo: "",
				addressMissionDestination: "",
				addressOSMways: [],
				missionKeywordAbbreviation: null as any,
				missionKeywordCategory: null as any,
				missionKeywordName: null as any,
				missionAdditionalInfo: "",
				missionPatientInfo: "",
				missionStationIds: [],
				hpgAmbulanceState: "NOT_REQUESTED",
				hpgFireEngineState: "NOT_REQUESTED",
				hpgPoliceState: "NOT_REQUESTED",
				hpgMissionString: null,
				hpgSelectedMissionString: null,
				hpg: null,
				missionLog: [],
				xPlaneObjects: [],
			}) as MissionOptionalDefaults,
		[session.data?.user.id],
	);

	const form = useForm({
		resolver: zodResolver(MissionOptionalDefaultsSchema),
		defaultValues: defaultFormValues,
	});
	const { missionFormValues, setOpen, setMissionFormValues } = usePannelStore((state) => state);

	const validationRequired =
		HPGValidationRequired(
			form.watch("missionStationIds"),
			aircrafts,
			form.watch("hpgMissionString"),
		) &&
		!form.watch("hpgMissionString")?.startsWith("kein Szenario") &&
		user?.settingsUseHPGAsDispatcher;

	useEffect(() => {
		if (session.data?.user.id) {
			form.setValue("createdUserId", session.data.user.id);
		}
	}, [session.data?.user.id, form]);

	useEffect(() => {
		form.setValue(
			"addressOSMways",
			searchElements.filter((e) => e.isSelected) as unknown as JsonValueType[],
		);
	}, [searchElements, form, missionFormValues]);

	useEffect(() => {
		if (missionFormValues) {
			if (Object.keys(missionFormValues).length === 0) {
				form.reset();
				return;
			}
			for (const key in missionFormValues) {
				console.debug(key, missionFormValues[key as keyof MissionOptionalDefaults]);
				if (key === "addressOSMways") continue; // Skip addressOSMways as it is handled separately
				form.setValue(
					key as keyof MissionOptionalDefaults,
					missionFormValues[key as keyof MissionOptionalDefaults],
				);
			}
		}
	}, [missionFormValues, form, defaultFormValues]);

	// Sync form state to store (avoid infinity loops by using watch)
	useEffect(() => {
		const subscription = form.watch((values) => {
			// Only update store if values actually changed to prevent loops
			const currentStoreValues = JSON.stringify(missionFormValues);
			const newFormValues = JSON.stringify(values);

			if (currentStoreValues !== newFormValues) {
				console.debug("Updating store missionFormValues", values);
				setMissionFormValues(values as MissionOptionalDefaults);
			}
		});

		return () => subscription.unsubscribe();
	}, [form, setMissionFormValues, missionFormValues]);

	const saveMission = async (
		mission: MissionOptionalDefaults,
		{ alertWhenValid = false, createNewMission = false } = {},
	) => {
		const [hpgSzenario, hpgSzenarioCode] = mission.hpgMissionString?.split(":") || [];
		const szenarioCode = selectRandomHPGMissionSzenery(hpgSzenarioCode || "");
		let newMission: Mission;
		if (createNewMission) {
			newMission = await createMissionMutation.mutateAsync({
				...(mission as unknown as Prisma.MissionCreateInput),
				hpgSelectedMissionString: szenarioCode,
			});
		} else {
			newMission = await editMissionMutation.mutateAsync({
				id: Number(editingMissionId),
				mission: {
					...(mission as unknown as Prisma.MissionCreateInput),
					state: undefined, // state should not be updated
					missionAdditionalInfo:
						!mission.missionAdditionalInfo.length && hpgSzenario
							? `HPG-Szenario: ${hpgSzenario}`
							: mission.missionAdditionalInfo,
					hpgSelectedMissionString: szenarioCode,
				},
			});
		}

		if (validationRequired) {
			await startHpgValidation(newMission.id, {
				alertWhenValid,
			}).catch((error) => {
				toast.error(`Fehler beim Starten der HPG-Validierung: ${error.message}`);
			});
		} else if (alertWhenValid) {
			await sendAlertMutation.mutateAsync(newMission.id);
		}
		return newMission;
	};
	return (
		<form className="space-y-4">
			{/* Koorinaten Section */}
			<div className="form-control">
				<h2 className="mb-2 text-lg font-bold">Koordinaten</h2>
				<div className="grid grid-cols-2 gap-4">
					<input
						type="text"
						{...form.register("addressLat")}
						className="input input-sm input-neutral input-bordered w-full"
						disabled
					/>
					<input
						type="text"
						{...form.register("addressLng")}
						className="input input-sm input-neutral input-bordered w-full"
						disabled
					/>
				</div>
				{(form.formState.errors.addressLat || form.formState.errors.addressLng) && (
					<p className="text-error">
						Bitte wähle eine Postion übder das Context-Menu über der Karte aus.
					</p>
				)}
			</div>

			{/* Adresse Section */}
			<div className="form-control">
				<h2 className="mb-2 text-lg font-bold">Adresse</h2>
				<input
					type="text"
					{...form.register("addressStreet")}
					placeholder="Straße"
					className="input input-primary input-bordered mb-4 w-full"
				/>
				<div className="grid grid-cols-2 gap-4">
					<input
						type="text"
						{...form.register("addressCity")}
						placeholder="Stadt"
						className="input input-primary input-bordered w-full"
					/>
					<input
						type="text"
						{...form.register("addressZip")}
						placeholder="PLZ"
						className="input input-primary input-bordered w-full"
					/>
				</div>
				<input
					type="text"
					{...form.register("addressAdditionalInfo")}
					placeholder="Zusätzliche Adressinformationen"
					className="input input-primary input-bordered mt-4 w-full"
				/>
			</div>
			{/* Rettungsmittel Section */}
			<div className="form-control">
				<h2 className="mb-2 text-lg font-bold">Rettungsmittel</h2>
				<StationsSelect
					isMulti
					selectedStations={form.watch("missionStationIds")}
					onChange={(v) => {
						form.setValue("missionStationIds", v.selectedStationIds);
						form.setValue("hpgAmbulanceState", v.hpgAmbulanceState);
						form.setValue("hpgFireEngineState", v.hpgFireEngineState);
						form.setValue("hpgPoliceState", v.hpgPoliceState);
					}}
					vehicleStates={{
						hpgAmbulanceState: form.watch("hpgAmbulanceState"),
						hpgFireEngineState: form.watch("hpgFireEngineState"),
						hpgPoliceState: form.watch("hpgPoliceState"),
					}}
				/>
			</div>

			{/* Einsatzdaten Section */}
			<div className="form-control">
				<h2 className="mb-2 text-lg font-bold">Einsatzdaten</h2>
				<select
					{...form.register("type")}
					className="select select-primary select-bordered mb-4 w-full"
					onChange={(e) => {
						form.setValue("type", e.target.value as missionType);
						if (e.target.value === "primary") {
							form.setValue("missionKeywordName", null as any);
							form.setValue("missionKeywordAbbreviation", null as any);
							form.setValue("hpgMissionString", null);
						} else {
							form.setValue("missionKeywordCategory", KEYWORD_CATEGORY.V_VERLEGUNG);
							form.setValue("missionKeywordAbbreviation", null as any);
							form.setValue("hpgMissionString", null);
						}
					}}
				>
					<option value="primär">PRIMÄR</option>
					<option value="sekundär">SEKUNDÄR</option>
				</select>

				{form.watch("type") === "primär" && (
					<>
						<select
							{...form.register("missionKeywordCategory")}
							className="select select-primary select-bordered mb-4 w-full"
							onChange={(e) => {
								form.setValue("missionKeywordCategory", e.target.value as string);
								form.setValue("missionKeywordName", null as any);
								form.setValue("missionKeywordAbbreviation", null as any);
								form.setValue("hpgMissionString", "");
							}}
							value={form.watch("missionKeywordCategory") || "please_select"}
						>
							<option disabled value="please_select">
								Einsatz Kategorie auswählen...
							</option>
							{Object.keys(KEYWORD_CATEGORY)
								.filter((k) => !k.startsWith("V_"))
								.map((use) => (
									<option key={use} value={use}>
										{use}
									</option>
								))}
						</select>
						{form.formState.errors.missionKeywordCategory && (
							<p className="text-error mb-4 text-sm">Bitte wähle eine Kategorie aus.</p>
						)}
					</>
				)}
				<select
					{...form.register("missionKeywordAbbreviation")}
					className="select select-primary select-bordered mb-4 w-full"
					onChange={(e) => {
						const keyword = keywords?.find((k) => k.abreviation === e.target.value);
						form.setValue("missionKeywordName", keyword?.name || (null as any));
						form.setValue("missionKeywordAbbreviation", keyword?.abreviation || (null as any));
						form.setValue("hpgMissionString", null);
					}}
					value={form.watch("missionKeywordAbbreviation") || "please_select"}
				>
					<option disabled value={"please_select"}>
						Einsatzstichwort auswählen...
					</option>
					{keywords &&
						keywords
							.filter((k) => k.category === form.watch("missionKeywordCategory"))
							.map((keyword) => (
								<option key={keyword.id} value={keyword.abreviation}>
									{keyword.name}
								</option>
							))}
				</select>
				{form.formState.errors.missionKeywordAbbreviation && (
					<p className="text-error mb-4 text-sm">Bitte wähle ein Stichwort aus.</p>
				)}
				<div className="mb-4">
					<select
						{...form.register("hpgMissionString")}
						onChange={(e) => {
							form.setValue("hpgMissionString", e.target.value);
							const [name] = e.target.value.split(":");
							const allHpgMissionTypes = keywords?.map((k) => k.hpgMissionTypes).flat();
							const missionAdditionalInfo = form.watch("missionAdditionalInfo");
							if (
								!missionAdditionalInfo ||
								allHpgMissionTypes?.find((t) => {
									const [hpgName] = t.split(":");
									return hpgName === missionAdditionalInfo;
								})
							) {
								form.setValue("missionAdditionalInfo", name || "");
							}
						}}
						className="select select-primary select-bordered mb-2 w-full"
						value={form.watch("hpgMissionString") || "please_select"}
					>
						<option disabled value="please_select">
							Einsatz Szenario auswählen...
						</option>
						<option value={"kein Szenario:3_1_1_1-4_1"}>Kein Szenario</option>
						{keywords &&
							keywords
								.find((k) => k.name === form.watch("missionKeywordName"))
								?.hpgMissionTypes?.map((missionString) => {
									const [name] = missionString.split(":");
									return (
										<option key={missionString} value={missionString}>
											{name}
										</option>
									);
								})}
					</select>
					{validationRequired && (
						<p className="text-warning text-sm">Szenario wird vor Alarmierung HPG-Validiert.</p>
					)}
				</div>

				<textarea
					{...form.register("missionAdditionalInfo")}
					placeholder="Einsatzinformationen"
					className="textarea textarea-primary textarea-bordered mb-4 w-full"
				/>
				{form.watch("type") === "sekundär" && (
					<input
						{...form.register("addressMissionDestination")}
						type="text"
						placeholder="Zielkrankenhaus"
						className="input input-primary input-bordered w-full"
					/>
				)}
			</div>
			<div className="form-control">
				<h2 className="mb-2 text-lg font-bold">Patienteninformationen</h2>
				<textarea
					{...form.register("missionPatientInfo")}
					placeholder="Patienteninformationen"
					className="textarea textarea-primary textarea-bordered w-full"
				/>
			</div>

			<p
				className={cn("text-sm text-gray-500", form.watch("addressOSMways").length && "text-info")}
			>
				In diesem Einsatz gibt es {form.watch("addressOSMways").length} Gebäude
			</p>

			<div className="flex items-center justify-between">
				<p
					className={cn("text-sm text-gray-500", form.watch("xPlaneObjects").length && "text-info")}
				>
					In diesem Einsatz gibt es {form.watch("xPlaneObjects").length} Objekte
				</p>
				<button
					disabled={!(form.watch("xPlaneObjects")?.length > 0)}
					className="btn btn-xs btn-error mt-2"
					onClick={() => form.setValue("xPlaneObjects", [])}
				>
					löschen
				</button>
			</div>

			<div className="form-control min-h-[140px]">
				<div className="flex gap-2">
					<button
						type="submit"
						className="btn btn-warning"
						onClick={form.handleSubmit(async (mission: MissionOptionalDefaults) => {
							try {
								const newMission = await saveMission(mission, {
									createNewMission: !editingMissionId,
									alertWhenValid: true,
								});

								setSearchElements([]); // Reset search elements
								setEditingMission(null);
								setContextMenu(null);
								if (editingMissionId) {
									toast.success(`${newMission.publicId} bearbeitet`);
								} else {
									toast.success(`${newMission.publicId} erstellt`);
								}
								form.reset();
								setOpen(false);
							} catch (error) {
								if (error instanceof AxiosError) {
									toast.error(`Fehler beim Erstellen des Einsatzes: ${error.response?.data.error}`);
								} else {
									toast.error(`Fehler beim Erstellen des Einsatzes: ${(error as Error).message}`);
								}
							}
						})}
					>
						<BellRing className="h-4 w-4" /> Alarmieren
					</button>
					<button
						type="submit"
						className="btn btn-primary flex-1"
						onClick={form.handleSubmit(async (mission: MissionOptionalDefaults) => {
							try {
								const newMission = await saveMission(mission, {
									createNewMission: !editingMissionId,
								});

								setSearchElements([]); // Reset search elements
								setContextMenu(null);
								if (editingMissionId) {
									toast.success(`${newMission.publicId} bearbeitet`);
								} else {
									toast.success(`${newMission.publicId} erstellt`);
								}
								form.reset();
								setOpen(false);
							} catch (error) {
								if (error instanceof AxiosError) {
									toast.error(`Fehler beim Erstellen des Einsatzes: ${error.response?.data.error}`);
								} else {
									toast.error(`Fehler beim Erstellen des Einsatzes: ${(error as Error).message}`);
								}
							}
						})}
					>
						<BookmarkPlus className="h-5 w-5" />{" "}
						{editingMissionId ? "Einsatz bearbeiten" : "Einsatz Vorbereiten"}
					</button>
				</div>
			</div>
		</form>
	);
};
