"use client";
import React, { useEffect, useMemo, useState } from "react";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import { Badge, cn } from "@repo/shared-components";
import {
	BADGES,
	ConnectedAircraft,
	getPublicUser,
	Mission,
	MissionLog,
	MissionSdsLog,
	MissionStationLog,
	Prisma,
	PublicUser,
	Station,
} from "@repo/db";
import { toast } from "react-hot-toast";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { editConnectedAircraftAPI } from "_querys/aircrafts";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
import { PersonIcon } from "@radix-ui/react-icons";
import {
	Ban,
	BellRing,
	CircleGaugeIcon,
	Clock,
	CompassIcon,
	Component,
	GaugeIcon,
	Hash,
	ListCollapse,
	LocateFixed,
	Lollipop,
	MapPin,
	Mountain,
	Navigation,
	Plus,
	RadioTower,
	Sunset,
	TextSearch,
} from "lucide-react";
import { useSession } from "next-auth/react";
import { sendSdsMessageAPI } from "_querys/missions";
import { getLivekitRooms } from "_querys/livekit";
import { findLeitstelleForPosition } from "_helpers/findLeitstelleinPoint";
import { formatDistance } from "date-fns";
import { de } from "date-fns/locale";

const FMSStatusHistory = ({
	aircraft,
	mission,
}: {
	aircraft: ConnectedAircraft & { Station: Station };
	mission?: Mission;
}) => {
	const log = ((mission?.missionLog as unknown as MissionLog[]) || [])
		.filter((entry) => entry.type === "station-log" && entry.data.stationId === aircraft.Station.id)
		.reverse()
		.splice(0, 6) as MissionStationLog[];

	const aircraftUser: PublicUser =
		typeof aircraft.publicUser === "string" ? JSON.parse(aircraft.publicUser) : aircraft.publicUser;

	return (
		<div className="p-4">
			<ul className="text-base-content font-semibold">
				<li className="mb-1 flex items-center gap-2">
					<p className="flex flex-1 items-center gap-2">
						<PersonIcon className="h-5 w-5" /> {aircraftUser.fullName} ({aircraftUser.publicId}){" "}
						{(() => {
							const badges = aircraftUser.badges
								.filter((b) => b.startsWith("P") && b.length == 2)
								.sort((a, b) => a.localeCompare(b));
							const lastBadge = badges[badges.length - 1];
							return lastBadge ? (
								<Badge badge={lastBadge as BADGES} className="h-5 w-8" width={40} />
							) : null;
						})()}
					</p>
					<p
						className={cn(
							"text-sm font-thin text-gray-500",
							aircraft.esimatedLogoutTime && "tooltip tooltip-left",
						)}
						data-tip={`in ${aircraft.esimatedLogoutTime && formatDistance(new Date(aircraft.esimatedLogoutTime), new Date(), { locale: de })}`}
					>
						{aircraft.esimatedLogoutTime
							? `Geplante Abmeldung: ${new Date(aircraft.esimatedLogoutTime).toLocaleTimeString(
									[],
									{
										hour: "2-digit",
										minute: "2-digit",
									},
								)}`
							: "Keine geplante Abmeldung"}
					</p>
				</li>
			</ul>
			<div className="divider mb-0 mt-0" />
			<ul className="space-y-2">
				{log.map((entry, index) => (
					<li key={index} className="flex items-center gap-2">
						<span
							className="text-base font-bold"
							style={{
								color: FMS_STATUS_TEXT_COLORS[entry.data.newFMSstatus],
							}}
						>
							{entry.data.newFMSstatus}
						</span>
						<span className="text-base-content">
							{new Date(entry.timeStamp).toLocaleTimeString([], {
								hour: "2-digit",
								minute: "2-digit",
							})}
						</span>
					</li>
				))}
			</ul>
		</div>
	);
};

