"use client";

import { useMemo } from "react";
import { useDashboardWidgets } from "@/hooks/useDashboardWidgets";
import { AlertMessage } from "@/components/settings/banks/AlertMessage";
import { SaveButton } from "@/components/settings/banks/SaveButton";
import type { Widget, WidgetWithPriority } from "@/types/dashboard-widgets";
import { SelectedWidgetsList } from "./SelectedWidgetsList";
import { AvailableWidgetsList } from "./AvailableWidgetsList";

export interface DashboardWidgetSelectionState {
  available: Widget[];
  selected: WidgetWithPriority[];
  loading: boolean;
  error: string | null;
  saveError: string | null;
  saveSuccess: string | null;
  dragId: string | null;
  addToSelected: (widget: Widget) => void;
  removeSelected: (id: string) => void;
  handleDragStart: (id: string) => void;
  handleDragOver: (e: React.DragEvent<HTMLDivElement>) => void;
  handleDrop: (id: string) => void;
}

export interface DashboardWidgetSelectionProps {
  /** When true (default), use internal hook; when false, all state/handlers below must be provided */
  useInternalHook?: boolean;
  available?: Widget[];
  selected?: WidgetWithPriority[];
  loading?: boolean;
  error?: string | null;
  saving?: boolean;
  saveError?: string | null;
  saveSuccess?: string | null;
  dragId?: string | null;
  addToSelected?: (widget: Widget) => void;
  removeSelected?: (id: string) => void;
  handleDragStart?: (id: string) => void;
  handleDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;
  handleDrop?: (id: string) => void;
  handleSave?: () => Promise<void>;
}

const noop = {
  addToSelected: () => {},
  removeSelected: () => {},
  handleDragStart: () => {},
  handleDragOver: () => {},
  handleDrop: () => {},
};

function useSelectionState(props: DashboardWidgetSelectionProps): DashboardWidgetSelectionState {
  const hook = useDashboardWidgets();
  const useInternal = props.useInternalHook !== false;

  if (useInternal) {
    return {
      available: hook.available,
      selected: hook.selected,
      loading: hook.loading,
      error: hook.error,
      saveError: hook.saveError,
      saveSuccess: hook.saveSuccess,
      dragId: hook.dragId,
      addToSelected: hook.addToSelected,
      removeSelected: hook.removeSelected,
      handleDragStart: hook.handleDragStart,
      handleDragOver: hook.handleDragOver,
      handleDrop: hook.handleDrop,
    };
  }

  return {
    available: props.available ?? [],
    selected: props.selected ?? [],
    loading: props.loading ?? false,
    error: props.error ?? null,
    saveError: props.saveError ?? null,
    saveSuccess: props.saveSuccess ?? null,
    dragId: props.dragId ?? null,
    addToSelected: props.addToSelected ?? noop.addToSelected,
    removeSelected: props.removeSelected ?? noop.removeSelected,
    handleDragStart: props.handleDragStart ?? noop.handleDragStart,
    handleDragOver: props.handleDragOver ?? noop.handleDragOver,
    handleDrop: props.handleDrop ?? noop.handleDrop,
  };
}

/**
 * Reusable block: which asset allocation widgets are active on the dashboard
 * and their order. Used on Dashboard Settings and Custom Widgets pages.
 */
export function DashboardWidgetSelection(props: DashboardWidgetSelectionProps) {
  const state = useSelectionState(props);
  const selectedIds = useMemo(
    () => new Set(state.selected.map((w) => w.widget_id)),
    [state.selected]
  );

  return (
    <>
      <AlertMessage error={state.saveError} success={state.saveSuccess} />
      <div className="grid gap-4 lg:grid-cols-[30%_70%]">
        <SelectedWidgetsList
          widgets={state.selected}
          loading={state.loading}
          error={state.error}
          dragId={state.dragId}
          onDragStart={state.handleDragStart}
          onDragOver={state.handleDragOver}
          onDrop={state.handleDrop}
          onRemove={state.removeSelected}
        />
        <AvailableWidgetsList
          widgets={state.available}
          selectedIds={selectedIds}
          loading={state.loading}
          error={state.error}
          onAdd={state.addToSelected}
        />
      </div>
    </>
  );
}

/** Same as above but with a Save button above the grid (for embedding in Custom Widgets page). */
export function DashboardWidgetSelectionWithSave() {
  const hook = useDashboardWidgets();
  return (
    <>
      <div className="mb-3 flex justify-end">
        <SaveButton
          onClick={hook.handleSave}
          disabled={hook.saving || hook.loading || !!hook.error}
          saving={hook.saving}
        />
      </div>
      <DashboardWidgetSelection
        useInternalHook={false}
        available={hook.available}
        selected={hook.selected}
        loading={hook.loading}
        error={hook.error}
        saving={hook.saving}
        saveError={hook.saveError}
        saveSuccess={hook.saveSuccess}
        dragId={hook.dragId}
        addToSelected={hook.addToSelected}
        removeSelected={hook.removeSelected}
        handleDragStart={hook.handleDragStart}
        handleDragOver={hook.handleDragOver}
        handleDrop={hook.handleDrop}
      />
    </>
  );
}
