import { For, Show, createEffect, createMemo, createSignal, onMount, type JSX } from "solid-js";
import { Portal } from "solid-js/web";
import { ChevronRight, Plus } from "../../../lib/icons";
import {
	getProjectContextMenuEyebrow,
	getProjectContextMenuSections,
	type ProjectContextMenuAction,
	type ProjectMenuTarget,
	type WorkspaceContextMenuShortcut,
} from "../../app-shell/data/shell.data";
import styles from "../WorkspaceContextMenu/WorkspaceContextMenu.module.scss";

type ShortcutPlatform = "mac" | "windows";

type NavigatorWithUserAgentData = Navigator & {
	userAgentData?: {
		platform?: string;
	};
};

type ProjectContextMenuPosition = {
	x: number;
	y: number;
};

type ProjectContextMenuProps = {
	target: ProjectMenuTarget | null;
	position: ProjectContextMenuPosition | null;
	onClose: VoidFunction;
	onSelect: (action: ProjectContextMenuAction, target: ProjectMenuTarget) => void;
	menuRef: (element: HTMLDivElement) => void;
};

const getShortcutPlatform = (): ShortcutPlatform => {
	if (typeof navigator === "undefined") {
		return "mac";
	}

	const navigatorWithUserAgentData = navigator as NavigatorWithUserAgentData;
	const platform =
		typeof navigatorWithUserAgentData.userAgentData?.platform === "string"
			? navigatorWithUserAgentData.userAgentData.platform
			: navigator.platform;

	return /mac|iphone|ipad|ipod/i.test(platform) ? "mac" : "windows";
};

const formatShortcut = (shortcut: WorkspaceContextMenuShortcut, platform: ShortcutPlatform): string => {
	const keyLabel = (() => {
		switch (shortcut.key) {
			case "enter":
				return platform === "mac" ? "↩" : "Enter";
			case "delete":
				return platform === "mac" ? "⌫" : "Del";
			default:
				return shortcut.key.toUpperCase();
		}
	})();

	const modifierLabels =
		shortcut.modifiers?.map((modifier) => {
			switch (modifier) {
				case "meta":
					return platform === "mac" ? "⌘" : "Ctrl";
				case "alt":
					return platform === "mac" ? "⌥" : "Alt";
				case "shift":
					return platform === "mac" ? "⇧" : "Shift";
			}
		}) ?? [];

	return platform === "mac" ? `${modifierLabels.join("")}${keyLabel}` : [...modifierLabels, keyLabel].join("+");
};

export const ProjectContextMenu = (props: ProjectContextMenuProps): JSX.Element => {
	const [activeSubmenuActionId, setActiveSubmenuActionId] = createSignal<string | null>(null);
	const [shortcutPlatform, setShortcutPlatform] = createSignal<ShortcutPlatform>("mac");
	const sections = createMemo(() => (props.target ? getProjectContextMenuSections(props.target) : []));
	const isCreateAction = (action: ProjectContextMenuAction): boolean => action.id.startsWith("new-");
	const menuState = createMemo<{
		target: ProjectMenuTarget;
		position: ProjectContextMenuPosition;
	} | null>(() => (props.target && props.position ? { target: props.target, position: props.position } : null));

	onMount(() => {
		setShortcutPlatform(getShortcutPlatform());
	});

	createEffect(() => {
		void props.target;
		setActiveSubmenuActionId(null);
	});

	return (
		<Show when={menuState()}>
			{(resolvedMenuState): JSX.Element => {
				const target = resolvedMenuState().target;
				const position = resolvedMenuState().position;

				return (
					<Portal>
						<div
							ref={props.menuRef}
							class={styles.menu}
							role="menu"
							aria-label={`${target.label} project context menu`}
							style={{ left: `${position.x}px`, top: `${position.y}px` }}
						>
							<Show when={target.kind !== "surface"}>
								<header class={styles.header}>
									<span class={styles.eyebrow}>{getProjectContextMenuEyebrow(target)}</span>
									<strong class={styles.title}>{target.label}</strong>
								</header>
							</Show>

							<div class={styles.sectionList}>
								<For each={sections()}>
									{(section): JSX.Element => (
										<section class={styles.section}>
											<Show when={section.label}>
												<span class={styles.sectionLabel}>{section.label}</span>
											</Show>
											<div class={styles.actionList}>
												<For each={section.items}>
													{(action): JSX.Element => {
														const isSubmenuOpen = () => activeSubmenuActionId() === action.id;

														return (
															<div class={styles.actionItem} onMouseEnter={() => setActiveSubmenuActionId(action.children ? action.id : null)}>
												<button
													type="button"
													role="menuitem"
													classList={{
														[styles.action]: true,
														[styles.actionCreate]: isCreateAction(action),
														[styles.actionDanger]: action.tone === "danger",
														[styles.actionSubmenuOpen]: isSubmenuOpen(),
													}}
																	onClick={() => {
																		if (action.children) {
																			setActiveSubmenuActionId(isSubmenuOpen() ? null : action.id);
																			return;
																		}

														props.onSelect(action, target);
														props.onClose();
													}}
												>
													<Show when={isCreateAction(action)}>
														<span class={styles.actionCreateIcon} aria-hidden="true">
															<Plus size={14} strokeWidth={2.25} />
														</span>
													</Show>
																	<span class={styles.actionLabel}>{action.label}</span>
																	<div class={styles.actionMeta}>
																		<Show when={action.shortcut}>
																			<span class={styles.actionShortcut}>{formatShortcut(action.shortcut!, shortcutPlatform())}</span>
																		</Show>
																		<Show when={action.children}>
																			<ChevronRight class={styles.actionChevron} size={16} strokeWidth={2} />
																		</Show>
																	</div>
																</button>

																<Show when={action.children && isSubmenuOpen()}>
																	<div class={styles.submenu} role="menu" aria-label={`${action.label} submenu`}>
																		<div class={styles.submenuList}>
																			<For each={action.children ?? []}>
																				{(childAction): JSX.Element => (
																					<button
																						type="button"
																						role="menuitem"
																						classList={{
																							[styles.action]: true,
																							[styles.actionDanger]: childAction.tone === "danger",
																						}}
																						onClick={() => {
																							props.onSelect(childAction, target);
																							props.onClose();
																						}}
																					>
																						<span class={styles.actionLabel}>{childAction.label}</span>
																					</button>
																				)}
																			</For>
																		</div>
																	</div>
																</Show>
															</div>
														);
													}}
												</For>
											</div>
										</section>
									)}
								</For>
							</div>
						</div>
					</Portal>
				);
			}}
		</Show>
	);
};
