"use client";

import { useEffect, useState, useRef, useCallback } from "react";
import { FileManagerTree, type TreeNode } from "./file-manager-tree";
import { ProfileSwitcher } from "./profile-switcher";
import { CreateWorkspaceDialog } from "./create-workspace-dialog";
import { UnicodeSpinner } from "../unicode-spinner";

/** Shape returned by /api/workspace/suggest-files */
type SuggestItem = {
	name: string;
	path: string;
	type: "folder" | "file" | "document" | "database";
};

type WorkspaceSidebarProps = {
	tree: TreeNode[];
	activePath: string | null;
	onSelect: (node: TreeNode) => void;
	onRefresh: () => void;
	orgName?: string;
	loading?: boolean;
	/** Current browse directory (absolute path), or null when in workspace mode. */
	browseDir?: string | null;
	/** Parent directory for ".." navigation. Null at filesystem root or when browsing is unavailable. */
	parentDir?: string | null;
	/** Navigate up one directory. */
	onNavigateUp?: () => void;
	/** Return to workspace mode from browse mode. */
	onGoHome?: () => void;
	/** Called when a file/folder is selected from the search dropdown. */
	onFileSearchSelect?: (item: SuggestItem) => void;
	/** Absolute path of the workspace root folder, used to render it as a special entry in browse mode. */
	workspaceRoot?: string | null;
	/** Navigate to the main chat / home panel. */
	onGoToChat?: () => void;
	/** Called when a tree node is dragged and dropped onto an external target (e.g. chat input). */
	onExternalDrop?: (node: TreeNode) => void;
	/** When true, renders as a mobile overlay drawer instead of a static sidebar. */
	mobile?: boolean;
	/** Close the mobile drawer. */
	onClose?: () => void;
	/** Active workspace profile name (null = default). */
	activeProfile?: string | null;
	/** Fixed width in px when not mobile (overrides default 260). */
	width?: number;
	/** Called after the user switches to a different profile. */
	onProfileSwitch?: () => void;
	/** Whether hidden (dot) files/folders are currently shown. */
	showHidden?: boolean;
	/** Toggle hidden files visibility. */
	onToggleHidden?: () => void;
	/** Called when the user clicks the collapse/hide sidebar button. */
	onCollapse?: () => void;
};

function HomeIcon() {
	return (
		<svg
			width="16"
			height="16"
			viewBox="0 0 24 24"
			fill="none"
			stroke="currentColor"
			strokeWidth="2"
			strokeLinecap="round"
			strokeLinejoin="round"
		>
			<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
			<polyline points="9 22 9 12 15 12 15 22" />
		</svg>
	);
}

function FolderOpenIcon() {
	return (
		<img
			src="/icons/folder-open.png"
			alt=""
			width={20}
			height={20}
			draggable={false}
			style={{ flexShrink: 0 }}
		/>
	);
}

/* ─── Theme toggle ─── */

function ThemeToggle() {
	const [isDark, setIsDark] = useState(false);

	useEffect(() => {
		setIsDark(document.documentElement.classList.contains("dark"));
	}, []);

	const toggle = () => {
		const next = !isDark;
		setIsDark(next);
		if (next) {
			document.documentElement.classList.add("dark");
			localStorage.setItem("theme", "dark");
		} else {
			document.documentElement.classList.remove("dark");
			localStorage.setItem("theme", "light");
		}
	};

	return (
		<button
			type="button"
			onClick={toggle}
			className="p-1.5 rounded-lg"
			style={{ color: "var(--color-text-muted)" }}
			title={isDark ? "Switch to light mode" : "Switch to dark mode"}
		>
			{isDark ? (
				/* Sun icon */
				<svg
					width="16"
					height="16"
					viewBox="0 0 24 24"
					fill="none"
					stroke="currentColor"
					strokeWidth="2"
					strokeLinecap="round"
					strokeLinejoin="round"
				>
					<circle cx="12" cy="12" r="4" />
					<path d="M12 2v2" />
					<path d="M12 20v2" />
					<path d="m4.93 4.93 1.41 1.41" />
					<path d="m17.66 17.66 1.41 1.41" />
					<path d="M2 12h2" />
					<path d="M20 12h2" />
					<path d="m6.34 17.66-1.41 1.41" />
					<path d="m19.07 4.93-1.41 1.41" />
				</svg>
			) : (
				/* Moon icon */
				<svg
					width="16"
					height="16"
					viewBox="0 0 24 24"
					fill="none"
					stroke="currentColor"
					strokeWidth="2"
					strokeLinecap="round"
					strokeLinejoin="round"
				>
					<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" />
				</svg>
			)}
		</button>
	);
}

