import { useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import {
	Activity,
	DatabaseBackup,
	LayoutDashboard,
	Monitor,
} from "lucide-react";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
	Dialog,
	DialogContent,
	DialogHeader,
	DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import {
	useDashboardShortcuts,
	useDeleteDashboardShortcut,
	useSaveDashboardShortcut,
} from "../hooks/useDashboard";
import {
	useDetachWidgetReference,
	useWidgetInstances,
	useWidgetReferences,
} from "../hooks/useWidgets";
import { useServiceInstances } from "../hooks/useServices";
import { useIsMobile } from "../hooks/useIsMobile";
import type {
	DashboardShortcut,
	DashboardShortcutInput,
	ServiceInstance,
	WidgetInstance,
} from "../types";
import { SectionCard } from "../components/SectionCard";
import { ConfirmDialog } from "../components/ConfirmDialog";
import { DialogFooter } from "../components/DialogFooter";
import { WidgetInstanceCard } from "../components/WidgetInstance";
import { WidgetConfigDialog } from "../components/WidgetConfigDialog";

// --- Mobile section grouping (mobile-parity) ---

const SECTION_ORDER = ["observability", "media", "backups", "custom"] as const;
type SectionId = (typeof SECTION_ORDER)[number];

const SECTION_META: Record<
	SectionId,
	{ label: string; icon: typeof Activity }
> = {
	observability: { label: "Observability", icon: Activity },
	media: { label: "Media", icon: Monitor },
	backups: { label: "Backups", icon: DatabaseBackup },
	custom: { label: "Custom", icon: LayoutDashboard },
};

const OBSERVABILITY_TYPES = new Set(["alertmanager", "prometheus"]);

function widgetSection(
	widget: WidgetInstance,
	services: ServiceInstance[],
): SectionId {
	if (!widget.service_id) {
		return widget.widget_kind === "backups" ? "backups" : "custom";
	}
	const service = services.find((s) => s.id === widget.service_id);
	const serviceType = service?.service_type ?? "";
	if (OBSERVABILITY_TYPES.has(serviceType)) return "observability";
	if (serviceType === "jellyfin") return "media";
	return "custom";
}

function groupWidgetsBySection(
	widgets: WidgetInstance[],
	services: ServiceInstance[],
): { id: SectionId; widgets: WidgetInstance[] }[] {
	const groups: Record<SectionId, WidgetInstance[]> = {
		observability: [],
		media: [],
		backups: [],
		custom: [],
	};
	for (const w of widgets) {
		groups[widgetSection(w, services)].push(w);
	}
	return SECTION_ORDER.map((id) => ({ id, widgets: groups[id] })).filter(
		(s) => s.widgets.length > 0,
	);
}

function MobileWidgetSections({
	sections,
	onEditWidget,
	onCopyWidget,
}: {
	sections: { id: SectionId; widgets: WidgetInstance[] }[];
	onEditWidget?: (widgetId: string) => void;
	onCopyWidget?: (widgetId: string) => void;
}) {
	return (
		<>
			<div className="-mx-1 flex gap-2 overflow-x-auto px-1 pb-1">
				{sections.map((section) => {
					const meta = SECTION_META[section.id];
					const Icon = meta.icon;
					return (
						<button
							key={section.id}
							type="button"
							className="mobile-touch-target inline-flex shrink-0 items-center gap-1.5 rounded-full border border-border bg-card px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
							onClick={() =>
								document
									.getElementById(`dashboard-section-${section.id}`)
									?.scrollIntoView({
										behavior: "smooth",
										block: "start",
									})
							}
						>
							<Icon className="size-3.5" />
							{meta.label}
						</button>
					);
				})}
			</div>
			<div className="grid grid-cols-1 gap-4">
				{sections.map((section) => (
					<section
						key={section.id}
						id={`dashboard-section-${section.id}`}
						className="scroll-mt-16 flex flex-col gap-2"
					>
						<h3 className="text-sm font-semibold text-muted-foreground">
							{SECTION_META[section.id].label}
						</h3>
						{section.widgets.map((widget) => (
							<WidgetInstanceCard
								key={widget.id}
								widget={widget}
								onEdit={onEditWidget ? (id) => onEditWidget(id) : undefined}
								onCopy={onCopyWidget ? (id) => onCopyWidget(id) : undefined}
							/>
						))}
					</section>
				))}
			</div>
		</>
	);
}

function emptyShortcut(): DashboardShortcutInput {
	return {
		id: null,
		label: "",
		shortcut_type: "website",
		enabled: true,
		icon: "",
		url: "",
		task_id: "",
		machine_id: "",
		user_id: "",
		notes: "",
	};
}

function normalizeWebsiteUrl(url: string): string {
	const trimmed = url.trim();
	if (!trimmed) return "";
	if (/^https?:\/\//i.test(trimmed)) return trimmed;
	return `https://${trimmed}`;
}

function shortcutHref(shortcut: DashboardShortcut): string {
	if (shortcut.shortcut_type === "website") {
		return normalizeWebsiteUrl(shortcut.url);
	}
	if (shortcut.shortcut_type === "action") {
		if (!shortcut.task_id) return "";
		const params = new URLSearchParams({ task: shortcut.task_id });
		if (shortcut.machine_id) params.set("machine_id", shortcut.machine_id);
		return `/actions?${params.toString()}`;
	}
	if (!shortcut.user_id) return "";
	return `/users?user=${encodeURIComponent(shortcut.user_id)}`;
}

function Field({
	label,
	htmlFor,
	helper,
	children,
}: {
	label: string;
	htmlFor: string;
	helper?: string;
	children: React.ReactNode;
}) {
	return (
		<div className="flex flex-col gap-1.5">
			<Label htmlFor={htmlFor}>{label}</Label>
			{children}
			{helper ? (
				<p className="text-xs text-muted-foreground">{helper}</p>
			) : null}
		</div>
	);
}

function ShortcutDialog({
	open,
	draft,
	onChange,
	onClose,
	onSave,
}: {
	open: boolean;
	draft: DashboardShortcutInput;
	onChange: (shortcut: DashboardShortcutInput) => void;
	onClose: () => void;
	onSave: () => void;
}) {
	return (
		<Dialog
			open={open}
			onOpenChange={(next) => {
				if (!next) onClose();
			}}
		>
			<DialogContent className="sm:max-w-lg">
				<DialogHeader>
					<DialogTitle>
						{draft.id ? "Edit shortcut" : "New shortcut"}
					</DialogTitle>
				</DialogHeader>
				<div className="flex flex-col gap-4">
					<div className="grid grid-cols-1 gap-3 sm:grid-cols-12">
						<div className="flex flex-col gap-1.5 sm:col-span-5">
							<Field label="Label" htmlFor="shortcut-label">
								<Input
									id="shortcut-label"
									value={draft.label}
									onChange={(e) =>
										onChange({ ...draft, label: e.target.value })
									}
								/>
							</Field>
						</div>
						<div className="flex flex-col gap-1.5 sm:col-span-2">
							<Field
								label="Icon"
								htmlFor="shortcut-icon"
								helper="Emoji or glyph"
							>
								<Input
									id="shortcut-icon"
									value={draft.icon}
									onChange={(e) => onChange({ ...draft, icon: e.target.value })}
								/>
							</Field>
						</div>
						<div className="flex flex-col gap-1.5 sm:col-span-5">
							<Field
								label="Type"
								htmlFor="shortcut-type"
								helper="Website opens a URL. Saved actions jump to a task. Users deep-link."
							>
								<Select
									value={draft.shortcut_type}
									onValueChange={(value) =>
										onChange({
											...draft,
											shortcut_type:
												value as DashboardShortcutInput["shortcut_type"],
										})
									}
								>
									<SelectTrigger id="shortcut-type" className="w-full">
										<SelectValue />
									</SelectTrigger>
									<SelectContent>
										<SelectItem value="website">Website</SelectItem>
										<SelectItem value="action">Saved action</SelectItem>
										<SelectItem value="user">User</SelectItem>
									</SelectContent>
								</Select>
							</Field>
						</div>
					</div>

					{draft.shortcut_type === "website" ? (
						<Field
							label="Website URL"
							htmlFor="shortcut-url"
							helper="https:// is added if missing."
						>
							<Input
								id="shortcut-url"
								value={draft.url}
								onChange={(e) => onChange({ ...draft, url: e.target.value })}
							/>
						</Field>
					) : draft.shortcut_type === "action" ? (
						<div className="grid grid-cols-1 gap-3 md:grid-cols-2">
							<Field
								label="Task ID"
								htmlFor="shortcut-task"
								helper="Saved action ID."
							>
								<Input
									id="shortcut-task"
									value={draft.task_id}
									onChange={(e) =>
										onChange({ ...draft, task_id: e.target.value })
									}
								/>
							</Field>
							<Field
								label="Machine ID"
								htmlFor="shortcut-machine"
								helper="Optional machine target."
							>
								<Input
									id="shortcut-machine"
									value={draft.machine_id}
									onChange={(e) =>
										onChange({ ...draft, machine_id: e.target.value })
									}
								/>
							</Field>
						</div>
					) : (
						<Field
							label="User ID"
							htmlFor="shortcut-user"
							helper="Jellyfin user ID."
						>
							<Input
								id="shortcut-user"
								value={draft.user_id}
								onChange={(e) =>
									onChange({ ...draft, user_id: e.target.value })
								}
							/>
						</Field>
					)}

					<Field label="Notes" htmlFor="shortcut-notes">
						<Input
							id="shortcut-notes"
							value={draft.notes}
							onChange={(e) => onChange({ ...draft, notes: e.target.value })}
						/>
					</Field>
					<div className="flex items-center gap-2">
						<Switch
							id="shortcut-enabled"
							checked={draft.enabled}
							onCheckedChange={(checked) =>
								onChange({ ...draft, enabled: checked })
							}
						/>
						<Label htmlFor="shortcut-enabled">Enabled</Label>
					</div>
				</div>
				<DialogFooter
					onCancel={onClose}
					onConfirm={onSave}
					confirmLabel="Save shortcut"
					confirmBusyLabel="Save shortcut"
				/>
			</DialogContent>
		</Dialog>
	);
}

function ShortcutCard({
	shortcut,
	onOpen,
	onEdit,
	onDelete,
}: {
	shortcut: DashboardShortcut;
	onOpen: () => void;
	onEdit: () => void;
	onDelete: () => void;
}) {
	const href = shortcutHref(shortcut);
	const subtitle =
		shortcut.shortcut_type === "website"
			? shortcut.url || "No URL configured"
			: shortcut.shortcut_type === "action"
				? [
						shortcut.task_id || "task pending",
						shortcut.machine_id
							? `machine ${shortcut.machine_id}`
							: "any machine",
					].join(" · ")
				: shortcut.user_id || "No user configured";

	return (
		<Card className="h-full">
			<CardContent className="flex flex-col gap-3 p-3">
				<div className="flex flex-row items-start justify-between gap-2">
					<div className="min-w-0">
						<div className="truncate font-semibold">{shortcut.label}</div>
						<div className="truncate text-sm text-muted-foreground">
							{subtitle}
						</div>
					</div>
					<div className="flex flex-row items-center gap-2">
						{shortcut.icon ? (
							<div className="grid size-8 place-items-center rounded-md bg-muted text-lg">
								{shortcut.icon}
							</div>
						) : null}
						<Badge variant="outline">{shortcut.shortcut_type}</Badge>
					</div>
				</div>
				{shortcut.notes ? (
					<p className="text-xs text-muted-foreground">{shortcut.notes}</p>
				) : null}
				<div className="flex flex-row flex-wrap gap-2">
					<Button
						size="sm"
						disabled={!shortcut.enabled || !href}
						onClick={onOpen}
					>
						Open
					</Button>
					<Button size="sm" variant="outline" onClick={onEdit}>
						Edit
					</Button>
					<Button size="sm" variant="destructive" onClick={onDelete}>
						Delete
					</Button>
				</div>
			</CardContent>
		</Card>
	);
}

export function Dashboard() {
	const navigate = useNavigate();
	const { data: shortcuts = [] } = useDashboardShortcuts();
	const saveShortcut = useSaveDashboardShortcut();
	const deleteShortcut = useDeleteDashboardShortcut();
	const [shortcutDialogOpen, setShortcutDialogOpen] = useState(false);
	const [shortcutDraft, setShortcutDraft] = useState<DashboardShortcutInput>(
		emptyShortcut(),
	);
	const [deleteShortcutId, setDeleteShortcutId] = useState<string | null>(null);
	const [widgetDialogOpen, setWidgetDialogOpen] = useState(false);
	const [editWidgetId, setEditWidgetId] = useState<string | undefined>();
	const { data: widgetInstances = [] } = useWidgetInstances(
		undefined,
		"dashboard",
	);
	const { data: widgetReferences = [] } = useWidgetReferences("main");
	const { data: services = [] } = useServiceInstances();
	const isMobile = useIsMobile();

	const visibleWidgets = useMemo(() => {
		const refs = widgetReferences
			.filter((r) => r.widget.enabled)
			.map((r) => r.widget);
		return [...widgetInstances, ...refs]
			.filter((w) => w.enabled)
			.sort((a, b) => a.sort_order - b.sort_order);
	}, [widgetInstances, widgetReferences]);

	// Track which visible widgets are references (for the copy/detach button).
	const referencedWidgetIds = useMemo(
		() => new Set(widgetReferences.map((r) => r.widget.id)),
		[widgetReferences],
	);
	const detachRef = useDetachWidgetReference();

	const mobileSections = useMemo(
		() => groupWidgetsBySection(visibleWidgets, services),
		[visibleWidgets, services],
	);

	const openCreateShortcut = () => {
		setShortcutDraft(emptyShortcut());
		setShortcutDialogOpen(true);
	};

	const openEditShortcut = (shortcut: DashboardShortcut) => {
		setShortcutDraft({
			id: shortcut.id,
			label: shortcut.label,
			shortcut_type: shortcut.shortcut_type,
			enabled: shortcut.enabled,
			icon: shortcut.icon,
			url: shortcut.url,
			task_id: shortcut.task_id,
			machine_id: shortcut.machine_id,
			user_id: shortcut.user_id,
			notes: shortcut.notes,
		});
		setShortcutDialogOpen(true);
	};

	const saveShortcutDraft = async () => {
		await saveShortcut.mutateAsync(shortcutDraft);
		setShortcutDialogOpen(false);
		setShortcutDraft(emptyShortcut());
	};

	return (
		<div className="flex flex-col gap-4">
			{services.length === 0 ? (
				<SectionCard
					title="Welcome to Manage"
					description="Add a service to get started."
				>
					<div className="flex flex-col gap-3">
						<p className="text-sm text-muted-foreground">
							No services configured yet. Add a Jellyfin, SSH target, Authentik,
							or observability service to populate the navigation and
							dashboards.
						</p>
						<Button
							variant="outline"
							onClick={() => navigate("/services")}
							className="w-fit"
						>
							Add a service
						</Button>
					</div>
				</SectionCard>
			) : null}
			<SectionCard
				title="Shortcuts"
				description="Quick links to websites today, with room for action and user shortcuts later."
				action={
					<div className="flex gap-2">
						<Button variant="outline" onClick={() => setWidgetDialogOpen(true)}>
							Edit dashboard
						</Button>
						<Button variant="outline" onClick={openCreateShortcut}>
							Add shortcut
						</Button>
					</div>
				}
			>
				{shortcuts.length ? (
					<div className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
						{shortcuts.map((shortcut) => (
							<ShortcutCard
								key={shortcut.id}
								shortcut={shortcut}
								onOpen={() => {
									const href = shortcutHref(shortcut);
									if (shortcut.shortcut_type === "website") {
										window.open(href, "_blank", "noopener,noreferrer");
									} else if (href) {
										navigate(href);
									}
								}}
								onEdit={() => openEditShortcut(shortcut)}
								onDelete={() => setDeleteShortcutId(shortcut.id)}
							/>
						))}
					</div>
				) : (
					<Alert>
						<AlertDescription>
							No shortcuts yet. Add a website now, then add action or user
							shortcuts later.
						</AlertDescription>
					</Alert>
				)}
			</SectionCard>

			{isMobile && mobileSections.length > 0 ? (
				<MobileWidgetSections
					sections={mobileSections}
					onEditWidget={(id) => {
						setEditWidgetId(id);
						setWidgetDialogOpen(true);
					}}
					onCopyWidget={(id) => {
						const ref = widgetReferences.find((r) => r.widget.id === id);
						if (ref) detachRef.mutate(ref.id);
					}}
				/>
			) : (
				visibleWidgets.map((widget) => (
					<WidgetInstanceCard
						key={widget.id}
						widget={widget}
						onEdit={(id) => {
							setEditWidgetId(id);
							setWidgetDialogOpen(true);
						}}
						onCopy={
							referencedWidgetIds.has(widget.id)
								? () => {
										// Detach: find the reference and clone it.
										const ref = widgetReferences.find(
											(r) => r.widget.id === widget.id,
										);
										if (ref) detachRef.mutate(ref.id);
									}
								: undefined
						}
					/>
				))
			)}

			<ShortcutDialog
				open={shortcutDialogOpen}
				draft={shortcutDraft}
				onChange={setShortcutDraft}
				onClose={() => setShortcutDialogOpen(false)}
				onSave={saveShortcutDraft}
			/>
			<ConfirmDialog
				open={Boolean(deleteShortcutId)}
				title="Delete shortcut?"
				message="This cannot be undone. The shortcut will be removed from the dashboard."
				confirmLabel="Delete"
				onCancel={() => setDeleteShortcutId(null)}
				onConfirm={() => {
					if (deleteShortcutId) {
						deleteShortcut.mutate(deleteShortcutId);
					}
					setDeleteShortcutId(null);
				}}
			/>
			<WidgetConfigDialog
				open={widgetDialogOpen}
				onClose={() => {
					setWidgetDialogOpen(false);
					setEditWidgetId(undefined);
				}}
				dashboardScope="main"
				editWidgetId={editWidgetId}
			/>
		</div>
	);
}
