"use client";

import * as React from "react";
import { toast } from "sonner";

import { DashboardWidgetConfigHost } from "@/app/customer/[tenant]/settings/_components/widget-config";
import type { ConfigureTarget } from "@/app/customer/[tenant]/settings/_components/widget-config/types";
import { loadDashboardWidgetSettings } from "@/app/customer/[tenant]/settings/_lib/dashboard-widgets-api";
import type {
  DashboardSettingsWidget,
  DashboardWidgetIsin,
} from "@/app/customer/[tenant]/settings/_lib/dashboard-widgets-server-api";
import { dispatchDashboardWidgetConfigSaved } from "@/app/customer/_lib/dashboard-widget-configure-events";

type DashboardWidgetConfigureContextValue = {
  openWidget: (widgetId: number) => void;
};

const DashboardWidgetConfigureContext =
  React.createContext<DashboardWidgetConfigureContextValue | null>(null);

export function useDashboardWidgetConfigure() {
  return React.useContext(DashboardWidgetConfigureContext);
}

/**
 * Hosts the shared Configure Sheet on the dashboard so widget gear buttons open
 * the widget panel in place, instead of navigating to Dashboard Settings.
 */
export function DashboardWidgetConfigureProvider({
  tenant,
  children,
}: {
  tenant: string;
  children: React.ReactNode;
}) {
  const [widgets, setWidgets] = React.useState<DashboardSettingsWidget[]>([]);
  const [widgetSelections, setWidgetSelections] = React.useState<
    Record<string, DashboardWidgetIsin[]>
  >({});
  const [target, setTarget] = React.useState<ConfigureTarget | null>(null);
  const [open, setOpen] = React.useState(false);
  const [settingsLoading, setSettingsLoading] = React.useState(false);

  const ensureSettingsLoaded = React.useCallback(async () => {
    const data = await loadDashboardWidgetSettings(tenant);
    setWidgets(data.widgets);
    setWidgetSelections(
      Object.fromEntries(
        data.widgets
          .filter((widget) => widget.requires_isin_selection)
          .map((widget) => [String(widget.widget_id), widget.isin_selection]),
      ),
    );
    return data;
  }, [tenant]);

  const openWidget = React.useCallback(
    (widgetId: number) => {
      if (!Number.isFinite(widgetId) || widgetId <= 0) return;
      setTarget({ kind: "widget", widgetId });
      setOpen(true);
      setSettingsLoading(true);
      void ensureSettingsLoaded()
        .catch((err) => {
          toast.error(err instanceof Error ? err.message : "Widget settings could not be loaded.");
          setOpen(false);
          setTarget(null);
        })
        .finally(() => {
          setSettingsLoading(false);
        });
    },
    [ensureSettingsLoaded],
  );

  const handleWidgetsChanged = React.useCallback(() => {
    void ensureSettingsLoaded().catch(() => undefined);
    const savedWidgetId = target?.kind === "widget" ? target.widgetId : undefined;
    dispatchDashboardWidgetConfigSaved(
      savedWidgetId ? { widgetId: savedWidgetId } : { listChanged: true },
    );
  }, [ensureSettingsLoaded, target]);

  const value = React.useMemo(() => ({ openWidget }), [openWidget]);

  return (
    <DashboardWidgetConfigureContext.Provider value={value}>
      {children}
      <DashboardWidgetConfigHost
        tenant={tenant}
        widgets={widgets}
        target={target}
        open={open}
        onOpenChange={(next) => {
          setOpen(next);
          if (!next) {
            setTarget(null);
          }
        }}
        widgetSelections={widgetSelections}
        onWidgetSelectionsChange={setWidgetSelections}
        onWidgetsChanged={handleWidgetsChanged}
        settingsLoading={settingsLoading}
      />
    </DashboardWidgetConfigureContext.Provider>
  );
}

/** Prefer in-dashboard configure; fall back to settings deep-link when provider is absent. */
export function useWidgetSettingsAction(widgetId: number, settingsHrefFallback: string) {
  const configure = useDashboardWidgetConfigure();

  return React.useMemo(() => {
    if (configure && widgetId > 0) {
      return {
        onSettingsClick: () => configure.openWidget(widgetId),
        settingsHref: undefined as string | undefined,
      };
    }
    return {
      onSettingsClick: undefined as (() => void) | undefined,
      settingsHref: settingsHrefFallback || undefined,
    };
  }, [configure, settingsHrefFallback, widgetId]);
}
