import * as React from "react";
import type { OAuthStatus } from "./api/client";
import { api } from "./api/client";
import { Chat } from "./components/Chat";
import { GatewayPanel } from "./components/GatewayPanel";
import { SelectionScreen } from "./components/selection/SelectionScreen";
import { usePathCompletion } from "./components/selection/usePathCompletion";
import { gatewayApi } from "./api/gateway";
import "./App.css";

function App() {
	const [isGateway, setIsGateway] = React.useState<boolean | null>(null);
	const [projectPath, setProjectPath] = React.useState<string | null>(null);
	const [_view, setView] = React.useState<"chat" | "token-usage">("chat");
	const [isCheckingProject, setIsCheckingProject] = React.useState(true);
	const [errorMsg, setErrorMsg] = React.useState<string | null>(null);
	const [pathInput, setPathInput] = React.useState("");
	const [isOpening, setIsOpening] = React.useState(false);
	const [knownProjects, setKnownProjects] = React.useState<string[]>([]);
	const [homeDir, setHomeDir] = React.useState<string | null>(null);
	const [oauthStatus, setOauthStatus] = React.useState<OAuthStatus | null>(
		null,
	);

	// Detect gateway mode on startup — if /gateway/mode returns 200, we're a gateway.
	React.useEffect(() => {
		gatewayApi
			.getServerMode()
			.then((result) => setIsGateway(result.mode === "gateway"))
			.catch(() => setIsGateway(false));
	}, []);

	React.useEffect(() => {
		if (isGateway === null || isGateway) return;
		let active = true;
		function fetchOAuthStatus() {
			api
				.getOAuthStatus()
				.then((s) => {
					if (active) setOauthStatus(s);
				})
				.catch(() => {});
		}
		fetchOAuthStatus();
		const intervalId = window.setInterval(fetchOAuthStatus, 5000);
		return () => {
			active = false;
			window.clearInterval(intervalId);
		};
	}, [isGateway]);

	React.useEffect(() => {
		if (isGateway === null) return;
		if (isGateway) {
			setIsCheckingProject(false);
			return;
		}
		api
			.getCurrentProject()
			.then((path) => {
				if (path) {
					setProjectPath(path);
				}
			})
			.catch((error) => console.error(error))
			.finally(() => {
				setIsCheckingProject(false);
			});
	}, [isGateway]);

	React.useEffect(() => {
		if (projectPath) {
			const projectName =
				projectPath.replace(/\\/g, "/").split("/").filter(Boolean).pop() ??
				projectPath;
			document.title = `${projectName} | Huskies`;
		} else {
			document.title = "Huskies";
		}
	}, [projectPath]);

	React.useEffect(() => {
		if (isGateway === null || isGateway) return;
		api
			.getKnownProjects()
			.then((projects) => setKnownProjects(projects))
			.catch((error) => console.error(error));
	}, [isGateway]);

	React.useEffect(() => {
		if (isGateway === null || isGateway) return;
		let active = true;
		api
			.getHomeDirectory()
			.then((home) => {
				if (!active) return;
				setHomeDir(home);
				setPathInput((current) => {
					if (current.trim()) {
						return current;
					}
					const initial = home.endsWith("/") ? home : `${home}/`;
					return initial;
				});
			})
			.catch((error) => {
				console.error(error);
			});

		return () => {
			active = false;
		};
	}, [isGateway]);

	const {
		matchList,
		selectedMatch,
		suggestionTail,
		completionError,
		currentPartial,
		setSelectedMatch,
		acceptSelectedMatch,
		acceptMatch,
		closeSuggestions,
	} = usePathCompletion({
		pathInput,
		setPathInput,
		homeDir,
		listDirectoryAbsolute: api.listDirectoryAbsolute,
	});

	async function openProject(path: string) {
		const trimmedPath = path.trim();
		if (!trimmedPath) {
			setErrorMsg("Please enter a project path.");
			return;
		}

		try {
			setErrorMsg(null);
			setIsOpening(true);
			const confirmedPath = await api.openProject(trimmedPath);
			setProjectPath(confirmedPath);
		} catch (e) {
			console.error(e);
			const message =
				e instanceof Error
					? e.message
					: typeof e === "string"
						? e
						: "An error occurred opening the project.";

			setErrorMsg(message);
		} finally {
			setIsOpening(false);
		}
	}

	function handleOpen() {
		void openProject(pathInput);
	}

	async function handleForgetProject(path: string) {
		try {
			await api.forgetKnownProject(path);
			setKnownProjects((prev) => prev.filter((p) => p !== path));
		} catch (error) {
			console.error(error);
		}
	}

	async function closeProject() {
		try {
			await api.closeProject();
			setProjectPath(null);
			setView("chat");
		} catch (e) {
			console.error(e);
		}
	}

	function handlePathInputKeyDown(
		event: React.KeyboardEvent<HTMLInputElement>,
	) {
		if (event.key === "ArrowDown") {
			if (matchList.length > 0) {
				event.preventDefault();
				setSelectedMatch((selectedMatch + 1) % matchList.length);
			}
		} else if (event.key === "ArrowUp") {
			if (matchList.length > 0) {
				event.preventDefault();
				setSelectedMatch(
					(selectedMatch - 1 + matchList.length) % matchList.length,
				);
			}
		} else if (event.key === "Tab") {
			if (matchList.length > 0) {
				event.preventDefault();
				acceptSelectedMatch();
			}
		} else if (event.key === "Escape") {
			event.preventDefault();
			closeSuggestions();
		} else if (event.key === "Enter") {
			handleOpen();
		}
	}

	// Still probing server mode — wait before rendering.
	if (isGateway === null || isCheckingProject) {
		return null;
	}

	// Gateway mode: render the agent management UI instead of the normal chat.
	if (isGateway) {
		return <GatewayPanel />;
	}

	return (
		<main
			className="container"
			style={{ height: "100vh", padding: 0, maxWidth: "100%" }}
		>
			{!projectPath ? (
				<SelectionScreen
					knownProjects={knownProjects}
					onOpenProject={openProject}
					onForgetProject={handleForgetProject}
					pathInput={pathInput}
					homeDir={homeDir}
					onPathInputChange={setPathInput}
					onPathInputKeyDown={handlePathInputKeyDown}
					isOpening={isOpening}
					suggestionTail={suggestionTail}
					matchList={matchList}
					selectedMatch={selectedMatch}
					onSelectMatch={setSelectedMatch}
					onAcceptMatch={acceptMatch}
					onCloseSuggestions={closeSuggestions}
					completionError={completionError}
					currentPartial={currentPartial}
					oauthStatus={oauthStatus}
				/>
			) : (
				<div className="workspace" style={{ height: "100%" }}>
					<Chat
						projectPath={projectPath}
						onCloseProject={closeProject}
						oauthStatus={oauthStatus}
					/>
				</div>
			)}

			{errorMsg && (
				<div className="error-message" style={{ marginTop: "20px" }}>
					<p style={{ color: "red" }}>Error: {errorMsg}</p>
				</div>
			)}
		</main>
	);
}

export default App;
