/* eslint-disable @typescript-eslint/no-explicit-any */
import { OSMWay } from "@repo/db";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
import { useMapStore } from "_store/mapStore";
import { usePannelStore } from "_store/pannelStore";
import { MapPin, MapPinned, Search, Car, Ambulance, Siren, Flame } from "lucide-react";
import { getOsmAddress } from "_querys/osm";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import { Popup, useMap } from "react-leaflet";
import { findClosestPolygon } from "_helpers/findClosestPolygon";
import { xPlaneObjectsAvailable } from "_helpers/xPlaneObjectsAvailable";
import { useQuery } from "@tanstack/react-query";
import { getConnectedAircraftsAPI } from "_querys/aircrafts";

export const ContextMenu = () => {
	const map = useMap();
	const { data: aircrafts } = useQuery({
		queryKey: ["connectedAircrafts"],
		queryFn: getConnectedAircraftsAPI,
	});
	const {
		contextMenu,
		searchElements,
		setContextMenu,
		setSearchElements,
		setSearchPopup,
		toggleSearchElementSelection,
	} = useMapStore();
	const {
		missionFormValues,
		setMissionFormValues,
		setOpen,
		isOpen: isPannelOpen,
	} = usePannelStore((state) => state);
	const [showObjectOptions, setShowObjectOptions] = useState(false);
	const [rulerHover, setRulerHover] = useState(false);
	const [rulerOptionsHover, setRulerOptionsHover] = useState(false);

	const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";

	useEffect(() => {
		const showObjectOptions = rulerHover || rulerOptionsHover;
		setShowObjectOptions(showObjectOptions);
	}, [isPannelOpen, rulerHover, rulerOptionsHover, setOpen]);

	useEffect(() => {
		const handleContextMenu = (e: any) => {
			setContextMenu({ lat: e.latlng.lat, lng: e.latlng.lng });
		};
		const handleClick = () => {
			setContextMenu(null);
			setSearchPopup(null);
		};

		map.on("contextmenu", handleContextMenu);
		map.on("click", handleClick);

		return () => {
			map.off("contextmenu", handleContextMenu);
			map.off("click", handleClick);
		};
	}, [map, contextMenu, setContextMenu, setSearchPopup]);

	if (!contextMenu || !dispatcherConnected) return null;

	const missionBtnText =
		missionFormValues && isPannelOpen ? "Position übernehmen" : "Einsatz erstellen";

	const addOSMobjects = async (ignorePreviosSelected?: boolean) => {
		const res = await fetch(
			`https://overpass-api.de/api/interpreter?data=${encodeURIComponent(`
			[out:json];
			(
			way["building"](around:100, ${contextMenu.lat}, ${contextMenu.lng});
			relation["building"](around:100, ${contextMenu.lat}, ${contextMenu.lng});
			);
			out body;
			>;
			out skel qt;
		`)}`,
		);

		const data = await res.json();
		const parsed: OSMWay[] = data.elements
			.filter((e: any) => e.type === "way")
			.map((e: any) => {
				const elementInMap = searchElements.find((el) => el.wayID === e.id);
				return {
					isSelected: ignorePreviosSelected ? false : (elementInMap?.isSelected ?? false),
					wayID: e.id,
					nodes: e.nodes.map((nodeId: string) => {
						const node = data.elements.find((element: any) => element.id === nodeId);
						return {
							lat: node.lat,
							lon: node.lon,
						};
					}),
					tags: e.tags,
					type: e.type,
				} as OSMWay;
			});

		setSearchElements(parsed);
		return parsed;
	};

	return (
		<Popup
			position={[contextMenu.lat, contextMenu.lng]}
			autoClose={false}
			closeOnClick={false}
			autoPan={false}
		>
			<div
				className="pointer-events-none absolute flex items-center justify-center p-3 opacity-100"
				style={{ left: "-13px", top: "-13px" }}
			>
				<div className="w-38 h-38 pointer-events-none relative flex -translate-x-1/2 -translate-y-1/2 items-center justify-center">
					{/* Top Button */}
					<button
						className="btn btn-circle bg-rescuetrack tooltip tooltip-top tooltip-accent pointer-events-auto absolute left-1/2 top-0 h-10 w-10 opacity-80"
						data-tip={missionBtnText}
						style={{ transform: "translateX(-50%)" }}
						onClick={async () => {
							const { parsed } = await getOsmAddress(contextMenu.lat, contextMenu.lng);
							setOpen(true);
							setMissionFormValues({
								...missionFormValues,
								...parsed,
								state: "draft",
								addressLat: contextMenu.lat,
								addressLng: contextMenu.lng,
							});

							const objects = await addOSMobjects(true);

							const closestObject = findClosestPolygon(objects, {
								lat: contextMenu.lat,
								lon: contextMenu.lng,
							});

							if (closestObject) {
								toggleSearchElementSelection(closestObject.wayID, true);
							}
							if (isPannelOpen) {
								map.setView([contextMenu.lat, contextMenu.lng], 18, {
									animate: true,
								});
							}
						}}
					>
						<MapPinned size={20} />
					</button>
					{/* Left Button */}
					<button
						className="btn btn-circle bg-rescuetrack pointer-events-auto absolute left-0 top-1/2 h-10 w-10 opacity-80"
						style={{ transform: "translateY(-50%)" }}
						onMouseEnter={() => setRulerHover(true)}
						onMouseLeave={() => setRulerHover(false)}
						disabled={
							!isPannelOpen ||
							!xPlaneObjectsAvailable(missionFormValues?.missionStationIds, aircrafts)
						}
					>
						<Car size={20} />
					</button>
					{/* Bottom Button */}
					<button
						className="btn btn-circle bg-rescuetrack tooltip tooltip-bottom tooltip-accent pointer-events-auto absolute bottom-0 left-1/2 h-10 w-10 opacity-80"
						data-tip="Koordinaten kopieren"
						style={{ transform: "translateX(-50%)" }}
						onClick={async () => {
							const coords = `${contextMenu.lat}, ${contextMenu.lng}`;
							await navigator.clipboard.writeText(coords);
							toast.success("Koordinaten in die Zwischenablage kopiert!");
						}}
					>
						<MapPin size={20} />
					</button>
					{/* Right Button (original Search button) */}
					<button
						className="btn btn-circle bg-rescuetrack tooltip tooltip-right tooltip-accent pointer-events-auto absolute right-0 top-1/2 h-10 w-10 opacity-80"
						data-tip="Gebäude suchen"
						style={{ transform: "translateY(-50%)" }}
						onClick={async () => {
							addOSMobjects();
						}}
					>
						<Search size={20} />
					</button>
					{/* XPlane Object Options - shown when Ruler button is hovered or options are hovered */}
					{showObjectOptions && (
						<div
							className="pointer-events-auto absolute -left-[100px] top-1/2 z-10 flex h-[200px] w-[120px] -translate-y-1/2 flex-col items-center justify-center py-5"
							onMouseEnter={() => setRulerOptionsHover(true)}
							onMouseLeave={() => setRulerOptionsHover(false)}
						>
							<div className="flex w-full flex-col">
								<button
									className="btn btn-circle bg-rescuetrack tooltip tooltip-left tooltip-accent mb-2 ml-[30px] h-10 w-10 opacity-80"
									data-tip="Rettungswagen platzieren"
									onClick={() => {
										setMissionFormValues({
											...missionFormValues,
											xPlaneObjects: [
												...(missionFormValues?.xPlaneObjects ?? []),
												{
													objectName: "ambulance",
													alt: 0,
													lat: contextMenu.lat,
													lon: contextMenu.lng,
												},
											],
										});
									}}
								>
									<Ambulance size={20} />
								</button>
								<button
									className="btn btn-circle bg-rescuetrack tooltip tooltip-left tooltip-accent mb-2 h-10 w-10 opacity-80"
									data-tip="LF platzieren"
									onClick={() => {
										console.log("Add fire engine");
										setMissionFormValues({
											...missionFormValues,
											xPlaneObjects: [
												...(missionFormValues?.xPlaneObjects ?? []),
												{
													objectName: "fire_engine",
													alt: 0,
													lat: contextMenu.lat,
													lon: contextMenu.lng,
												},
											],
										});
									}}
								>
									<Flame size={20} />
								</button>
								<button
									className="btn btn-circle bg-rescuetrack tooltip tooltip-left tooltip-accent ml-[30px] h-10 w-10 opacity-80"
									data-tip="Streifenwagen platzieren"
									onClick={() => {
										console.log("Add police");
										setMissionFormValues({
											...missionFormValues,
											xPlaneObjects: [
												...(missionFormValues?.xPlaneObjects ?? []),
												{
													objectName: "police",
													alt: 0,
													lat: contextMenu.lat,
													lon: contextMenu.lng,
												},
											],
										});
									}}
								>
									<Siren size={20} />
								</button>
							</div>
						</div>
					)}
				</div>
			</div>
		</Popup>
	);
};
