"use client";

import * as React from "react";
import { Plus, Settings2, Trash2 } from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";

import {
  isAllowedDashboardWidget,
  kindFromFilePathAndName,
} from "@/app/customer/_lib/dashboard-widget-allowlist";
import type { DashboardWidgetKind } from "@/app/customer/_lib/dashboard-widget-registry-definitions";
import { updateDashboardAssetWidgetSettings } from "../_lib/dashboard-widgets-api";
import type {
  DashboardSettingsWidget,
  DashboardWidgetIsin,
} from "../_lib/dashboard-widgets-server-api";
import { SettingsSection } from "./settings-section";
import { DashboardWidgetConfigHost } from "./widget-config/dashboard-widget-config-host";
import type { ConfigureTarget } from "./widget-config/types";
import {
  getWidgetRemoveAction,
  parseConfigureParam,
  widgetSupportsConfiguration,
} from "./widget-config/widget-config-registry";

type WidgetSectionDef = {
  id: string;
  title: string;
  description: string;
  kinds: DashboardWidgetKind[] | "other";
  addTarget?: ConfigureTarget;
};

const WIDGET_SECTIONS: WidgetSectionDef[] = [
  {
    id: "asset-allocation",
    title: "Asset Allocation",
    description: "Allocation cards by asset class. Add a widget to configure banks and report type.",
    kinds: ["asset_allocation"],
    addTarget: { kind: "create-aa" },
  },
  {
    id: "consolidated-holdings",
    title: "Consolidated Holdings",
    description: "Holdings cards with drill-down. Add a widget to configure banks and report type.",
    kinds: ["consolidated_holdings"],
    addTarget: { kind: "create-ch" },
  },
  {
    id: "diy-holdings",
    title: "DIY Consolidated Holdings",
    description: "Custom two-level grouping with independent asset, bank, and currency filters.",
    kinds: ["diy_consolidated_holdings"],
    addTarget: { kind: "create-diy" },
  },
  {
    id: "cashflow",
    title: "Cashflow",
    description: "Calendar widgets with event type, structure status, bank, and asset class filters.",
    kinds: ["cashflow_calendar"],
    addTarget: { kind: "create-cf" },
  },
  {
    id: "top-gainers",
    title: "Top Gainers and Losers",
    description: "Configure the comparison period used for gainers and losers rankings.",
    kinds: ["top_gainers_losers"],
    addTarget: { kind: "create-tgl" },
  },
  {
    id: "deposit",
    title: "Deposit",
    description: "Maturity widgets filtered by bank and currency. Add a widget to configure filters.",
    kinds: ["deposit"],
    addTarget: { kind: "create-dep" },
  },
  {
    id: "other",
    title: "Other widgets",
    description: "Enable additional dashboard widgets. Use Configure when options are available.",
    kinds: "other",
  },
];

function widgetKind(widget: DashboardSettingsWidget): DashboardWidgetKind | null {
  return kindFromFilePathAndName(widget.file_path, widget.name);
}

function widgetsForSection(
  widgets: DashboardSettingsWidget[],
  section: WidgetSectionDef,
): DashboardSettingsWidget[] {
  if (section.kinds === "other") {
    const grouped = new Set<DashboardWidgetKind>([
      "asset_allocation",
      "consolidated_holdings",
      "diy_consolidated_holdings",
      "cashflow_calendar",
      "top_gainers_losers",
      "deposit",
    ]);
    return widgets.filter((widget) => {
      const kind = widgetKind(widget);
      return kind != null && !grouped.has(kind);
    });
  }
  const allowed = new Set(section.kinds);
  return widgets.filter((widget) => {
    const kind = widgetKind(widget);
    return kind != null && allowed.has(kind);
  });
}