const FMSStatusSelector = ({
	aircraft,
}: {
	aircraft: ConnectedAircraft & { Station: Station };
}) => {
	const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
	const [hoveredStatus, setHoveredStatus] = useState<string | null>(null);
	const queryClient = useQueryClient();
	const changeAircraftMutation = useMutation({
		mutationFn: async ({
			id,
			update,
		}: {
			id: number;
			update: Prisma.ConnectedAircraftUpdateInput;
		}) => {
			await editConnectedAircraftAPI(id, update);
			queryClient.invalidateQueries({
				queryKey: ["aircrafts"],
			});
		},
	});

	return (
		<div className="text-base-content mt-2 flex flex-col gap-2 p-4">
			<div className="flex h-full items-center justify-center gap-2">
				{Array.from({ length: 9 }, (_, i) => (i + 1).toString())
					.filter((status) => status !== "5") // Exclude status 5
					.map((status) => (
						<button
							disabled={!dispatcherConnected}
							key={status}
							className={cn(
								"min-w-13 min-h-13 flex cursor-pointer items-center justify-center text-4xl font-bold",
								!dispatcherConnected && "cursor-not-allowed",
							)}
							style={{
								backgroundColor:
									hoveredStatus === status
										? FMS_STATUS_COLORS[status]
										: aircraft.fmsStatus === status
											? FMS_STATUS_COLORS[status]
											: "var(--color-base-200)",
								color:
									aircraft.fmsStatus === status
										? "white"
										: hoveredStatus === status
											? "white"
											: "gray",
							}}
							onMouseEnter={() => setHoveredStatus(status)}
							onMouseLeave={() => setHoveredStatus(null)}
							onClick={async () => {
								await changeAircraftMutation.mutateAsync({
									id: aircraft.id,
									update: {
										fmsStatus: status,
									},
								});
								toast.success(`Status auf ${status} geändert`);
							}}
						>
							{status}
						</button>
					))}
			</div>
			<div className="flex items-center justify-center gap-1 p-2">
				{["E", "C", "F", "J", "L", "c", "d", "h", "o", "u"].map((status) => (
					<button
						disabled={!dispatcherConnected}
						key={status}
						className={cn(
							"flex min-h-10 min-w-10 cursor-pointer items-center justify-center text-lg font-bold",
							!dispatcherConnected && "cursor-not-allowed",
						)}
						style={{
							backgroundColor:
								hoveredStatus === status
									? FMS_STATUS_COLORS[6]
									: aircraft.fmsStatus === status
										? FMS_STATUS_COLORS[status]
										: "var(--color-base-200)",
							color:
								aircraft.fmsStatus === status
									? "white"
									: hoveredStatus === status
										? "white"
										: "gray",
						}}
						onMouseEnter={() => setHoveredStatus(status)}
						onMouseLeave={() => setHoveredStatus(null)}
						onClick={async () => {
							await changeAircraftMutation.mutateAsync({
								id: aircraft.id,
								update: {
									fmsStatus: status,
								},
							});
						}}
					>
						{status}
					</button>
				))}
			</div>
		</div>
	);
};

