import { useMemo, useState } from "react";
import { useParams } from "react-router-dom";
import { Boxes, Settings2 } from "lucide-react";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { useDashboardBySlug } from "../hooks/useDashboards";
import { useWidgetReferences } from "../hooks/useWidgets";
import { PinnedServiceLink } from "../components/PinnedServiceLink";
import { WidgetInstanceCard } from "../components/WidgetInstance";
import { WidgetConfigDialog } from "../components/WidgetConfigDialog";

/**
 * Payload model for named dashboards (design choice: inline items, not widget
 * instance ids). The payload stores an ordered list of items:
 *
 * ```
 * { items: DashboardItem[] }
 * ```
 *
 * Where `DashboardItem` is either a pinned service link (this slice) or a
 * future widget reference (follow-up). Widget composition on named dashboards
 * is deferred — the main Dashboard already has the rich widget config dialog.
 */
interface LinkItem {
	type: "link";
	label: string;
	target: string;
}

type DashboardItem = LinkItem;

function parseItems(payload: Record<string, unknown>): DashboardItem[] {
	const items = payload.items;
	if (!Array.isArray(items)) return [];
	return items.filter(
		(item): item is LinkItem =>
			typeof item === "object" &&
			item !== null &&
			item.type === "link" &&
			typeof item.label === "string" &&
			typeof item.target === "string",
	);
}

export function NamedDashboardPage() {
	const { slug = "" } = useParams<{ slug: string }>();
	const { data: dashboard, isLoading, isError } = useDashboardBySlug(slug);
	const dashboardScope = `named:${slug}`;
	const { data: widgetRefs = [] } = useWidgetReferences(dashboardScope);
	const [configOpen, setConfigOpen] = useState(false);
	const [editWidgetId, setEditWidgetId] = useState<string | undefined>();

	const items = useMemo(
		() => parseItems(dashboard?.payload ?? {}),
		[dashboard?.payload],
	);

	const visibleWidgets = useMemo(
		() =>
			widgetRefs
				.filter((r) => r.widget.enabled)
				.map((r) => r.widget)
				.sort((a, b) => a.sort_order - b.sort_order),
		[widgetRefs],
	);

	if (isLoading) {
		return <Skeleton className="h-32 w-full" />;
	}

	if (isError || !dashboard) {
		return (
			<Alert>
				<AlertDescription>
					Dashboard not found. It may have been deleted or the link is invalid.
				</AlertDescription>
			</Alert>
		);
	}

	return (
		<div className="flex flex-col gap-4">
			<div className="flex items-center justify-between">
				<h2 className="text-xl font-semibold">{dashboard.label}</h2>
				<Button
					variant="outline"
					size="sm"
					className="mobile-touch-target"
					onClick={() => setConfigOpen(true)}
				>
					<Settings2 className="size-4" />
					Edit widgets
				</Button>
			</div>

			{visibleWidgets.length > 0 ? (
				<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
					{visibleWidgets.map((widget) => (
						<WidgetInstanceCard
							key={widget.id}
							widget={widget}
							onEdit={(id) => {
								setEditWidgetId(id);
								setConfigOpen(true);
							}}
						/>
					))}
				</div>
			) : null}

			{items.length === 0 && visibleWidgets.length === 0 ? (
				<Alert>
					<AlertDescription>
						This dashboard is empty. Add widgets via "Edit widgets" or pinned
						service links from the dashboard management panel on the Services
						page.
					</AlertDescription>
				</Alert>
			) : items.length > 0 ? (
				<div className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
					{items.map((item, index) => (
						<PinnedServiceLink
							key={`${item.target}-${index}`}
							label={item.label}
							target={item.target}
							icon={Boxes}
						/>
					))}
				</div>
			) : null}

			<WidgetConfigDialog
				open={configOpen}
				onClose={() => {
					setConfigOpen(false);
					setEditWidgetId(undefined);
				}}
				dashboardScope={dashboardScope}
				editWidgetId={editWidgetId}
			/>
		</div>
	);
}