export function SettingsPanelDashboard({
  tenant,
  widgets,
  selectedWidgetIds,
  widgetSelections,
  isLoading,
  errorMessage,
  initialConfigure,
  onSelectedWidgetIdsChange,
  onWidgetSelectionsChange,
  onWidgetsChanged,
  onConfigureConsumed,
}: {
  tenant: string;
  widgets: DashboardSettingsWidget[];
  selectedWidgetIds: number[];
  widgetSelections: Record<string, DashboardWidgetIsin[]>;
  isLoading: boolean;
  errorMessage: string | null;
  /** Deep-link token (`aaw-1`, `create-aa`, `create-diy`, …). */
  initialConfigure?: string | null;
  onSelectedWidgetIdsChange: (ids: number[]) => void;
  onWidgetSelectionsChange: (selections: Record<string, DashboardWidgetIsin[]>) => void;
  onWidgetsChanged?: () => void;
  onConfigureConsumed?: () => void;
}) {
  const selected = React.useMemo(() => new Set(selectedWidgetIds), [selectedWidgetIds]);
  const [configTarget, setConfigTarget] = React.useState<ConfigureTarget | null>(null);
  const [configOpen, setConfigOpen] = React.useState(false);
  const [removingWidgetId, setRemovingWidgetId] = React.useState<number | null>(null);

  const allowedWidgets = React.useMemo(
    () =>
      widgets.filter((widget) =>
        isAllowedDashboardWidget(widget.file_path, widget.name),
      ),
    [widgets],
  );

  React.useEffect(() => {
    if (isLoading) return;
    const target = parseConfigureParam(initialConfigure);
    if (!target) return;
    setConfigTarget(target);
    setConfigOpen(true);
    onConfigureConsumed?.();
  }, [initialConfigure, isLoading, onConfigureConsumed]);

  const toggleWidget = (widgetId: number, checked: boolean) => {
    const next = new Set(selectedWidgetIds);
    if (checked) next.add(widgetId);
    else next.delete(widgetId);
    onSelectedWidgetIdsChange(Array.from(next));
  };

  const openConfigure = (target: ConfigureTarget) => {
    setConfigTarget(target);
    setConfigOpen(true);
  };

  const removeWidget = async (widget: DashboardSettingsWidget) => {
    const action = getWidgetRemoveAction(widget);
    if (!action) return;
    if (!window.confirm(action.confirm)) return;

    setRemovingWidgetId(widget.widget_id);
    try {
      await updateDashboardAssetWidgetSettings(tenant, {
        operation: action.operation,
        widgetId: widget.widget_id,
      });
      toast.success(action.success);
      onWidgetsChanged?.();
    } catch (removeError) {
      toast.error(
        removeError instanceof Error ? removeError.message : "Widget could not be removed.",
      );
    } finally {
      setRemovingWidgetId(null);
    }
  };

  return (
    <>
      <div className="space-y-8">
        {isLoading ? <p className="text-muted-foreground text-sm">Loading dashboard widgets…</p> : null}
        {errorMessage ? <p className="text-destructive text-sm">{errorMessage}</p> : null}

        {!isLoading && !errorMessage
          ? WIDGET_SECTIONS.map((section) => {
              const sectionWidgets = widgetsForSection(allowedWidgets, section);
              // Hide empty "Other" section; always keep creatable sections for Add Widget.
              if (section.kinds === "other" && sectionWidgets.length === 0) return null;

              return (
                <SettingsSection
                  key={section.id}
                  title={section.title}
                  description={section.description}
                  action={
                    section.addTarget ? (
                      <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        className="gap-1.5"
                        onClick={() => openConfigure(section.addTarget!)}
                      >
                        <Plus className="size-3.5" />
                        Add Widget
                      </Button>
                    ) : undefined
                  }
                >
                  {sectionWidgets.length === 0 ? (
                    <p className="rounded-lg border border-dashed p-6 text-center text-muted-foreground text-sm">
                      No widgets yet. Click Add Widget to create one.
                    </p>
                  ) : (
                    <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
                      {sectionWidgets.map((widget) => {
                        const checked = selected.has(widget.widget_id);
                        const canConfigure = widgetSupportsConfiguration(widget);
                        const removeAction = canConfigure ? getWidgetRemoveAction(widget) : null;
                        return (
                          <div
                            key={widget.widget_id}
                            className="flex flex-col rounded-lg border border-border/80 bg-background p-4 transition-colors has-[[data-checked]]:border-primary/40"
                          >
                            <label className="flex cursor-pointer items-start gap-3">
                              <Checkbox
                                checked={checked}
                                onCheckedChange={(value) =>
                                  toggleWidget(widget.widget_id, value === true)
                                }
                                aria-label={`Show ${widget.name}`}
                                className="mt-0.5"
                              />
                              <span className="min-w-0">
                                <span className="block font-medium text-sm">{widget.name}</span>
                                {widget.short_description ? (
                                  <span className="mt-1 block text-muted-foreground text-xs leading-relaxed">
                                    {widget.short_description}
                                  </span>
                                ) : null}
                              </span>
                            </label>

                            {canConfigure ? (
                              <div className="mt-auto flex flex-wrap justify-end gap-2 pt-3">
                                {removeAction ? (
                                  <Button
                                    type="button"
                                    variant="outline"
                                    size="sm"
                                    className="gap-1.5 text-destructive"
                                    disabled={removingWidgetId === widget.widget_id}
                                    onClick={() => void removeWidget(widget)}
                                  >
                                    <Trash2 className="size-3.5" />
                                    {removingWidgetId === widget.widget_id ? "Removing…" : "Remove"}
                                  </Button>
                                ) : null}
                                <Button
                                  type="button"
                                  variant="outline"
                                  size="sm"
                                  className="gap-1.5"
                                  onClick={() =>
                                    openConfigure({ kind: "widget", widgetId: widget.widget_id })
                                  }
                                >
                                  <Settings2 className="size-3.5" />
                                  Configure
                                </Button>
                              </div>
                            ) : null}
                          </div>
                        );
                      })}
                    </div>
                  )}
                </SettingsSection>
              );
            })
          : null}

        {!isLoading && !errorMessage && allowedWidgets.length === 0 ? (
          <p className="rounded-lg border border-dashed p-6 text-center text-muted-foreground text-sm">
            No dashboard widgets are available.
          </p>
        ) : null}
      </div>

      <DashboardWidgetConfigHost
        tenant={tenant}
        widgets={allowedWidgets}
        target={configTarget}
        open={configOpen}
        onOpenChange={(next) => {
          setConfigOpen(next);
          if (!next) setConfigTarget(null);
        }}
        widgetSelections={widgetSelections}
        onWidgetSelectionsChange={onWidgetSelectionsChange}
        onWidgetsChanged={onWidgetsChanged}
      />
    </>
  );
}