function SearchIcon() {
	return (
		<svg
			width="14"
			height="14"
			viewBox="0 0 24 24"
			fill="none"
			stroke="currentColor"
			strokeWidth="2"
			strokeLinecap="round"
			strokeLinejoin="round"
		>
			<circle cx="11" cy="11" r="8" />
			<path d="m21 21-4.3-4.3" />
		</svg>
	);
}

function SmallFolderIcon() {
	return (
		<img
			src="/icons/folder.png"
			alt=""
			width={14}
			height={14}
			draggable={false}
			style={{ flexShrink: 0 }}
		/>
	);
}

function SmallFileIcon() {
	return (
		<img src="/icons/document.png" alt="" width={14} height={14} draggable={false} style={{ flexShrink: 0, filter: "drop-shadow(0 0.5px 1.5px rgba(0,0,0,0.2))" }} />
	);
}

function SmallDocIcon() {
	return (
		<img src="/icons/document.png" alt="" width={14} height={14} draggable={false} style={{ flexShrink: 0, filter: "drop-shadow(0 0.5px 1.5px rgba(0,0,0,0.2))" }} />
	);
}

function SmallDbIcon() {
	return (
		<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
			<ellipse cx="12" cy="5" rx="9" ry="3" /><path d="M3 5V19A9 3 0 0 0 21 19V5" /><path d="M3 12A9 3 0 0 0 21 12" />
		</svg>
	);
}

function SuggestTypeIcon({ type }: { type: string }) {
	switch (type) {
		case "folder": return <SmallFolderIcon />;
		case "document": return <SmallDocIcon />;
		case "database": return <SmallDbIcon />;
		default: return <SmallFileIcon />;
	}
}

/* ─── File search ─── */