const StationTab = ({ aircraft }: { aircraft: ConnectedAircraft & { Station: Station } }) => {
	const station = aircraft.Station;
	const { data: livekitRooms } = useQuery({
		queryKey: ["livekit-rooms"],
		queryFn: () => getLivekitRooms(),
		refetchInterval: 5000,
	});

	const participants =
		livekitRooms?.flatMap((room) =>
			room.participants.map((p) => ({
				...p,
				roomName: room.room.name,
			})),
		) || [];

	const livekitUser = participants.find((p) => p.attributes.userId === aircraft.userId);

	const lstName = useMemo(() => {
		if (!aircraft.posLng || !aircraft.posLat) return station.bosRadioArea;
		return findLeitstelleForPosition(aircraft.posLng, aircraft.posLat);
	}, [aircraft.posLng, aircraft.posLat, station.bosRadioArea]);

	return (
		<div className="text-base-content p-4">
			<ul className="text-base-content font-semibold">
				<li className="mb-1 flex items-center gap-2">
					<Component size={16} /> Aktuelle Rufgruppe: {livekitUser?.roomName || "Nicht verbunden"}
				</li>
				<li className="mb-1 flex items-center gap-2">
					<RadioTower size={16} /> Leitstellenbereich: {lstName || station.bosRadioArea}
				</li>
			</ul>
			<div className="divider mb-0 mt-0" />
			<div className="mb-2 mt-2 flex items-center justify-between pr-2 text-sm font-semibold">
				<span className="flex items-center gap-2">
					<Clock size={16} /> {station.is24h ? "24h Betrieb" : "Tagbetrieb"}
				</span>
				<span className="flex items-center gap-2">
					<Sunset size={16} /> NVG: {station.hasNvg ? "Ja" : "Nein"}
				</span>
				<span className="flex items-center gap-2">
					<Mountain size={16} /> Winch: {station.hasWinch ? "Ja" : "Nein"}
				</span>
				<span className="flex items-center gap-2">
					<TextSearch size={16} /> {station.aircraftRegistration}
				</span>
			</div>
			<div className="divider mb-0 mt-0" />
			<div className="mt-2 flex items-center justify-between pr-2 text-sm font-semibold">
				<span className="flex items-center gap-2">
					<CompassIcon size={16} /> HDG: {aircraft.posHeading}°
				</span>
				<span className="flex items-center gap-2">
					<GaugeIcon size={16} /> SPD: {aircraft.posSpeed} kt
				</span>
				<span className="flex items-center gap-2">
					<CircleGaugeIcon size={16} /> ALT: {aircraft.posAlt} ft
				</span>
			</div>
			<div className="mt-2 flex items-center justify-between pr-2 text-sm font-semibold">
				<span className="flex items-center gap-2">
					<Lollipop size={16} />{" "}
					<span className={cn(aircraft.posH145active && "text-green-500")}>
						{aircraft.posH145active ? "H145 Aktiv" : "H145 Inaktiv"}
					</span>
				</span>
				<span className="flex items-center gap-2">
					<Lollipop size={16} />{" "}
					<span className={cn(aircraft.posXplanePluginActive && "text-green-500")}>
						{aircraft.posXplanePluginActive ? "X-Plane Plugin Aktiv" : "X-Plane Plugin Inaktiv"}
					</span>
				</span>
			</div>
		</div>
	);
};

const MissionTab = ({ mission }: { mission: Mission }) => {
	return (
		<div className="text-base-content p-4">
			<ul className="text-base-content font-semibold">
				<li className="mb-1 flex items-center gap-2">
					<BellRing size={16} /> {mission.missionKeywordCategory}
				</li>
				<li className="mb-1 flex items-center gap-2">
					<ListCollapse size={16} />
					{mission.missionKeywordName}
				</li>
				<li className="mt-3 flex items-center gap-2">
					<Hash size={16} />
					__{new Date().toISOString().slice(0, 10).replace(/-/g, "")}
					{mission.id}
				</li>
			</ul>
			<div className="divider mb-0 mt-0" />
			<div className="text-sm font-semibold">
				<p className="flex items-center gap-2">
					<MapPin size={16} /> {mission.addressLat} {mission.addressLng}
				</p>
				<p className="flex items-center gap-2">
					<Navigation size={16} /> {mission.addressStreet}
				</p>
				<p className="flex items-center gap-2">
					<LocateFixed size={16} /> {mission.addressZip} {mission.addressCity}
				</p>
			</div>
		</div>
	);
};

