import { createFileRoute, Link } from "@tanstack/react-router";
import { useRef, useState } from "react";
import {
	useApiKeys,
	useAuth,
	useChangePassword,
	useCreateApiKey,
	useDeleteApiKey,
} from "../hooks/useAuth";
import { useCurrency } from "../hooks/useCurrency";
import { useExportItems, useImportItems } from "../hooks/useItems";
import { useUpdateSetting } from "../hooks/useSettings";
import { useWeightUnit } from "../hooks/useWeightUnit";
import type { Currency, WeightUnit } from "../lib/formatters";

const UNITS: WeightUnit[] = ["g", "oz", "lb", "kg"];
const CURRENCIES: { value: Currency; label: string }[] = [
	{ value: "USD", label: "$" },
	{ value: "EUR", label: "€" },
	{ value: "GBP", label: "£" },
	{ value: "JPY", label: "¥" },
	{ value: "CAD", label: "CA$" },
	{ value: "AUD", label: "A$" },
];

export const Route = createFileRoute("/settings")({
	component: SettingsPage,
});

function ChangePasswordSection() {
	const changePassword = useChangePassword();
	const [currentPassword, setCurrentPassword] = useState("");
	const [newPassword, setNewPassword] = useState("");
	const [message, setMessage] = useState<{
		type: "success" | "error";
		text: string;
	} | null>(null);

	async function handleSubmit(e: React.FormEvent) {
		e.preventDefault();
		setMessage(null);
		try {
			await changePassword.mutateAsync({ currentPassword, newPassword });
			setMessage({ type: "success", text: "Password changed" });
			setCurrentPassword("");
			setNewPassword("");
		} catch (err) {
			setMessage({ type: "error", text: (err as Error).message });
		}
	}

	return (
		<form onSubmit={handleSubmit} className="space-y-3">
			<h3 className="text-sm font-medium text-gray-900">Change Password</h3>
			<input
				type="password"
				placeholder="Current password"
				value={currentPassword}
				onChange={(e) => setCurrentPassword(e.target.value)}
				required
				className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-200"
			/>
			<input
				type="password"
				placeholder="New password"
				value={newPassword}
				onChange={(e) => setNewPassword(e.target.value)}
				required
				minLength={6}
				className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-200"
			/>
			{message && (
				<p
					className={`text-sm ${message.type === "success" ? "text-green-600" : "text-red-600"}`}
				>
					{message.text}
				</p>
			)}
			<button
				type="submit"
				disabled={changePassword.isPending}
				className="px-4 py-2 text-sm font-medium text-white bg-gray-700 hover:bg-gray-800 disabled:opacity-50 rounded-lg transition-colors"
			>
				{changePassword.isPending ? "..." : "Change Password"}
			</button>
		</form>
	);
}

function ApiKeySection() {
	const { data: keys } = useApiKeys();
	const createKey = useCreateApiKey();
	const deleteKey = useDeleteApiKey();
	const [name, setName] = useState("");
	const [newKey, setNewKey] = useState<string | null>(null);

	async function handleCreate(e: React.FormEvent) {
		e.preventDefault();
		const result = await createKey.mutateAsync({ name });
		setNewKey(result.key);
		setName("");
	}

	return (
		<div className="space-y-3">
			<h3 className="text-sm font-medium text-gray-900">API Keys</h3>
			<p className="text-xs text-gray-500">
				API keys allow programmatic access to GearBox (e.g., from Claude Desktop
				or scripts).
			</p>

			{newKey && (
				<div className="bg-amber-50 border border-amber-200 rounded-lg p-3">
					<p className="text-xs font-medium text-amber-800 mb-1">
						Copy this key now — it won't be shown again:
					</p>
					<code className="text-xs text-amber-900 break-all select-all">
						{newKey}
					</code>
					<button
						type="button"
						onClick={() => setNewKey(null)}
						className="mt-2 block text-xs text-amber-700 hover:text-amber-900"
					>
						Dismiss
					</button>
				</div>
			)}

			<form onSubmit={handleCreate} className="flex gap-2">
				<input
					type="text"
					placeholder="Key name (e.g., claude-desktop)"
					value={name}
					onChange={(e) => setName(e.target.value)}
					required
					className="flex-1 px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-200"
				/>
				<button
					type="submit"
					disabled={createKey.isPending}
					className="px-4 py-2 text-sm font-medium text-white bg-gray-700 hover:bg-gray-800 disabled:opacity-50 rounded-lg transition-colors"
				>
					Create
				</button>
			</form>

			{keys && keys.length > 0 && (
				<div className="space-y-2">
					{keys.map((key) => (
						<div
							key={key.id}
							className="flex items-center justify-between py-2 px-3 bg-gray-50 rounded-lg"
						>
							<div>
								<span className="text-sm text-gray-900">{key.name}</span>
								<span className="text-xs text-gray-400 ml-2">
									{key.keyPrefix}...
								</span>
							</div>
							<button
								type="button"
								onClick={() => deleteKey.mutate(key.id)}
								className="text-xs text-red-500 hover:text-red-700"
							>
								Revoke
							</button>
						</div>
					))}
				</div>
			)}
		</div>
	);
}