function FileSearch({ onSelect }: { onSelect: (item: SuggestItem) => void }) {
	const [query, setQuery] = useState("");
	const [results, setResults] = useState<SuggestItem[]>([]);
	const [open, setOpen] = useState(false);
	const [loading, setLoading] = useState(false);
	const [selectedIndex, setSelectedIndex] = useState(0);
	const inputRef = useRef<HTMLInputElement>(null);
	const containerRef = useRef<HTMLDivElement>(null);

	// Debounced fetch from the same suggest-files API that tiptap uses
	useEffect(() => {
		if (!query.trim()) {
			setResults([]);
			setOpen(false);
			return;
		}

		setLoading(true);
		const timer = setTimeout(async () => {
			try {
				const res = await fetch(
					`/api/workspace/suggest-files?q=${encodeURIComponent(query.trim())}`,
				);
				const data = await res.json();
				setResults(data.items ?? []);
				setOpen(true);
				setSelectedIndex(0);
			} catch {
				setResults([]);
			} finally {
				setLoading(false);
			}
		}, 150);

		return () => clearTimeout(timer);
	}, [query]);

	// Click outside to close
	useEffect(() => {
		function handleClickOutside(e: MouseEvent) {
			if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
				setOpen(false);
			}
		}
		document.addEventListener("mousedown", handleClickOutside);
		return () => document.removeEventListener("mousedown", handleClickOutside);
	}, []);

	const handleKeyDown = useCallback(
		(e: React.KeyboardEvent) => {
			if (e.key === "ArrowDown") {
				e.preventDefault();
				setSelectedIndex((i) => Math.min(i + 1, results.length - 1));
			} else if (e.key === "ArrowUp") {
				e.preventDefault();
				setSelectedIndex((i) => Math.max(i - 1, 0));
			} else if (e.key === "Enter" && results[selectedIndex]) {
				e.preventDefault();
				onSelect(results[selectedIndex]);
				setQuery("");
				setOpen(false);
				inputRef.current?.blur();
			} else if (e.key === "Escape") {
				setOpen(false);
				setQuery("");
				inputRef.current?.blur();
			}
		},
		[results, selectedIndex, onSelect],
	);

	const handleSelect = useCallback(
		(item: SuggestItem) => {
			onSelect(item);
			setQuery("");
			setOpen(false);
		},
		[onSelect],
	);

	return (
		<div ref={containerRef} className="relative px-3 pt-2 pb-1">
			<div className="relative">
				<span
					className="absolute left-2.5 top-1/2 -translate-y-1/2 pointer-events-none"
					style={{ color: "var(--color-text-muted)" }}
				>
					<SearchIcon />
				</span>
				<input
					ref={inputRef}
					type="text"
					value={query}
					onChange={(e) => setQuery(e.target.value)}
					onKeyDown={handleKeyDown}
					onFocus={() => { if (results.length > 0) {setOpen(true);} }}
					placeholder="Search files..."
					className="w-full pl-8 pr-3 py-1.5 rounded-lg text-xs outline-none transition-colors"
					style={{
						background: "var(--color-bg)",
						color: "var(--color-text)",
						border: "1px solid var(--color-border)",
					}}
				/>
				{loading && (
					<span className="absolute right-2.5 top-1/2 -translate-y-1/2">
						<UnicodeSpinner
							name="braille"
							className="text-sm"
							style={{ color: "var(--color-text-muted)" }}
						/>
					</span>
				)}
			</div>

			{open && results.length > 0 && (
				<div
					className="absolute left-3 right-3 mt-1 rounded-lg shadow-lg border overflow-hidden z-50 max-h-[300px] overflow-y-auto"
					style={{ background: "var(--color-surface)", borderColor: "var(--color-border)" }}
				>
					{results.map((item, i) => (
						<button
							key={item.path}
							type="button"
							onClick={() => handleSelect(item)}
							className="w-full flex items-center gap-2 px-3 py-2 text-left text-xs cursor-pointer transition-colors"
							style={{
								background: i === selectedIndex ? "var(--color-surface-hover)" : "transparent",
								color: "var(--color-text)",
							}}
							onMouseEnter={() => setSelectedIndex(i)}
						>
							<span className="flex-shrink-0" style={{ color: "var(--color-text-muted)" }}>
								<SuggestTypeIcon type={item.type} />
							</span>
							<div className="min-w-0 flex-1">
								<div className="truncate font-medium">{item.name}</div>
								<div className="truncate" style={{ color: "var(--color-text-muted)", fontSize: "10px" }}>
									{item.path.split("/").slice(0, -1).join("/")}
								</div>
							</div>
							<span
								className="text-[10px] px-1.5 py-0.5 rounded-full flex-shrink-0 capitalize"
								style={{ background: "var(--color-surface-hover)", color: "var(--color-text-muted)" }}
							>
								{item.type}
							</span>
						</button>
					))}
				</div>
			)}

			{open && query.trim() && !loading && results.length === 0 && (
				<div
					className="absolute left-3 right-3 mt-1 rounded-lg shadow-lg border z-50 px-3 py-3 text-center"
					style={{ background: "var(--color-surface)", borderColor: "var(--color-border)" }}
				>
					<p className="text-xs" style={{ color: "var(--color-text-muted)" }}>
						No files found
					</p>
				</div>
			)}
		</div>
	);
}