const SDSTab = ({
	aircraft,
	mission,
}: {
	aircraft: ConnectedAircraft & {
		Station: Station;
	};
	mission?: Mission;
}) => {
	const session = useSession();
	const [isChatOpen, setIsChatOpen] = useState(false);
	const [note, setNote] = useState("");
	const queryClient = useQueryClient();
	const textInputRef = React.useRef<HTMLInputElement>(null);

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

	const sendSdsMutation = useMutation({
		mutationFn: async ({
			missionId,
			sdsMessage,
		}: {
			missionId?: number;
			sdsMessage: MissionSdsLog;
		}) => {
			await sendSdsMessageAPI({ missionId, sdsMessage });
			queryClient.invalidateQueries({
				queryKey: ["missions"],
			});
		},
	});

	const log = useMemo(
		() =>
			(mission?.missionLog as unknown as MissionLog[])
				?.slice()
				.reverse()
				.filter(
					(entry) => entry.type === "sds-log" && entry.data.stationId === aircraft.Station.id,
				) || [],
		[mission?.missionLog, aircraft.Station.id],
	);

	useEffect(() => {
		const interval = setInterval(() => {
			textInputRef.current?.focus();
		}, 100);
		return () => clearInterval(interval);
	});

	const sendSds = () => {
		sendSdsMutation
			.mutateAsync({
				missionId: mission?.id,
				sdsMessage: {
					type: "sds-log",
					auto: false,
					timeStamp: new Date().toISOString(),
					data: {
						stationId: aircraft.Station.id,
						station: aircraft.Station,
						message: note,
						user: getPublicUser(session.data!.user, {
							ignorePrivacy: true,
						}),
					},
				},
			})
			.then(() => {
				toast.success("SDS-Nachricht gesendet");
				setIsChatOpen(false);
				setNote("");
			});
	};

	return (
		<div className="p-4">
			{dispatcherConnected && (
				<div>
					<div className="flex items-center gap-2">
						{!isChatOpen ? (
							<button
								className="text-base-content cursor-pointer text-base"
								onClick={() => setIsChatOpen(true)}
							>
								<span className="flex items-center gap-2">
									<Plus size={18} /> SDS senden
								</span>
							</button>
						) : (
							<div className="flex w-full items-center gap-2">
								<input
									autoFocus
									type="text"
									placeholder=""
									className="input input-sm text-base-content flex-1"
									value={note}
									onChange={(e) => setNote(e.target.value)}
									ref={textInputRef}
									onKeyDown={(e) => {
										if (e.key === "Enter" && note.trim()) {
											sendSds();
										}
									}}
								/>
								<button
									className="btn btn-sm btn-primary btn-outline"
									onClick={() => {
										if (!note.trim()) return;
										sendSds();
									}}
								>
									<Plus size={20} />
								</button>
								<button
									className="btn btn-sm btn-outline"
									onClick={() => {
										setIsChatOpen(false);
										setNote("");
									}}
								>
									<Ban size={20} />
								</button>
							</div>
						)}
					</div>
					<div className="divider m-0" />
				</div>
			)}
			<ul className="max-h-[300px] space-y-2 overflow-x-auto overflow-y-auto">
				{log.map((entry, index) => {
					const sdsEntry = entry as MissionSdsLog;
					return (
						<li key={index} className="flex items-center gap-2">
							<span className="text-base-content">
								{new Date(sdsEntry.timeStamp).toLocaleTimeString([], {
									hour: "2-digit",
									minute: "2-digit",
								})}
							</span>
							<span
								className="text-base font-bold"
								style={{
									color: FMS_STATUS_TEXT_COLORS[6],
								}}
							>
								{sdsEntry.data.user.firstname?.[0]?.toUpperCase() ?? "?"}
								{sdsEntry.data.user.lastname?.[0]?.toUpperCase() ?? "?"}
							</span>
							<span className="text-base-content">{sdsEntry.data.message}</span>
						</li>
					);
				})}
				{!log.length && (
					<p className="my-10 w-full text-center font-semibold text-gray-500">
						Kein SDS-Verlauf verfügbar
					</p>
				)}
			</ul>
		</div>
	);
};

export { FMSStatusSelector, StationTab as RettungsmittelTab, MissionTab, SDSTab };
export default FMSStatusHistory;
