"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 { Select } from "_components/Select";
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 { getStationsAPI } from "_querys/stations";
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 "_helpers/cn";

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

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

	const { data: aircrafts } = useQuery({
		queryKey: ["aircrafts"],
		queryFn: getConnectedAircraftsAPI,
		refetchInterval: 10000,
	});

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

	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 session = useSession();
	const defaultFormValues = React.useMemo(
		() =>
			({
				createdUserId: session.data?.user.id,
				type: "primär",
				addressOSMways: [],
				missionKeywordAbbreviation: null as any,
				missionKeywordCategory: null as any,
				missionKeywordName: null as any,
				hpgFireEngineState: null,
				hpgAmbulanceState: null,
				hpgPoliceState: null,
				hpgMissionString: null,
				hpgSelectedMissionString: null,
				hpg: null,
				missionLog: [],
			}) as Partial<MissionOptionalDefaults>,
		[session.data?.user.id],
	);

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

	const validationRequired = HPGValidationRequired(
		form.watch("missionStationIds"),
		aircrafts,
		form.watch("hpgMissionString"),
	);

	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]);

	useEffect(() => {
		if (missionFormValues) {
			if (Object.keys(missionFormValues).length === 0) {
				form.reset();
				return;
			}
			for (const key in missionFormValues) {
				form.setValue(
					key as keyof MissionOptionalDefaults,
					missionFormValues[key as keyof MissionOptionalDefaults],
				);
			}
		}
	}, [missionFormValues, form, defaultFormValues]);

	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),
				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}`);
				});
			}
			return newMission;
		} 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, {}).catch((error) => {
				toast.error(`Fehler beim Starten der HPG-Validierung: ${error.message}`);
			});
		}
		return newMission;
	};

	return (
		<form className="space-y-4">
			{/* Koorinaten Section */}
			<div className="form-control">
				<h2 className="text-lg font-bold mb-2">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="text-lg font-bold mb-2">Adresse</h2>
				<input
					type="text"
					{...form.register("addressStreet")}
					placeholder="Straße"
					className="input input-primary input-bordered w-full mb-4"
				/>
				<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 w-full mt-4"
				/>
			</div>

			{/* Rettungsmittel Section */}
			<div className="form-control">
				<h2 className="text-lg font-bold mb-2">Rettungsmittel</h2>
				<Select
					name="missionStationIds"
					label={""}
					placeholder="Wähle ein oder mehrere Rettungsmittel aus"
					isMulti
					form={form}
					options={stations?.map((s) => ({
						label: s.bosCallsign,
						value: s.id,
					}))}
				/>
			</div>

			{/* Einsatzdaten Section */}
			<div className="form-control">
				<h2 className="text-lg font-bold mb-2">Einsatzdaten</h2>
				<select
					{...form.register("type")}
					className="select select-primary select-bordered w-full mb-4"
					onChange={(e) => {
						form.setValue("type", e.target.value as missionType);
						form.setValue("missionKeywordName", KEYWORD_CATEGORY.AB_ATMUNG);
						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 w-full mb-4"
							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).map((use) => (
								<option key={use} value={use}>
									{use}
								</option>
							))}
						</select>
						{form.formState.errors.missionKeywordCategory && (
							<p className="text-error text-sm mb-4">Bitte wähle eine Kategorie aus.</p>
						)}
						<select
							{...form.register("missionKeywordAbbreviation")}
							className="select select-primary select-bordered w-full mb-4"
							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 text-sm mb-4">Bitte wähle ein Stichwort aus.</p>
						)}
						<div className="mb-4">
							<select
								{...form.register("hpgMissionString")}
								onChange={(e) => {
									form.setValue("hpgMissionString", e.target.value);
									if (
										form.watch("missionAdditionalInfo").length === 0 ||
										form.watch("missionAdditionalInfo").startsWith("HPG-Szenario:")
									) {
										const [name] = e.target.value.split(":");
										form.setValue("missionAdditionalInfo", `HPG-Szenario: ${name}`);
									}
								}}
								className="select select-primary select-bordered w-full mb-2"
								value={form.watch("hpgMissionString") || "please_select"}
							>
								<option disabled value="please_select">
									Einsatz Szenario auswählen...
								</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-sm text-warning">Szenario wird vor Alarmierung HPG-Validiert.</p>
							)}
						</div>
					</>
				)}
				<textarea
					{...form.register("missionAdditionalInfo")}
					placeholder="Einsatzinformationen"
					className="textarea textarea-primary textarea-bordered w-full mb-4"
				/>
				{form.watch("type") === "sekundär" && (
					<input
						{...form.register("addressMissionLocation")}
						type="text"
						placeholder="Zielkrankenhaus"
						className="input input-primary input-bordered w-full"
					/>
				)}
			</div>
			<div className="form-control">
				<h2 className="text-lg font-bold mb-2">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="form-control min-h-[140px]">
				<div className="flex gap-2">
					{isEditingMission && editingMissionId ? (
						<button
							type="button"
							className="btn btn-primary flex-1"
							onClick={form.handleSubmit(async (mission: MissionOptionalDefaults) => {
								try {
									const newMission = await saveMission(mission);
									toast.success(`Einsatz ${newMission.id} erfolgreich aktualisiert`);
									setSearchElements([]); // Reset search elements
									setEditingMission(false, null); // Reset editing state
									form.reset(); // Reset the form
									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}`);
									}
								}
							})}
						>
							Änderungen speichern
						</button>
					) : (
						<>
							<button
								type="submit"
								className="btn btn-warning"
								onClick={form.handleSubmit(async (mission: MissionOptionalDefaults) => {
									try {
										const newMission = await saveMission(mission, {
											alertWhenValid: true,
										});
										if (!validationRequired) {
											await sendAlertMutation.mutateAsync(newMission.id);
										}
										setSearchElements([]); // Reset search elements
										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: true,
										});

										setSearchElements([]); // Reset search elements
										toast.success(`Einsatz ${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" /> Einsatz vorbereiten
							</button>
						</>
					)}
				</div>
			</div>
		</form>
	);
};