/** Extract the directory name from an absolute path for display. */
function dirDisplayName(dir: string): string {
	if (dir === "/") {return "/";}
	return dir.split("/").pop() || dir;
}

export function WorkspaceSidebar({
	tree,
	activePath,
	onSelect,
	onRefresh,
	orgName,
	loading,
	browseDir,
	parentDir,
	onNavigateUp,
	onGoHome,
	onFileSearchSelect,
	workspaceRoot,
	onGoToChat,
	onExternalDrop,
	mobile,
	onClose,
	activeProfile,
	onProfileSwitch,
	showHidden,
	onToggleHidden,
	width: widthProp,
	onCollapse,
}: WorkspaceSidebarProps) {
	const isBrowsing = browseDir != null;
	const [showCreateWorkspace, setShowCreateWorkspace] = useState(false);
	const width = mobile ? "280px" : (widthProp ?? 260);

	const sidebar = (
		<aside
			className={`flex flex-col h-screen shrink-0 ${mobile ? "drawer-left" : "border-r"}`}
			style={{
				width: typeof width === "number" ? `${width}px` : width,
				minWidth: typeof width === "number" ? `${width}px` : width,
				background: "var(--color-sidebar-bg)",
				borderColor: "var(--color-border)",
			}}
		>
			{/* Header */}
			<div
				className="flex items-center gap-2 px-3 py-2.5 border-b"
				style={{ borderColor: "var(--color-border)" }}
			>
				{isBrowsing ? (
					<>
						<span
							className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0"
							style={{
								background: "var(--color-surface-hover)",
								color: "var(--color-text-muted)",
							}}
						>
							<FolderOpenIcon />
						</span>
						<div className="flex-1 min-w-0">
							<div
								className="text-sm font-medium truncate"
								style={{ color: "var(--color-text)" }}
								title={browseDir}
							>
								{dirDisplayName(browseDir)}
							</div>
							<div
								className="text-[11px] truncate"
								style={{
									color: "var(--color-text-muted)",
								}}
								title={browseDir}
							>
								{browseDir}
							</div>
						</div>
						{/* Home button to return to workspace */}
						{onGoHome && (
							<button
								type="button"
								onClick={onGoHome}
								className="p-1.5 rounded-lg flex-shrink-0"
								style={{ color: "var(--color-text-muted)" }}
								title="Return to workspace"
							>
								<HomeIcon />
							</button>
						)}
					</>
				) : (
					<>
						<button
							type="button"
							onClick={() => void onGoToChat?.()}
							className="w-7 h-7 rounded-lg flex items-center justify-center shrink-0 cursor-pointer transition-colors hover:bg-stone-200 dark:hover:bg-stone-700"
							style={{
								background: "transparent",
								color: "var(--color-text-muted)",
							}}
							title="All Chats"
						>
							<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
								<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
								<polyline points="9 22 9 12 15 12 15 22" />
							</svg>
						</button>
						<ProfileSwitcher
							onProfileSwitch={onProfileSwitch}
							onCreateWorkspace={() => setShowCreateWorkspace(true)}
							activeProfileHint={activeProfile}
							trigger={({ isOpen, onClick, activeProfile: profileName, switching }) => (
								<button
									type="button"
									onClick={onClick}
									disabled={switching}
									className="flex-1 min-w-0 w-full flex items-center justify-between gap-1.5 text-left rounded-lg py-1 px-1.5 transition-colors hover:bg-stone-100 dark:hover:bg-stone-800 disabled:opacity-50"
									title="Switch workspace profile"
								>
									<div className="min-w-0 truncate">
										<div
											className="text-[13px] font-semibold truncate text-stone-700 dark:text-stone-200"
										>
											{orgName || "Workspace"}
										</div>
										<div
											className="text-[11px] flex items-center gap-1 truncate text-stone-400 dark:text-stone-500"
										>
											<span>Ironclaw</span>
											{profileName && profileName !== "default" && (
												<span
													className="px-1 py-0.5 rounded text-[10px] shrink-0 bg-stone-200 text-stone-500 dark:bg-stone-700 dark:text-stone-400"
												>
													{profileName}
												</span>
											)}
										</div>
									</div>
									<svg
										className={`w-3 h-3 shrink-0 transition-transform text-stone-400 ${isOpen ? "rotate-180" : ""}`}
										fill="none"
										stroke="currentColor"
										viewBox="0 0 24 24"
									>
										<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
									</svg>
								</button>
							)}
						/>
					</>
				)}
				{onCollapse && (
					<button
						type="button"
						onClick={onCollapse}
						className="p-1 rounded-md shrink-0 transition-colors hover:bg-stone-200 dark:hover:bg-stone-700"
						style={{ color: "var(--color-text-muted)" }}
						title="Hide sidebar (⌘B)"
					>
						<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
							<rect width="18" height="18" x="3" y="3" rx="2" />
							<path d="M9 3v18" />
						</svg>
					</button>
				)}
			</div>

			{/* Create workspace dialog */}
			<CreateWorkspaceDialog
				isOpen={showCreateWorkspace}
				onClose={() => setShowCreateWorkspace(false)}
				onCreated={onProfileSwitch}
			/>

			{/* File search */}
			{onFileSearchSelect && (
				<FileSearch onSelect={onFileSearchSelect} />
			)}

			{/* Tree */}
			<div className="flex-1 overflow-y-auto px-1">
				{loading ? (
					<div className="flex items-center justify-center py-12">
						<UnicodeSpinner
							name="braille"
							className="text-2xl"
							style={{ color: "var(--color-text-muted)" }}
						/>
					</div>
				) : (
			<FileManagerTree
				tree={tree}
				activePath={activePath}
				onSelect={onSelect}
				onRefresh={onRefresh}
				parentDir={parentDir}
				onNavigateUp={onNavigateUp}
				browseDir={browseDir}
				workspaceRoot={workspaceRoot}
				onExternalDrop={onExternalDrop}
			/>
				)}
			</div>

			{/* Footer */}
			<div
				className="px-3 py-2.5 border-t flex items-center justify-between"
				style={{ borderColor: "var(--color-border)" }}
			>
				<a
					href="https://ironclaw.sh"
					target="_blank"
					rel="noopener noreferrer"
					className="flex items-center gap-2 px-2 py-1.5 rounded-lg text-sm"
					style={{ color: "var(--color-text-muted)" }}
				>
					ironclaw.sh
				</a>
				<div className="flex items-center gap-0.5">
					{onToggleHidden && (
						<button
							type="button"
							onClick={onToggleHidden}
							className="p-1.5 rounded-lg transition-colors"
							style={{ color: showHidden ? "var(--color-accent)" : "var(--color-text-muted)" }}
							title={showHidden ? "Hide dotfiles" : "Show dotfiles"}
						>
							<svg
								width="16"
								height="16"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								strokeWidth="2"
								strokeLinecap="round"
								strokeLinejoin="round"
							>
								{showHidden ? (
									<>
										<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" />
										<circle cx="12" cy="12" r="3" />
									</>
								) : (
									<>
										<path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" />
										<path d="M14.084 14.158a3 3 0 0 1-4.242-4.242" />
										<path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" />
										<path d="m2 2 20 20" />
									</>
								)}
							</svg>
						</button>
					)}
					<ThemeToggle />
				</div>
			</div>
		</aside>
	);

    if (!mobile) { return sidebar; }

	return (
		<div className="drawer-backdrop" onClick={() => void onClose?.()}>
			{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
			<div onClick={(e) => e.stopPropagation()} className="fixed inset-y-0 left-0 z-50">
				{sidebar}
			</div>
		</div>
	);
}
