import { useEffect, useState } from "react";
import { Link, Outlet, useLocation, useOutletContext } from "react-router-dom";

import {
	getUserConfig,
	updateUserConfig,
	type UserConfig,
	type UserConfigUpdate,
} from "../api/settings";
import { ErrorState, LoadingState } from "../components/data-states";
import { Icon } from "../components/icon";
import { useAsyncData } from "../hooks/use-async-data";

const TABS = [
	{ label: "General", path: "general" },
	{ label: "SSH Keys", path: "ssh-keys" },
] as const;

const THEME_OPTIONS = [
	{ value: "system", label: "System" },
	{ value: "light", label: "Light" },
	{ value: "dark", label: "Dark" },
];

const TOAST_LEVEL_OPTIONS = [
	{ value: "all", label: "All" },
	{ value: "errors", label: "Errors only" },
	{ value: "none", label: "None" },
];

const MUTE_CATEGORIES = ["instance", "system", "health", "security"];

type SettingsOutletContext = {
	config: UserConfig;
	handleChange: (
		key: keyof UserConfigUpdate,
		value: string | string[] | null,
	) => void;
	handleSave: () => Promise<void>;
	saveStatus: "idle" | "saving" | "saved" | "error";
};

export const SettingsPage = () => {
	const location = useLocation();
	const {
		data: loadedConfig,
		status,
		reload,
	} = useAsyncData<UserConfig>(getUserConfig, []);
	const [config, setConfig] = useState<UserConfig>({
		theme: "system",
		default_editor: null,
		git_user_name: null,
		git_user_email: null,
		last_session_id: null,
		notification_toast_level: "all",
		notification_mute_categories: [],
	});
	const [saveStatus, setSaveStatus] = useState<
		"idle" | "saving" | "saved" | "error"
	>("idle");

	// Sync loaded config into local editable state
	useEffect(() => {
		if (loadedConfig) {
			setConfig({
				...loadedConfig,
				notification_toast_level:
					loadedConfig.notification_toast_level ?? "all",
				notification_mute_categories:
					loadedConfig.notification_mute_categories ?? [],
			});
		}
	}, [loadedConfig]);

	const handleChange = (
		key: keyof UserConfigUpdate,
		value: string | string[] | null,
	) => {
		setConfig((prev) => ({ ...prev, [key]: value }) as UserConfig);
		setSaveStatus("idle");
	};

	const handleSave = async () => {
		setSaveStatus("saving");
		try {
			const update: UserConfigUpdate = {
				theme: config.theme,
				default_editor: config.default_editor,
				git_user_name: config.git_user_name,
				git_user_email: config.git_user_email,
				notification_toast_level: config.notification_toast_level,
				notification_mute_categories: config.notification_mute_categories,
			};
			const updated = await updateUserConfig(update);
			setConfig(updated);
			window.dispatchEvent(
				new CustomEvent("userconfig:updated", { detail: updated }),
			);
			setSaveStatus("saved");
			if (updated.theme === "system") {
				document.documentElement.removeAttribute("data-theme");
			} else {
				document.documentElement.setAttribute("data-theme", updated.theme);
			}
			window.setTimeout(() => setSaveStatus("idle"), 2000);
		} catch {
			setSaveStatus("error");
		}
	};

	if (status === "loading") {
		return (
			<section className="stack">
				<LoadingState message="Loading settings..." />
			</section>
		);
	}

	if (status === "error") {
		return (
			<section className="stack">
				<ErrorState message="Failed to load settings" onRetry={reload} />
			</section>
		);
	}

	const parts = location.pathname.split("/").filter(Boolean);
	const activePath = location.pathname.endsWith("/settings")
		? "general"
		: (parts[parts.length - 1] ?? "general");

	return (
		<section className="stack settings-page">
			<header className="settings-header card stack-sm">
				<div>
					<p className="eyebrow">Configuration</p>
					<h1>Settings</h1>
				</div>
				<p className="muted">
					General preferences, SSH keys, and config profiles.
				</p>
			</header>

			<nav className="settings-tabs" aria-label="Settings sections">
				{TABS.map((tab) => (
					<Link
						key={tab.path}
						className={`settings-tab ${activePath === tab.path ? "active" : ""}`}
						to={tab.path === "general" ? "/settings" : `/settings/${tab.path}`}
					>
						{tab.label}
					</Link>
				))}
			</nav>

			<div className="settings-panel card">
				<Outlet context={{ config, handleChange, handleSave, saveStatus }} />
			</div>
		</section>
	);
};

export const GeneralSettingsTab = () => {
	const { config, handleChange, handleSave, saveStatus } =
		useOutletContext<SettingsOutletContext>();

	return (
		<div className="stack">
			<h2>General</h2>
			<label className="form-field">
				Theme
				<select
					value={config.theme}
					onChange={(e) => handleChange("theme", e.target.value)}
				>
					{THEME_OPTIONS.map((opt) => (
						<option key={opt.value} value={opt.value}>
							{opt.label}
						</option>
					))}
				</select>
			</label>
			<label className="form-field">
				Git user name
				<input
					type="text"
					value={config.git_user_name ?? ""}
					onChange={(e) =>
						handleChange("git_user_name", e.target.value || null)
					}
					placeholder="Your git commit name"
				/>
			</label>
			<label className="form-field">
				Git user email
				<input
					type="email"
					value={config.git_user_email ?? ""}
					onChange={(e) =>
						handleChange("git_user_email", e.target.value || null)
					}
					placeholder="your.email@example.com"
				/>
			</label>
			<label className="form-field">
				Default editor
				<input
					type="text"
					value={config.default_editor ?? ""}
					onChange={(e) =>
						handleChange("default_editor", e.target.value || null)
					}
					placeholder="e.g., vscode, vim, cursor"
				/>
			</label>
			<h3>Notifications</h3>
			<label className="form-field">
				Toast level
				<select
					value={config.notification_toast_level ?? "all"}
					onChange={(e) =>
						handleChange("notification_toast_level", e.target.value)
					}
				>
					{TOAST_LEVEL_OPTIONS.map((opt) => (
						<option key={opt.value} value={opt.value}>
							{opt.label}
						</option>
					))}
				</select>
			</label>
			<fieldset className="form-field">
				<legend>Mute categories</legend>
				<div className="stack-sm">
					{MUTE_CATEGORIES.map((cat) => (
						<label
							key={cat}
							style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}
						>
							<input
								type="checkbox"
								checked={(config.notification_mute_categories ?? []).includes(
									cat,
								)}
								onChange={(e) => {
									const current = config.notification_mute_categories ?? [];
									const next = e.target.checked
										? [...current, cat]
										: current.filter((c) => c !== cat);
									handleChange("notification_mute_categories", next);
								}}
							/>
							{cat}
						</label>
					))}
				</div>
			</fieldset>
			<div className="settings-actions">
				<button
					className="primary-button"
					onClick={() => void handleSave()}
					type="button"
				>
					{saveStatus === "saving" ? (
						<>
							<Icon name="loading" size="sm" /> Saving...
						</>
					) : (
						<>
							<Icon name="save" size="sm" /> Save Settings
						</>
					)}
				</button>
				{saveStatus === "saved" && (
					<span className="success-text">Settings saved!</span>
				)}
				{saveStatus === "error" && (
					<span className="error-text">Failed to save</span>
				)}
			</div>
		</div>
	);
};