function ImportExportSection() {
	const exportItems = useExportItems();
	const importItems = useImportItems();
	const fileInputRef = useRef<HTMLInputElement>(null);
	const [importResult, setImportResult] = useState<{
		imported: number;
		createdCategories: string[];
		errors: string[];
	} | null>(null);

	async function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
		const file = e.target.files?.[0];
		if (!file) return;
		setImportResult(null);
		try {
			const result = await importItems.mutateAsync(file);
			setImportResult(result);
		} catch (err) {
			setImportResult({
				imported: 0,
				createdCategories: [],
				errors: [(err as Error).message],
			});
		}
		// Reset so the same file can be imported again if needed
		if (fileInputRef.current) fileInputRef.current.value = "";
	}

	return (
		<div className="space-y-3">
			<h3 className="text-sm font-medium text-gray-900">Import / Export</h3>
			<p className="text-xs text-gray-500">
				Export your gear collection as a CSV file, or import items from a CSV.
			</p>

			<div className="flex flex-wrap gap-2">
				<button
					type="button"
					onClick={exportItems}
					className="px-4 py-2 text-sm font-medium text-white bg-gray-700 hover:bg-gray-800 rounded-lg transition-colors"
				>
					Export CSV
				</button>

				<label className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-200 hover:bg-gray-50 rounded-lg transition-colors cursor-pointer">
					{importItems.isPending ? "Importing..." : "Import CSV"}
					<input
						ref={fileInputRef}
						type="file"
						accept=".csv"
						className="hidden"
						disabled={importItems.isPending}
						onChange={handleFileChange}
					/>
				</label>
			</div>

			{importResult && (
				<div
					className={`rounded-lg p-3 text-xs space-y-1 ${
						importResult.errors.length > 0 && importResult.imported === 0
							? "bg-red-50 border border-red-200 text-red-700"
							: "bg-green-50 border border-green-200 text-green-700"
					}`}
				>
					{importResult.imported > 0 && (
						<p className="font-medium">
							{importResult.imported} item
							{importResult.imported !== 1 ? "s" : ""} imported.
						</p>
					)}
					{importResult.createdCategories.length > 0 && (
						<p>New categories: {importResult.createdCategories.join(", ")}</p>
					)}
					{importResult.errors.map((err, i) => (
						// biome-ignore lint/suspicious/noArrayIndexKey: static error list
						<p key={i} className="text-red-600">
							{err}
						</p>
					))}
					{importResult.imported === 0 && importResult.errors.length === 0 && (
						<p>No items found in the CSV.</p>
					)}
				</div>
			)}
		</div>
	);
}

function SettingsPage() {
	const unit = useWeightUnit();
	const currency = useCurrency();
	const updateSetting = useUpdateSetting();
	const { data: auth } = useAuth();

	return (
		<div className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
			<div className="mb-6">
				<Link
					to="/"
					className="text-sm text-gray-500 hover:text-gray-700 mb-2 inline-block"
				>
					&larr; Back
				</Link>
				<h1 className="text-xl font-semibold text-gray-900">Settings</h1>
			</div>

			<div className="bg-white rounded-xl border border-gray-100 p-5 space-y-6">
				<div className="flex items-center justify-between">
					<div>
						<h3 className="text-sm font-medium text-gray-900">Weight Unit</h3>
						<p className="text-xs text-gray-500 mt-0.5">
							Choose the unit used to display weights across the app
						</p>
					</div>
					<div className="flex items-center gap-1 bg-gray-100 rounded-full px-1 py-0.5">
						{UNITS.map((u) => (
							<button
								key={u}
								type="button"
								onClick={() =>
									updateSetting.mutate({
										key: "weightUnit",
										value: u,
									})
								}
								className={`px-2.5 py-1 text-xs rounded-full transition-colors ${
									unit === u
										? "bg-white text-gray-700 shadow-sm font-medium"
										: "text-gray-400 hover:text-gray-600"
								}`}
							>
								{u}
							</button>
						))}
					</div>
				</div>

				<div className="border-t border-gray-100" />

				<div className="flex items-center justify-between">
					<div>
						<h3 className="text-sm font-medium text-gray-900">Currency</h3>
						<p className="text-xs text-gray-500 mt-0.5">
							Changes the currency symbol displayed. This does not convert
							values.
						</p>
					</div>
					<div className="flex items-center gap-1 bg-gray-100 rounded-full px-1 py-0.5">
						{CURRENCIES.map((c) => (
							<button
								key={c.value}
								type="button"
								onClick={() =>
									updateSetting.mutate({
										key: "currency",
										value: c.value,
									})
								}
								className={`px-2.5 py-1 text-xs rounded-full transition-colors ${
									currency === c.value
										? "bg-white text-gray-700 shadow-sm font-medium"
										: "text-gray-400 hover:text-gray-600"
								}`}
							>
								{c.label}
							</button>
						))}
					</div>
				</div>
			</div>

			<div className="bg-white rounded-xl border border-gray-100 p-5 space-y-6 mt-4">
				<ImportExportSection />
			</div>

			{auth?.user && (
				<div className="bg-white rounded-xl border border-gray-100 p-5 space-y-6 mt-4">
					<ChangePasswordSection />
					<div className="border-t border-gray-100" />
					<ApiKeySection />
				</div>
			)}
		</div>
	);
}
