import {
	type ConditionId,
	getConditionDescription,
	getConditionsForEdition,
} from "@initiative/domain";
import type { LucideIcon } from "lucide-react";
import {
	ArrowDown,
	Ban,
	BatteryLow,
	Droplet,
	EarOff,
	EyeOff,
	Gem,
	Ghost,
	Hand,
	Heart,
	Link,
	Moon,
	ShieldMinus,
	Siren,
	Snail,
	Sparkles,
	ZapOff,
} from "lucide-react";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useRulesEditionContext } from "../contexts/rules-edition-context.js";
import { cn } from "../lib/utils";
import { Tooltip } from "./ui/tooltip.js";

const ICON_MAP: Record<string, LucideIcon> = {
	EyeOff,
	Heart,
	EarOff,
	BatteryLow,
	Siren,
	Hand,
	Ban,
	Ghost,
	ZapOff,
	Gem,
	Droplet,
	ArrowDown,
	Link,
	ShieldMinus,
	Snail,
	Sparkles,
	Moon,
};

const COLOR_CLASSES: Record<string, string> = {
	neutral: "text-muted-foreground",
	pink: "text-pink-400",
	amber: "text-amber-400",
	orange: "text-orange-400",
	gray: "text-gray-400",
	violet: "text-violet-400",
	yellow: "text-yellow-400",
	slate: "text-slate-400",
	green: "text-green-400",
	indigo: "text-indigo-400",
	sky: "text-sky-400",
};

interface ConditionPickerProps {
	anchorRef: React.RefObject<HTMLElement | null>;
	activeConditions: readonly ConditionId[] | undefined;
	onToggle: (conditionId: ConditionId) => void;
	onClose: () => void;
}

export function ConditionPicker({
	anchorRef,
	activeConditions,
	onToggle,
	onClose,
}: Readonly<ConditionPickerProps>) {
	const ref = useRef<HTMLDivElement>(null);
	const [pos, setPos] = useState<{
		top: number;
		left: number;
		maxHeight: number;
	} | null>(null);

	useLayoutEffect(() => {
		const anchor = anchorRef.current;
		const el = ref.current;
		if (!anchor || !el) return;

		const anchorRect = anchor.getBoundingClientRect();
		const menuHeight = el.scrollHeight;
		const pad = 8;

		const spaceBelow = window.innerHeight - anchorRect.bottom - pad;
		const spaceAbove = anchorRect.top - pad;
		const openBelow = spaceBelow >= menuHeight || spaceBelow >= spaceAbove;

		const top = openBelow
			? anchorRect.bottom + 4
			: Math.max(pad, anchorRect.top - Math.min(menuHeight, spaceAbove) - 4);
		const maxHeight = openBelow ? spaceBelow : Math.min(menuHeight, spaceAbove);

		setPos({ top, left: anchorRect.left, maxHeight });
	}, [anchorRef]);

	useEffect(() => {
		function handleClickOutside(e: MouseEvent) {
			if (ref.current && !ref.current.contains(e.target as Node)) {
				onClose();
			}
		}
		document.addEventListener("mousedown", handleClickOutside);
		return () => document.removeEventListener("mousedown", handleClickOutside);
	}, [onClose]);

	const { edition } = useRulesEditionContext();
	const conditions = getConditionsForEdition(edition);
	const active = new Set(activeConditions ?? []);

	return createPortal(
		<div
			ref={ref}
			className="card-glow fixed z-50 w-fit overflow-y-auto rounded-lg border border-border bg-background p-1"
			style={
				pos
					? { top: pos.top, left: pos.left, maxHeight: pos.maxHeight }
					: { visibility: "hidden" as const }
			}
		>
			{conditions.map((def) => {
				const Icon = ICON_MAP[def.iconName];
				if (!Icon) return null;
				const isActive = active.has(def.id);
				const colorClass = COLOR_CLASSES[def.color] ?? "text-muted-foreground";
				return (
					<Tooltip
						key={def.id}
						content={getConditionDescription(def, edition)}
						className="block"
					>
						<button
							type="button"
							className={cn(
								"flex w-full items-center gap-2 rounded px-2 py-1 text-sm transition-colors hover:bg-hover-neutral-bg",
								isActive && "bg-card/50",
							)}
							onClick={() => onToggle(def.id)}
						>
							<Icon
								size={14}
								className={isActive ? colorClass : "text-muted-foreground"}
							/>
							<span
								className={
									isActive ? "text-foreground" : "text-muted-foreground"
								}
							>
								{def.label}
							</span>
						</button>
					</Tooltip>
				);
			})}
		</div>,
		document.body,
	);
}
