import React, { useCallback, useEffect, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import type { TerminalRef } from "../components/features/terminal/terminal";
import type { TerminalSessionInfo } from "../components/features/terminal/terminal-session-tabs";
import { useMobileViewport } from "./use-mobile-viewport";
import { useAutoHide } from "./use-auto-hide";
import { useVirtualKeyboard } from "./use-virtual-keyboard";
import { useTerminalSessions } from "./use-terminal-sessions";
import type { TerminalSession } from "../api/terminal";
import type { ModifierKey } from "./use-special-keys";

const SESSIONS_TO_INFO = (sessions: TerminalSession[]): TerminalSessionInfo[] =>
	sessions.map((s) => ({
		id: s.id,
		name: s.name,
		status: s.status as TerminalSessionInfo["status"],
	}));

type TerminalStatus =
	| "connecting"
	| "connected"
	| "disconnected"
	| "error"
	| "resetting";

export const useTerminalPage = () => {
	const { instanceId } = useParams<{ instanceId: string }>();
	const navigate = useNavigate();
	const isMobile = useMobileViewport();
	const [isFullscreen, setIsFullscreen] = useState(false);
	const terminalRefs = useRef<Record<string, React.RefObject<TerminalRef>>>({});
	const headerAutoHide = useAutoHide({ timeout: 3000, enabled: isMobile });

	const [terminalStatuses, setTerminalStatuses] = useState<
		Record<string, TerminalStatus>
	>({});
	const changeFontSizeRef = useRef<((delta: number) => void) | null>(null);
	const sendDataRef = useRef<((data: string) => void) | null>(null);
	const focusInputRef = useRef<(() => void) | null>(null);
	const [showResetConfirm, setShowResetConfirm] = useState(false);
	const [showSpecialKeysPanel, setShowSpecialKeysPanel] = useState(false);
	const [activeModifier, setActiveModifier] = useState<ModifierKey | null>(
		null,
	);
	const { isOpen: isKeyboardOpen, height: keyboardHeight } =
		useVirtualKeyboard();

	const [instanceInfo, setInstanceInfo] = useState<{
		display_name: string;
		workspace_name?: string | null;
		tool_type_name: string;
	} | null>(null);

	const {
		sessions,
		activeSessionId,
		setActiveSessionId,
		createSession,
		closeSession,
		renameSession,
		resetSession,
		loading,
		error,
	} = useTerminalSessions(instanceId ?? "");

	// Fetch instance details for tab title
	useEffect(() => {
		if (!instanceId) return;
		const load = async () => {
			try {
				const { getUserSessions } = await import("../api/sessions");
				const allSessions = await getUserSessions();
				const match = allSessions.find((s) => s.id === instanceId);
				if (match) {
					setInstanceInfo({
						display_name: match.display_name,
						workspace_name: match.workspace_name,
						tool_type_name: match.tool_type_name,
					});
				}
			} catch {
				// ignore
			}
		};
		void load();
	}, [instanceId]);

	// Auto-create default session
	useEffect(() => {
		if (!loading && sessions.length === 0 && !error && instanceId) {
			void createSession("Session 1");
		}
	}, [loading, sessions.length, error, instanceId, createSession]);

	// Update document title based on active terminal session
	useEffect(() => {
		if (!instanceId) {
			document.title = "Terminal";
			return;
		}
		const active = sessions.find((s) => s.id === activeSessionId);
		const baseName = instanceInfo
			? `${instanceInfo.workspace_name ?? instanceInfo.display_name} · ${instanceInfo.tool_type_name}`
			: `Instance ${instanceId.slice(0, 8)}`;
		if (sessions.length <= 1) {
			document.title = baseName;
		} else {
			const sessionName = active?.name ?? "Session";
			document.title = `${baseName} ${sessionName}`;
		}
		return () => {
			document.title = "Headquarter";
		};
	}, [instanceId, activeSessionId, sessions, instanceInfo]);

	// Sync refs with sessions
	useEffect(() => {
		for (const session of sessions) {
			if (!terminalRefs.current[session.id]) {
				terminalRefs.current[session.id] = React.createRef<TerminalRef>();
			}
		}
		const currentIds = new Set(sessions.map((s) => s.id));
		for (const id of Object.keys(terminalRefs.current)) {
			if (!currentIds.has(id)) {
				delete terminalRefs.current[id];
			}
		}
	}, [sessions]);

	// Fit and focus active terminal
	useEffect(() => {
		if (activeSessionId && terminalRefs.current[activeSessionId]) {
			const ref = terminalRefs.current[activeSessionId];
			let raf1 = 0;
			let raf2 = 0;
			raf1 = requestAnimationFrame(() => {
				raf2 = requestAnimationFrame(() => {
					ref.current?.fit();
					ref.current?.focus();
				});
			});
			return () => {
				cancelAnimationFrame(raf1);
				cancelAnimationFrame(raf2);
			};
		}
	}, [activeSessionId]);

	// Keyboard shortcuts
	useEffect(() => {
		const handleKeyDown = (e: KeyboardEvent) => {
			const isAltShift = e.altKey && e.shiftKey && !e.ctrlKey && !e.metaKey;
			if (!isAltShift) return;

			switch (e.key.toLowerCase()) {
				case "n":
					e.preventDefault();
					if (sessions.length < 5) {
						void createSession(`Session ${sessions.length + 1}`);
					}
					break;
				case "w":
					e.preventDefault();
					if (
						activeSessionId &&
						window.confirm("Close this terminal session?")
					) {
						void closeSession(activeSessionId);
					}
					break;
				case "arrowleft":
					e.preventDefault();
					if (activeSessionId) {
						const idx = sessions.findIndex((s) => s.id === activeSessionId);
						if (idx > 0) setActiveSessionId(sessions[idx - 1].id);
					}
					break;
				case "arrowright":
					e.preventDefault();
					if (activeSessionId) {
						const idx = sessions.findIndex((s) => s.id === activeSessionId);
						if (idx < sessions.length - 1)
							setActiveSessionId(sessions[idx + 1].id);
					}
					break;
				case "r":
					e.preventDefault();
					if (activeSessionId) void resetSession(activeSessionId);
					break;
				case "f":
					e.preventDefault();
					setIsFullscreen((prev) => !prev);
					break;
			}
		};

		window.addEventListener("keydown", handleKeyDown);
		return () => window.removeEventListener("keydown", handleKeyDown);
	}, [
		sessions,
		activeSessionId,
		createSession,
		closeSession,
		resetSession,
		setActiveSessionId,
	]);

	// Keep screen awake
	useEffect(() => {
		let wakeLock: WakeLockSentinel | null = null;
		const requestWakeLock = async () => {
			try {
				if ("wakeLock" in navigator) {
					wakeLock = await navigator.wakeLock.request("screen");
				}
			} catch {
				// ignore
			}
		};
		void requestWakeLock();
		const handleVisibilityChange = () => {
			if (document.visibilityState === "visible") void requestWakeLock();
		};
		document.addEventListener("visibilitychange", handleVisibilityChange);
		return () => {
			document.removeEventListener("visibilitychange", handleVisibilityChange);
			wakeLock?.release().catch(() => {});
		};
	}, []);

	// Lock page scroll on mobile
	useEffect(() => {
		if (!isMobile) return;
		document.documentElement.classList.add("terminal-page-open");
		document.body.classList.add("terminal-page-open");
		return () => {
			document.documentElement.classList.remove("terminal-page-open");
			document.body.classList.remove("terminal-page-open");
		};
	}, [isMobile]);

	const handleFullscreenClick = useCallback(
		(e: React.MouseEvent<HTMLElement>) => {
			if (!isFullscreen) return;
			const target = e.target as Node;
			const current = e.currentTarget as HTMLElement;
			const content = current.querySelector(".terminal-page-content");
			const header = current.querySelector(".terminal-fullscreen-header");
			if (content?.contains(target) || header?.contains(target)) return;
			setIsFullscreen(false);
		},
		[isFullscreen],
	);

	const handleSelect = useCallback(
		(sessionId: string) => setActiveSessionId(sessionId),
		[setActiveSessionId],
	);

	const handleClose = useCallback(
		async (sessionId: string) => closeSession(sessionId),
		[closeSession],
	);

	const handleCreate = useCallback(() => {
		void createSession(`Session ${sessions.length + 1}`);
	}, [createSession, sessions.length]);

	const handleRename = useCallback(
		(sessionId: string, newName: string) => {
			void renameSession(sessionId, newName);
		},
		[renameSession],
	);

	const handleTerminalReady = useCallback(
		(
			sendData: (data: string) => void,
			status: TerminalStatus,
			focusInput: () => void,
			changeFontSize: (delta: number) => void,
		) => {
			setTerminalStatuses((prev) => ({
				...prev,
				[activeSessionId ?? "default"]: status,
			}));
			sendDataRef.current = sendData;
			focusInputRef.current = focusInput;
			changeFontSizeRef.current = changeFontSize;
		},
		[activeSessionId],
	);

	const handleFontSizeChange = useCallback((delta: number) => {
		changeFontSizeRef.current?.(delta);
	}, []);

	const handleSendKey = useCallback((data: string) => {
		sendDataRef.current?.(data);
	}, []);

	const handleReset = useCallback(() => {
		if (activeSessionId && terminalRefs.current[activeSessionId]) {
			terminalRefs.current[activeSessionId].current?.reset();
		}
	}, [activeSessionId]);

	return {
		instanceId,
		navigate,
		isMobile,
		isFullscreen,
		setIsFullscreen,
		terminalRefs,
		headerAutoHide,
		terminalStatuses,
		sendDataRef,
		focusInputRef,
		changeFontSizeRef,
		showResetConfirm,
		setShowResetConfirm,
		showSpecialKeysPanel,
		setShowSpecialKeysPanel,
		activeModifier,
		setActiveModifier,
		isKeyboardOpen,
		keyboardHeight,
		sessions,
		activeSessionId,
		setActiveSessionId,
		loading,
		error,
		handleFullscreenClick,
		handleSelect,
		handleClose,
		handleCreate,
		handleRename,
		handleTerminalReady,
		handleFontSizeChange,
		handleSendKey,
		handleReset,
		sessionInfos: SESSIONS_TO_INFO(sessions),
	};
};
