"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { Button } from "@open-mercato/ui/primitives/button";
import { IconButton } from "@open-mercato/ui/primitives/icon-button";
import { Spinner } from "@open-mercato/ui/primitives/spinner";
import { ErrorNotice } from "@open-mercato/ui/primitives/ErrorNotice";
import { Alert, AlertDescription, AlertTitle } from "@open-mercato/ui/primitives/alert";
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
import { getDashboardWidgets, loadDashboardWidgetModule } from "./widgetRegistry.js";
import { cn } from "@open-mercato/shared/lib/utils";
import { GripVertical, Info, Plus, RefreshCw, Settings2, Trash2, X, Loader2 } from "lucide-react";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { InjectionSpot } from "../injection/InjectionSpot.js";
function sizeClass(size) {
  switch (size) {
    case "lg":
      return "md:col-span-2";
    case "md":
      return "md:col-span-1";
    case "sm":
    default:
      return "md:col-span-1";
  }
}
function sortLayout(items) {
  return [...items].sort((a, b) => {
    const aOrder = a.order ?? a.priority ?? 0;
    const bOrder = b.order ?? b.priority ?? 0;
    return aOrder - bOrder;
  }).map((item, index) => ({ ...item, order: index, priority: index }));
}
const DEFAULT_SIZE = "md";
function generateId() {
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
    return crypto.randomUUID();
  }
  return Date.now().toString(36) + Math.random().toString(36).slice(2);
}
function DashboardScreen() {
  const t = useT();
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [hasRegisteredWidgets, setHasRegisteredWidgets] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [layout, setLayout] = React.useState([]);
  const [widgetCatalog, setWidgetCatalog] = React.useState([]);
  const [allowedWidgetIds, setAllowedWidgetIds] = React.useState([]);
  const [canConfigure, setCanConfigure] = React.useState(false);
  const [context, setContext] = React.useState(null);
  const [editing, setEditing] = React.useState(false);
  const [settingsId, setSettingsId] = React.useState(null);
  const pendingOpsRef = React.useRef(0);
  const saveQueueRef = React.useRef(Promise.resolve());
  const draggingIdRef = React.useRef(null);
  const adjustSaving = React.useCallback((delta) => {
    pendingOpsRef.current = Math.max(0, pendingOpsRef.current + delta);
    setSaving(pendingOpsRef.current > 0);
  }, []);
  const load = React.useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const call = await apiCall("/api/dashboards/layout");
      if (!call.ok || !call.result) {
        throw new Error(`Failed with status ${call.status}`);
      }
      const data = call.result;
      const registeredWidgetCount = getDashboardWidgets().length;
      const normalizedLayout = sortLayout(data.layout?.items ?? []);
      setLayout(normalizedLayout);
      setWidgetCatalog(data.widgets ?? []);
      setHasRegisteredWidgets(registeredWidgetCount > 0 || (data.widgets ?? []).length > 0);
      setAllowedWidgetIds(data.allowedWidgetIds ?? []);
      setCanConfigure(!!data.canConfigure);
      if (data.context) {
        setContext({
          userId: data.context.userId,
          tenantId: data.context.tenantId ?? null,
          organizationId: data.context.organizationId ?? null,
          userName: data.context.userName ?? null,
          userEmail: data.context.userEmail ?? null,
          userLabel: data.context.userLabel ?? null
        });
      } else {
        setContext(null);
      }
      if (!data.canConfigure) {
        setEditing(false);
        setSettingsId(null);
      }
    } catch (err) {
      console.error("Failed to load dashboard layout", err);
      if (getDashboardWidgets().length === 0) {
        setHasRegisteredWidgets(false);
        setLayout([]);
        setWidgetCatalog([]);
        setAllowedWidgetIds([]);
        setCanConfigure(false);
        setContext(null);
        setEditing(false);
        setSettingsId(null);
        return;
      }
      setError(t("dashboard.loadError"));
    } finally {
      setLoading(false);
    }
  }, [t]);
  React.useEffect(() => {
    load();
  }, [load]);
  const metaById = React.useMemo(() => {
    const map = /* @__PURE__ */ new Map();
    for (const meta of widgetCatalog) map.set(meta.id, meta);
    return map;
  }, [widgetCatalog]);
  const availableWidgets = React.useMemo(() => {
    const currentIds = new Set(layout.map((item) => item.widgetId));
    return widgetCatalog.filter((meta) => !currentIds.has(meta.id));
  }, [layout, widgetCatalog]);
  const resolveWidgetTitle = React.useCallback((meta) => {
    const keys = [
      `${meta.id}.title`,
      `dashboard.widgets.${meta.id}.title`
    ];
    if (meta.id.includes(".")) {
      const parts = meta.id.split(".");
      const lastPart = parts.pop();
      keys.unshift(`${parts.join(".")}.widgets.${lastPart}.title`);
    }
    for (const key of keys) {
      const translated = t(key);
      if (translated !== key) return translated;
    }
    return meta.title;
  }, [t]);
  const resolveWidgetDescription = React.useCallback((meta) => {
    if (!meta.description) return null;
    const keys = [
      `${meta.id}.description`,
      `dashboard.widgets.${meta.id}.description`
    ];
    if (meta.id.includes(".")) {
      const parts = meta.id.split(".");
      const lastPart = parts.pop();
      keys.unshift(`${parts.join(".")}.widgets.${lastPart}.description`);
    }
    for (const key of keys) {
      const translated = t(key);
      if (translated !== key) return translated;
    }
    return meta.description;
  }, [t]);
  const queueLayoutSave = React.useCallback((items) => {
    saveQueueRef.current = saveQueueRef.current.then(async () => {
      adjustSaving(1);
      try {
        const payload = {
          items: items.map((item, index) => ({
            id: item.id,
            widgetId: item.widgetId,
            order: index,
            priority: index,
            size: item.size ?? DEFAULT_SIZE,
            settings: item.settings ?? null
          }))
        };
        const call = await apiCall("/api/dashboards/layout", {
          method: "PUT",
          headers: { "content-type": "application/json" },
          body: JSON.stringify(payload)
        });
        if (!call.ok) throw new Error(`Failed with status ${call.status}`);
        setError(null);
      } catch (err) {
        console.error("Failed to save layout", err);
        setError(t("dashboard.saveError"));
      } finally {
        adjustSaving(-1);
      }
    });
  }, [adjustSaving, t]);
  const patchWidgetSettings = React.useCallback(async (itemId, nextSettings) => {
    adjustSaving(1);
    try {
      const call = await apiCall(`/api/dashboards/layout/${encodeURIComponent(itemId)}`, {
        method: "PATCH",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ settings: nextSettings })
      });
      if (!call.ok) throw new Error(`Failed with status ${call.status}`);
      setError(null);
    } catch (err) {
      console.error("Failed to update widget settings", err);
      setError(t("dashboard.saveError"));
    } finally {
      adjustSaving(-1);
    }
  }, [adjustSaving, t]);
  const handleAddWidget = React.useCallback((widgetId) => {
    const meta = metaById.get(widgetId);
    if (!meta) return;
    setLayout((prev) => {
      const next = sortLayout([
        ...prev,
        {
          id: generateId(),
          widgetId: meta.id,
          order: prev.length,
          priority: prev.length,
          size: meta.defaultSize ?? DEFAULT_SIZE,
          settings: meta.defaultSettings ?? null
        }
      ]);
      queueLayoutSave(next);
      return next;
    });
    setSettingsId(null);
  }, [metaById, queueLayoutSave]);
  const handleRemoveWidget = React.useCallback((itemId) => {
    setLayout((prev) => {
      const next = sortLayout(prev.filter((item) => item.id !== itemId));
      queueLayoutSave(next);
      return next;
    });
    if (settingsId === itemId) setSettingsId(null);
  }, [queueLayoutSave, settingsId]);
  const handleReorder = React.useCallback((dragId, targetId) => {
    if (!dragId || dragId === targetId) return;
    setLayout((prev) => {
      const items = [...prev];
      const from = items.findIndex((item) => item.id === dragId);
      const to = items.findIndex((item) => item.id === targetId);
      if (from === -1 || to === -1) return prev;
      const [moved] = items.splice(from, 1);
      items.splice(to, 0, moved);
      const next = items.map((item, index) => ({
        ...item,
        order: index,
        priority: index
      }));
      queueLayoutSave(next);
      return next;
    });
  }, [queueLayoutSave]);
  const handleSettingsChange = React.useCallback((itemId, nextSettings) => {
    setLayout((prev) => prev.map((item) => item.id === itemId ? { ...item, settings: nextSettings } : item));
    void patchWidgetSettings(itemId, nextSettings);
  }, [patchWidgetSettings]);
  const toggleEditing = React.useCallback(() => {
    if (!canConfigure) return;
    setEditing((prev) => {
      const next = !prev;
      if (!next) setSettingsId(null);
      return next;
    });
  }, [canConfigure]);
  const handleRefresh = React.useCallback(() => {
    load();
  }, [load]);
  const injectionContext = React.useMemo(
    () => ({
      layout,
      widgetCatalog,
      allowedWidgetIds,
      canConfigure,
      editing,
      userContext: context
    }),
    [allowedWidgetIds, canConfigure, context, editing, layout, widgetCatalog]
  );
  const dashboardBeforeSpotId = "dashboard:before";
  const dashboardAfterSpotId = "dashboard:after";
  if (loading) {
    return /* @__PURE__ */ jsx("div", { className: "flex min-h-[320px] items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { size: "lg" }) });
  }
  if (error && layout.length === 0) {
    return /* @__PURE__ */ jsx(
      ErrorNotice,
      {
        title: t("dashboard.unavailable"),
        message: error,
        action: /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleRefresh, children: t("dashboard.retry") })
      }
    );
  }
  if (!hasRegisteredWidgets && layout.length === 0) {
    return /* @__PURE__ */ jsxs(Alert, { variant: "info", children: [
      /* @__PURE__ */ jsx(Info, { className: "h-4 w-4", "aria-hidden": true }),
      /* @__PURE__ */ jsx(AlertTitle, { children: t("dashboard.empty.noWidgets.title", "No dashboard widgets yet") }),
      /* @__PURE__ */ jsx(AlertDescription, { children: t(
        "dashboard.empty.noWidgets.description",
        "After you add the first module that exposes dashboard widgets, they will appear here."
      ) })
    ] });
  }
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
    /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
      /* @__PURE__ */ jsxs("div", { children: [
        /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: t("dashboard.title") }),
        /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("dashboard.subtitle") })
      ] }),
      /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
        saving && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
          /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
          /* @__PURE__ */ jsx("span", { children: t("dashboard.saving") })
        ] }),
        canConfigure && /* @__PURE__ */ jsxs(Button, { variant: editing ? "secondary" : "outline", size: "sm", onClick: toggleEditing, children: [
          /* @__PURE__ */ jsx(Settings2, { className: "h-4 w-4" }),
          /* @__PURE__ */ jsx("span", { children: editing ? t("dashboard.action.done") : t("dashboard.action.customize") })
        ] })
      ] })
    ] }),
    error && layout.length > 0 && /* @__PURE__ */ jsx(
      ErrorNotice,
      {
        title: t("dashboard.error.partial"),
        message: error,
        action: /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleRefresh, children: t("dashboard.error.reload") })
      }
    ),
    /* @__PURE__ */ jsx(InjectionSpot, { spotId: dashboardBeforeSpotId, context: injectionContext }),
    editing && availableWidgets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed bg-muted/50 p-4", children: [
      /* @__PURE__ */ jsx("div", { className: "mb-2 text-sm font-medium text-muted-foreground", children: t("dashboard.addWidget") }),
      /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: availableWidgets.map((meta) => /* @__PURE__ */ jsxs(
        Button,
        {
          variant: "outline",
          size: "sm",
          onClick: () => handleAddWidget(meta.id),
          children: [
            /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
            resolveWidgetTitle(meta)
          ]
        },
        meta.id
      )) })
    ] }),
    /* @__PURE__ */ jsx(
      "div",
      {
        className: cn(
          "grid gap-3 sm:gap-4 md:gap-6",
          "grid-cols-1",
          "md:grid-cols-2",
          "xl:grid-cols-3"
        ),
        onDragOver: (event) => {
          if (!editing || !canConfigure) return;
          event.preventDefault();
          event.dataTransfer.dropEffect = "move";
        },
        onDrop: (event) => {
          if (!editing || !canConfigure) return;
          event.preventDefault();
          const dragId = event.dataTransfer.getData("text/plain") || draggingIdRef.current;
          if (!dragId) return;
          setLayout((prev) => {
            const items = [...prev];
            const from = items.findIndex((entry) => entry.id === dragId);
            if (from === -1) return prev;
            const [moved] = items.splice(from, 1);
            items.push(moved);
            const next = items.map((item, index) => ({
              ...item,
              order: index,
              priority: index
            }));
            queueLayoutSave(next);
            return next;
          });
          draggingIdRef.current = null;
        },
        children: layout.map((item) => {
          const meta = metaById.get(item.widgetId);
          if (!meta) return null;
          const title = resolveWidgetTitle(meta);
          const description = resolveWidgetDescription(meta);
          return /* @__PURE__ */ jsx(
            DashboardWidgetCard,
            {
              item,
              meta,
              title,
              description,
              context,
              editing: editing && canConfigure,
              activeSettings: settingsId === item.id,
              onToggleSettings: () => setSettingsId((current) => current === item.id ? null : item.id),
              onRemove: () => handleRemoveWidget(item.id),
              onSettingsChange: (settings) => handleSettingsChange(item.id, settings),
              onDragStart: () => {
                draggingIdRef.current = item.id;
              },
              onDragEnd: () => {
                draggingIdRef.current = null;
              },
              onDrop: (event) => {
                const dragId = event.dataTransfer.getData("text/plain") || draggingIdRef.current;
                handleReorder(dragId, item.id);
                draggingIdRef.current = null;
              },
              onDragEnter: () => {
              },
              onDragLeave: () => {
              },
              sizeClass: sizeClass(item.size)
            },
            item.id
          );
        })
      }
    ),
    layout.length === 0 && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-dashed bg-muted/30 p-10 text-center text-sm text-muted-foreground", children: !hasRegisteredWidgets ? t(
      "dashboard.empty.noWidgets.description",
      "After you add the first module that exposes dashboard widgets, they will appear here."
    ) : canConfigure ? t("dashboard.empty.configurable") : t("dashboard.empty.readonly") }),
    /* @__PURE__ */ jsx(InjectionSpot, { spotId: dashboardAfterSpotId, context: injectionContext })
  ] });
}
function DashboardWidgetCard({
  item,
  meta,
  title,
  description,
  context,
  editing,
  activeSettings,
  onToggleSettings,
  onRemove,
  onSettingsChange,
  onDragStart,
  onDragEnd,
  onDrop,
  onDragEnter,
  onDragLeave,
  sizeClass: sizeClass2
}) {
  const t = useT();
  const [module, setModule] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [loadError, setLoadError] = React.useState(null);
  const [isDragOver, setIsDragOver] = React.useState(false);
  const [refreshToken, setRefreshToken] = React.useState(0);
  const [refreshing, setRefreshing] = React.useState(false);
  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setLoadError(null);
    loadDashboardWidgetModule(meta.loaderKey).then((loaded) => {
      if (cancelled) return;
      setModule(loaded);
      setLoading(false);
    }).catch((err) => {
      if (cancelled) return;
      console.error("Failed to load widget module", err);
      setLoadError(t("dashboard.widget.loadError"));
      setLoading(false);
    });
    return () => {
      cancelled = true;
    };
  }, [meta.loaderKey, t]);
  React.useEffect(() => {
    if (!meta.supportsRefresh) {
      setRefreshing(false);
    }
  }, [meta.supportsRefresh]);
  React.useEffect(() => {
    if (activeSettings) {
      setRefreshing(false);
    }
  }, [activeSettings]);
  React.useEffect(() => {
    if (loadError) {
      setRefreshing(false);
    }
  }, [loadError]);
  const handleRefreshStateChange = React.useCallback((next) => {
    setRefreshing(next);
  }, []);
  const triggerRefresh = React.useCallback(() => {
    if (loading || !!loadError) return;
    setRefreshing(true);
    setRefreshToken((current) => current + 1);
  }, [loadError, loading]);
  const hydratedSettings = React.useMemo(() => {
    const raw = item.settings ?? meta.defaultSettings ?? null;
    if (module?.hydrateSettings) {
      try {
        return module.hydrateSettings(raw);
      } catch (err) {
        console.warn("Failed to hydrate widget settings", err);
        return raw;
      }
    }
    return raw;
  }, [item.settings, meta.defaultSettings, module]);
  const handleSettingsChange = React.useCallback((next) => {
    let raw = next;
    if (module?.dehydrateSettings) {
      try {
        raw = module.dehydrateSettings(next);
      } catch (err) {
        console.warn("Failed to dehydrate widget settings", err);
      }
    }
    onSettingsChange(raw);
  }, [module, onSettingsChange]);
  const WidgetComponent = module?.Widget;
  const mode = activeSettings ? "settings" : "view";
  return /* @__PURE__ */ jsxs(
    "div",
    {
      className: cn(
        "group relative flex h-full flex-col rounded-lg border bg-background shadow-sm transition",
        isDragOver ? "border-primary ring-2 ring-primary/20" : "hover:border-primary/40",
        editing ? "cursor-grab" : "cursor-default",
        sizeClass2
      ),
      draggable: editing,
      onDragStart: (event) => {
        if (!editing) return;
        event.dataTransfer.effectAllowed = "move";
        event.dataTransfer.setData("text/plain", item.id);
        onDragStart();
      },
      onDragEnd: () => {
        if (!editing) return;
        onDragEnd();
      },
      onDragOver: (event) => {
        if (!editing) return;
        event.preventDefault();
        event.stopPropagation();
        event.dataTransfer.dropEffect = "move";
        if (!isDragOver) {
          setIsDragOver(true);
          onDragEnter();
        }
      },
      onDrop: (event) => {
        if (!editing) return;
        event.preventDefault();
        event.stopPropagation();
        onDrop(event);
        setIsDragOver(false);
        onDragLeave();
      },
      onDragLeave: (event) => {
        if (!editing) return;
        event.stopPropagation();
        if (event.currentTarget.contains(event.relatedTarget)) return;
        setIsDragOver(false);
        onDragLeave();
      },
      children: [
        /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 border-b px-3 py-2", children: [
          /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
            editing && /* @__PURE__ */ jsx(GripVertical, { className: "h-4 w-4 text-muted-foreground" }),
            /* @__PURE__ */ jsxs("div", { children: [
              /* @__PURE__ */ jsx("div", { className: "text-sm font-medium leading-none", children: title }),
              description ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: description }) : null
            ] })
          ] }),
          /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
            !editing && meta.supportsRefresh && /* @__PURE__ */ jsx(
              IconButton,
              {
                variant: "ghost",
                size: "sm",
                disabled: refreshing || loading || !!loadError,
                onClick: triggerRefresh,
                "aria-label": t("dashboard.widget.refresh"),
                children: refreshing ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" })
              }
            ),
            editing && /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsx(
                IconButton,
                {
                  variant: activeSettings ? "outline" : "ghost",
                  size: "sm",
                  onClick: onToggleSettings,
                  "aria-label": activeSettings ? t("dashboard.widget.closeSettings") : t("dashboard.widget.editSettings"),
                  children: activeSettings ? /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Settings2, { className: "h-4 w-4" })
                }
              ),
              /* @__PURE__ */ jsx(
                IconButton,
                {
                  variant: "ghost",
                  size: "sm",
                  onClick: onRemove,
                  "aria-label": t("dashboard.widget.remove"),
                  children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
                }
              )
            ] })
          ] })
        ] }),
        /* @__PURE__ */ jsxs("div", { className: "flex-1 p-4", children: [
          loading && /* @__PURE__ */ jsx("div", { className: "flex h-full min-h-[120px] items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, {}) }),
          loadError && !loading && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: loadError }),
          !loading && !loadError && WidgetComponent && /* @__PURE__ */ jsx(
            WidgetComponent,
            {
              mode,
              layout: item,
              context: context ?? { userId: "", tenantId: null, organizationId: null, userName: null, userEmail: null, userLabel: null },
              settings: hydratedSettings,
              onSettingsChange: handleSettingsChange,
              refreshToken,
              onRefreshStateChange: handleRefreshStateChange
            }
          )
        ] })
      ]
    }
  );
}
export {
  DashboardScreen
};
//# sourceMappingURL=DashboardScreen.js.map
