"use client";

import { useEffect, useState } from "react";
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
import {
	Disc,
	Mic,
	PlugZap,
	ServerCrash,
	ShieldQuestion,
	Signal,
	SignalLow,
	SignalMedium,
	WifiOff,
	ZapOff,
} from "lucide-react";
import { useAudioStore } from "_store/audioStore";
import { cn } from "_helpers/cn";
import { ConnectionQuality } from "livekit-client";
import { ROOMS } from "_data/livekitRooms";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
import { useSession } from "next-auth/react";
import { dispatchSocket } from "dispatch/socket";
import { useSounds } from "_components/Audio/useSounds";

export const Audio = () => {
	const {
		speakingParticipants,
		isTalking,
		toggleTalking,
		connect,
		state,
		connectionQuality,
		disconnect,
		remoteParticipants,
		room,
		message,
		removeMessage,
	} = useAudioStore();
	const [selectedRoom, setSelectedRoom] = useState<string>("LST_01");
	useSounds({
		isReceiving: speakingParticipants.length > 0,
		isTransmitting: isTalking,
		unpausedTracks: speakingParticipants,
	});

	const { selectedStation, status: pilotState } = usePilotConnectionStore((state) => state);
	const { selectedZone, status: dispatcherState } = useDispatchConnectionStore((state) => state);
	const session = useSession();
	const [isReceivingBlick, setIsReceivingBlick] = useState(false);
	const [recentSpeakers, setRecentSpeakers] = useState<typeof speakingParticipants>([]);

	useEffect(() => {
		if (speakingParticipants.length > 0) {
			setRecentSpeakers(speakingParticipants);
		} else if (recentSpeakers.length > 0) {
			const timeout = setTimeout(() => {
				setRecentSpeakers([]);
			}, 10000);
			return () => clearTimeout(timeout);
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [speakingParticipants]);

	useEffect(() => {
		if (speakingParticipants.length > 0) {
			setIsReceivingBlick(true);

			const timeout = setInterval(() => {
				setIsReceivingBlick((s) => !s);
			}, 1000);
			return () => {
				clearTimeout(timeout);
				setIsReceivingBlick(false);
			};
		}
	}, [setIsReceivingBlick, speakingParticipants]);

	useEffect(() => {
		if (message && state !== "error") {
			const timeout = setTimeout(() => {
				removeMessage();
			}, 10000);
			return () => clearTimeout(timeout);
		}
	}, [message, removeMessage, state]);

	const displayedSpeakers = speakingParticipants.length > 0 ? speakingParticipants : recentSpeakers;

	const canStopOtherSpeakers = dispatcherState === "connected";

	const role =
		(dispatcherState === "connected" && selectedZone) ||
		(pilotState == "connected" && selectedStation?.bosCallsignShort) ||
		session.data?.user?.publicId;

	return (
		<>
			<div className="bg-base-200 rounded-box flex items-center gap-2 p-1">
				{message && (
					<div
						className="tooltip tooltip-left tooltip-warning font-semibold"
						data-tip="Nachricht entfernen"
					>
						<button
							className={cn("btn btn-sm btn-ghost border-warning bg-transparent ")}
							onClick={() => {
								removeMessage();
							}}
						>
							{message}
						</button>
					</div>
				)}
				{displayedSpeakers.length > 0 && (
					<div
						className={cn(
							"tooltip-left tooltip-error font-semibold",
							canStopOtherSpeakers && speakingParticipants.length > 0 && "tooltip",
						)}
						data-tip="Funkspruch unterbrechen"
					>
						<button
							className={cn(
								"btn btn-sm btn-soft bg-transparent border",
								canStopOtherSpeakers && speakingParticipants.length > 0 && "hover:bg-error",
								speakingParticipants.length > 0 && " hover:bg-errorborder",
								isReceivingBlick && "border-warning",
							)}
							onClick={() => {
								if (!canStopOtherSpeakers) return;
								const payload = JSON.stringify({
									by: role,
								});
								speakingParticipants.forEach(async (p) => {
									await room?.localParticipant.performRpc({
										destinationIdentity: p.identity,
										method: "force-mute",
										payload,
									});
								});
							}}
						>
							{displayedSpeakers.map((p) => p.attributes.role).join(", ") || ""}
						</button>
					</div>
				)}
				<button
					onClick={() => {
						if (state === "connected") toggleTalking();
						if (!role) return;
						if (state === "error" || state === "disconnected") connect(selectedRoom, role);
					}}
					className={cn(
						"btn btn-sm btn-soft border-none hover:bg-inherit",
						!isTalking && "bg-transparent hover:bg-sky-400/20",
						isTalking && "bg-green-700 hover:bg-green-600",
						state === "disconnected" && "bg-red-500 hover:bg-red-500",
						state === "error" && "bg-red-500 hover:bg-red-500",
						state === "connecting" && "bg-yellow-500 hover:bg-yellow-500 cursor-default",
					)}
				>
					{state === "connected" && <Mic className="w-5 h-5" />}
					{state === "disconnected" && <WifiOff className="w-5 h-5" />}
					{state === "connecting" && <PlugZap className="w-5 h-5" />}
					{state === "error" && <ServerCrash className="w-5 h-5" />}
				</button>

				{state === "connected" && (
					<details className="dropdown relative z-[1050]">
						<summary className="dropdown btn btn-ghost flex items-center gap-1">
							{connectionQuality === ConnectionQuality.Excellent && <Signal className="w-5 h-5" />}
							{connectionQuality === ConnectionQuality.Good && <SignalMedium className="w-5 h-5" />}
							{connectionQuality === ConnectionQuality.Poor && <SignalLow className="w-5 h-5" />}
							{connectionQuality === ConnectionQuality.Lost && <ZapOff className="w-5 h-5" />}
							{connectionQuality === ConnectionQuality.Unknown && (
								<ShieldQuestion className="w-5 h-5" />
							)}
							<div className="badge badge-sm badge-soft badge-success">{remoteParticipants}</div>
						</summary>
						<ul className="menu dropdown-content bg-base-200 rounded-box z-[1050] w-52 p-2 shadow-sm">
							{ROOMS.map((r) => (
								<li key={r}>
									<button
										className="btn btn-sm btn-ghost text-left flex items-center justify-start gap-2 relative"
										onClick={() => {
											if (!role) return;
											if (selectedRoom === r) return;
											setSelectedRoom(r);
											connect(r, role);
										}}
									>
										{room?.name === r && (
											<Disc className="text-success text-sm absolute left-2" width={15} />
										)}
										<span className="flex-1 text-center">{r}</span>
									</button>
								</li>
							))}
							<li>
								<button
									className="btn btn-sm btn-ghost text-left flex items-center justify-start gap-2 relative"
									onClick={() => {
										disconnect();
									}}
								>
									<WifiOff className="text-error text-sm absolute left-2" width={15} />
									<span className="flex-1 text-center">Disconnect</span>
								</button>
							</li>
						</ul>
					</details>
				)}
			</div>
		</>
	);
};
