import { useMemo, useState } from "@wordpress/element";
import { Button, TextControl, Notice } from "@wordpress/components";
import { buildTree } from "./tree";

export default function MenuTree({
									 items,
									 selectedId,
									 onSelect,
									 onAddChild,
									 onReorder,
									 onPatchItem,
									 onSaveItem,
									 onDeleteItem,
									 onOpenSettingsModal,
									 busy,
								 }) {
	const tree = useMemo(() => buildTree(items), [items]);
	const [dropHint, setDropHint] = useState(null);

	return (
		<div>
			{tree.map((n) => (
				<Node
					key={n.id}
					node={n}
					depth={0}
					selectedId={selectedId}
					onSelect={onSelect}
					onAddChild={onAddChild}
					onReorder={onReorder}
					onPatchItem={onPatchItem}
					onSaveItem={onSaveItem}
					onDeleteItem={onDeleteItem}
					onOpenSettingsModal={onOpenSettingsModal}
					busy={busy}
					dropHint={dropHint}
					setDropHint={setDropHint}
				/>
			))}
		</div>
	);
}

function Node({
				  node,
				  depth,
				  selectedId,
				  onSelect,
				  onAddChild,
				  onReorder,
				  onPatchItem,
				  onSaveItem,
				  onDeleteItem,
				  onOpenSettingsModal,
				  busy,
				  dropHint,
				  setDropHint,
			  }) {
	const [expanded, setExpanded] = useState(false);
	const selected = String(node.id) === String(selectedId);

	const isDropTarget = dropHint && String(dropHint.dropId) === String(node.id);
	const dropMode = isDropTarget ? dropHint.mode : null;

	const onDragStart = (e) => {
		e.dataTransfer.setData("text/plain", String(node.id));
		e.dataTransfer.effectAllowed = "move";
	};

	const calcMode = (e) => {
		const rect = e.currentTarget.getBoundingClientRect();
		const y = e.clientY - rect.top;
		const r = y / rect.height;
		if (r < 0.25) return "before";
		if (r > 0.75) return "after";
		return "child";
	};

	const onDragOver = (e) => {
		e.preventDefault();
		e.dataTransfer.dropEffect = "move";
		const mode = calcMode(e);
		setDropHint({ dropId: node.id, mode });
	};

	const onDragLeave = () => {
		if (!dropHint) return;
		if (String(dropHint.dropId) !== String(node.id)) return;
		setDropHint(null);
	};

	const onDrop = (e) => {
		e.preventDefault();
		const dragId = e.dataTransfer.getData("text/plain");
		if (!dragId || String(dragId) === String(node.id)) return;

		const mode = calcMode(e);
		setDropHint(null);
		onReorder({ dragId, dropId: node.id, mode });
	};

	return (
		<div style={{ marginLeft: depth * 20, marginBottom: 10 }} className="jet-menu-tree__node">
			<div
				className={
					"jet-menu-tree__item" +
					(selected ? " is-selected" : "") +
					(dropMode === "child" ? " is-drop-child" : "")
				}
				onClick={() => {
					onSelect(node.id);
					setExpanded((v) => !v);
				}}
				draggable
				onDragStart={onDragStart}
				onDragOver={onDragOver}
				onDragLeave={onDragLeave}
				onDrop={onDrop}
			>
				<div
					className={
						"jet-menu-tree__drop-placeholder" +
						(dropMode === "before" ? " is-before" : "") +
						(dropMode === "after" ? " is-after" : "") +
						(dropMode === "child" ? " is-child" : "")
					}
				/>

				<span
					style={{
						flex: 1,
						minWidth: 0,
						whiteSpace: "nowrap",
						overflow: "hidden",
						textOverflow: "ellipsis",
					}}
				>
          {node.title || "(no title)"}
        </span>

				<Button
					size="compact"
					variant="tertiary"
					onClick={(e) => {
						e.stopPropagation();
						onAddChild(node.id);
					}}
					disabled={busy}
				>
					+ Child
				</Button>
			</div>

			{expanded ? (
				<div className="jet-menu-tree__inline-editor">
					<div className="jet-menu-tree__inline-row">
						<TextControl
							label="Label"
							value={node.title || ""}
							onChange={(v) => onPatchItem(node.id, { title: v })}
							__next40pxDefaultSize
							__nextHasNoMarginBottom
						/>
					</div>

					{node.type === "custom" ? (
						<div className="jet-menu-tree__inline-row">
							<TextControl
								label="URL"
								value={node.url || ""}
								onChange={(v) => onPatchItem(node.id, { url: v })}
								__next40pxDefaultSize
								__nextHasNoMarginBottom
							/>
						</div>
					) : (
						<div className="jet-menu-tree__inline-row">
							<TextControl
								label="URL"
								value={node.url || ""}
								onChange={() => {}}
								disabled
								style={{ opacity: 0.5 }}
								__next40pxDefaultSize
								__nextHasNoMarginBottom
							/>
							<Notice status="warning" isDismissible={false}>
								This item’s URL comes from its source (post/taxonomy). You can change only the label.
							</Notice>
						</div>
					)}

					<div className="jet-menu-tree__inline-actions">
						<div style={{ flex: 1 }}>
							<Button
								variant="secondary"
								onClick={() => onOpenSettingsModal(node.id)}
								icon={ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path d="M18 12h-2.18c-.17.7-.44 1.35-.81 1.93l1.54 1.54-2.1 2.1-1.54-1.54c-.58.36-1.23.63-1.91.79V19H8v-2.18c-.68-.16-1.33-.43-1.91-.79l-1.54 1.54-2.12-2.12 1.54-1.54c-.36-.58-.63-1.23-.79-1.91H1V9.03h2.17c.16-.7.44-1.35.8-1.94L2.43 5.55l2.1-2.1 1.54 1.54c.58-.37 1.24-.64 1.93-.81V2h3v2.18c.68.16 1.33.43 1.91.79l1.54-1.54 2.12 2.12-1.54 1.54c.36.59.64 1.24.8 1.94H18V12zm-8.5 1.5c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/></g></svg> }
								disabled={busy}
							>
								Item settings
							</Button>
						</div>

						<Button
							variant="primary"
							onClick={() => onSaveItem(node.id)}
							disabled={busy}
							icon={ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path d="M17.7 4.3c-.4-.4-1-.4-1.4 0L8 12.59l-3.3-3.3c-.4-.4-1-.4-1.4 0s-.4 1 0 1.4l4 4c.4.4 1 .4 1.4 0l8-8c.4-.4.4-1 0-1.4z"/></g></svg> }
						>
							Save
						</Button>

						<Button
							isDestructive
							variant="tertiary"
							onClick={() => onDeleteItem(node.id)}
							icon={ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="16" height="16"/><g><path d="M12 4h3c.6 0 1 .4 1 1v1H3V5c0-.6.5-1 1-1h3c.2-1.1 1.3-2 2.5-2s2.3.9 2.5 2zM8 4h3c-.2-.6-.9-1-1.5-1S8.2 3.4 8 4zM4 7h11l-.9 10.1c0 .5-.5.9-1 .9H5.9c-.5 0-.9-.4-1-.9L4 7z"/></g></svg> }
							disabled={busy}
						>
							Delete
						</Button>

						<Button
							variant="tertiary"
							onClick={() => setExpanded(false)} disabled={busy}
							icon={ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="16" height="16"/><g><path d="M14.95 6.46L11.41 10l3.54 3.54-1.41 1.41L10 11.42l-3.53 3.53-1.42-1.42L8.58 10 5.05 6.47l1.42-1.42L10 8.58l3.54-3.53z"/></g></svg> }
						>
							Close
						</Button>
					</div>
				</div>
			) : null}

			{node.children?.length
				? node.children.map((ch) => (
					<Node
						key={ch.id}
						node={ch}
						depth={depth + 1}
						selectedId={selectedId}
						onSelect={onSelect}
						onAddChild={onAddChild}
						onReorder={onReorder}
						onPatchItem={onPatchItem}
						onSaveItem={onSaveItem}
						onDeleteItem={onDeleteItem}
						onOpenSettingsModal={onOpenSettingsModal}
						busy={busy}
						dropHint={dropHint}
						setDropHint={setDropHint}
					/>
				))
				: null}
		</div>
	);
}