import {
  For,
  Show,
  createEffect,
  createMemo,
  createSignal,
  onCleanup,
  onMount,
  createResource,
} from "solid-js";
import { useSearchParams } from "@solidjs/router";
import {
  BarChart3,
  Building2,
  CircleDashed,
  Coins,
  EllipsisVertical,
  Eye,
  EyeOff,
  GripVertical,
  LineChart,
  RotateCcw,
  Search,
  Settings2,
  TrendingUp,
  Users,
} from "lucide-solid";
import {
  ADMIN_DASHBOARD_WIDGETS,
  type DashboardWidgetDefinition,
  type DashboardWidgetSize,
} from "~/lib/admin/dashboard";
import type { RuntimeDashboardLayout } from "~/lib/runtime/types";
import { loadAdminDashboardLayout, saveAdminDashboardLayout } from "~/lib/runtime/storage";

const API = "";

async function fetchMetrics() {
  const accessToken =
    typeof sessionStorage !== "undefined"
      ? (sessionStorage.getItem("nxtgauge_admin_access_token") || "").trim()
      : "";
  const res = await fetch(`${API}/api/admin/dashboard/metrics`, {
    headers: {
      Accept: "application/json",
      ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
    },
    credentials: "include",
  });
  if (!res.ok) throw new Error("Failed to load metrics");
  return res.json();
}

type WidgetStateKind = "live" | "empty" | "pending";
type WidgetType = "summary" | "analytics";
type SortMode = "layout" | "name" | "status";
type FilterMode = "all" | WidgetType;
type GridLayoutMode = "3x4" | "3x3";

type WidgetMeta = {
  state: WidgetStateKind;
  type: WidgetType;
  statusLabel: string;
  subtitle: string;
  emptyMessage?: string;
  pendingMessage?: string;
};

const WIDGET_DEFINITION_MAP = Object.fromEntries(
  ADMIN_DASHBOARD_WIDGETS.map((definition) => [definition.widgetKey, definition])
);

const DEFAULT_LAYOUT: RuntimeDashboardLayout = {
  order: ADMIN_DASHBOARD_WIDGETS.slice()
    .sort((a, b) => a.order - b.order)
    .map((definition) => definition.widgetKey),
  visibility: Object.fromEntries(
    ADMIN_DASHBOARD_WIDGETS.map((definition) => [definition.widgetKey, definition.defaultVisible])
  ),
  size: Object.fromEntries(
    ADMIN_DASHBOARD_WIDGETS.map((definition) => [definition.widgetKey, definition.defaultSize])
  ),
};

const WIDGET_META: Record<string, WidgetMeta> = {
  kpi_total_users: {
    state: "live",
    type: "summary",
    statusLabel: "Live Data",
    subtitle: "Powered by USER_MANAGEMENT",
  },
  kpi_active_companies: {
    state: "live",
    type: "summary",
    statusLabel: "Live Data",
    subtitle: "Powered by COMPANY_MANAGEMENT",
  },
  kpi_open_leads: {
    state: "live",
    type: "summary",
    statusLabel: "Live Data",
    subtitle: "Powered by REQUIREMENTS_MANAGEMENT",
  },
  kpi_pending_approvals: {
    state: "live",
    type: "summary",
    statusLabel: "Live Data",
    subtitle: "Powered by APPROVAL_MANAGEMENT",
  },
  kpi_total_revenue: {
    state: "live",
    type: "summary",
    statusLabel: "Live Data",
    subtitle: "Powered by REVENUE_LEDGER",
  },
  kpi_credits_purchased: {
    state: "empty",
    type: "summary",
    statusLabel: "No Data",
    subtitle: "Powered by CREDIT_MANAGEMENT",
    emptyMessage: "No credit activity available yet",
  },
  chart_leads_trend: {
    state: "live",
    type: "analytics",
    statusLabel: "Live Data",
    subtitle: "Weekly leads performance overview • Powered by REPORTS",
  },
  chart_revenue_overview: {
    state: "live",
    type: "analytics",
    statusLabel: "Live Data",
    subtitle: "Weekly revenue overview • Powered by REVENUE_LEDGER",
  },
};

function sanitizeLayout(layout: RuntimeDashboardLayout | null | undefined): RuntimeDashboardLayout {
  const knownKeys = new Set(ADMIN_DASHBOARD_WIDGETS.map((definition) => definition.widgetKey));
  const fallbackOrder = DEFAULT_LAYOUT.order;
  const incomingOrder = Array.isArray(layout?.order) ? layout!.order : [];

  const seen = new Set<string>();
  const normalizedOrder: string[] = [];

  for (const key of incomingOrder) {
    const normalizedKey = String(key || "");
    if (!knownKeys.has(normalizedKey) || seen.has(normalizedKey)) continue;
    seen.add(normalizedKey);
    normalizedOrder.push(normalizedKey);
  }

  for (const key of fallbackOrder) {
    if (!seen.has(key)) normalizedOrder.push(key);
  }

  const visibility: Record<string, boolean> = {};
  const size: Record<string, DashboardWidgetSize> = {};

  for (const definition of ADMIN_DASHBOARD_WIDGETS) {
    const key = definition.widgetKey;
    visibility[key] =
      typeof layout?.visibility?.[key] === "boolean"
        ? Boolean(layout?.visibility?.[key])
        : definition.defaultVisible;

    const rawSize = String(layout?.size?.[key] || "").toUpperCase();
    size[key] =
      rawSize === "S" || rawSize === "M" || rawSize === "L"
        ? (rawSize as DashboardWidgetSize)
        : definition.defaultSize;
  }

  return {
    order: normalizedOrder,
    visibility,
    size,
  };
}

function reorderKeys(order: string[], draggedKey: string, targetKey: string): string[] {
  if (draggedKey === targetKey) return order;
  const next = order.slice();
  const fromIndex = next.indexOf(draggedKey);
  const toIndex = next.indexOf(targetKey);
  if (fromIndex === -1 || toIndex === -1) return order;
  next.splice(fromIndex, 1);
  next.splice(toIndex, 0, draggedKey);
  return next;
}

function iconForWidget(widgetKey: string) {
  const cls = "text-[#FA5014]";
  if (widgetKey.includes("users")) return <Users size={22} class={cls} />;
  if (widgetKey.includes("companies")) return <Building2 size={22} class={cls} />;
  if (widgetKey.includes("leads")) return <TrendingUp size={22} class={cls} />;
  if (widgetKey.includes("credits")) return <Coins size={22} class={cls} />;
  if (widgetKey.includes("revenue")) return <BarChart3 size={22} class={cls} />;
  if (widgetKey.includes("approvals")) return <CircleDashed size={22} class={cls} />;
  return <LineChart size={22} class={cls} />;
}

function badgeClass(state: WidgetStateKind): string {
  if (state === "live") return "border-[#FDBA8C] bg-[#FFF1EB] text-[#FA5014]";
  if (state === "pending") return "border-[#D1D5DB] bg-[#F3F4F6] text-[#6B7280]";
  return "border-[#E5E7EB] bg-white text-[#6B7280]";
}

function widgetSpan(mode: GridLayoutMode): string {
  return mode === "3x3" ? "xl:col-span-4" : "xl:col-span-3";
}

function EmptyPreview() {
  return (
    <div class="flex h-full flex-col items-center justify-center">
      <CircleDashed size={22} class="text-[#FA5014]" />
      <div class="mt-3 text-2xl font-bold leading-none text-[#9CA3AF]">--</div>
    </div>
  );
}

function PendingPreview() {
  return (
    <div class="flex h-full flex-col items-center justify-center gap-3">
      <LineChart size={22} class="text-[#FA5014]" />
      <div class="w-full max-w-[130px] space-y-2">
        <div class="h-2 rounded bg-[#E5E7EB]" />
        <div class="h-2 w-5/6 rounded bg-[#E5E7EB]" />
        <div class="h-2 w-4/6 rounded bg-[#E5E7EB]" />
      </div>
    </div>
  );
}

function LivePreview(props: { value?: string; trend?: string; trendUp?: boolean }) {
  return (
    <div class="flex h-full flex-col items-center justify-center">
      <p class="text-[26px] font-bold leading-none text-[#111827]">{props.value || "0"}</p>
      <p class="mt-2 inline-flex items-center gap-1 text-xs font-semibold text-[#FA5014]">
        {props.trendUp ? "↗" : "↘"} {props.trend || "0%"}
      </p>
    </div>
  );
}

export default function AdminHomePage() {
  const [searchParams] = useSearchParams();
  const [layout, setLayout] = createSignal<RuntimeDashboardLayout>(sanitizeLayout(DEFAULT_LAYOUT));
  const [settingsOpen, setSettingsOpen] = createSignal(false);
  const [isHydrating, setIsHydrating] = createSignal(true);
  const [isAutoSaving, setIsAutoSaving] = createSignal(false);
  const [autoSaveNotice, setAutoSaveNotice] = createSignal("");
  const [lastSavedSnapshot, setLastSavedSnapshot] = createSignal("");
  const [draggingKey, setDraggingKey] = createSignal<string | null>(null);
  const [openMenuId, setOpenMenuId] = createSignal<string | null>(null);

  const [search, setSearch] = createSignal("");
  const [filterMode, setFilterMode] = createSignal<FilterMode>("all");
  const [sortMode, setSortMode] = createSignal<SortMode>("layout");
  const [gridLayout, setGridLayout] = createSignal<GridLayoutMode>("3x4");

  const [metrics] = createResource(fetchMetrics);

  const getWidgetState = (key: string) => {
    if (key.startsWith("kpi_")) {
      const idMap: Record<string, string> = {
        kpi_total_users: "users",
        kpi_active_companies: "companies",
        kpi_open_leads: "leads",
        kpi_pending_approvals: "approvals",
        kpi_total_revenue: "revenue",
        kpi_credits_purchased: "credits",
      };
      if (metrics.loading) return { state: "pending", statusLabel: "Loading..." };
      // Guard against error state — accessing metrics() when errored throws.
      if (metrics.error) return { state: "empty", statusLabel: "No Data" };
      const m = metrics()?.kpis?.find((k: any) => k.id === idMap[key]);
      if (m) return { state: "live", statusLabel: "Live Data", data: m };
      return { state: "empty", statusLabel: "No Data" };
    }
    if (metrics.loading) return { state: "pending", statusLabel: "Loading..." };
    if (metrics.error) return { state: "empty", statusLabel: "No Data" };
    const m = metrics();
    if (key === "chart_leads_trend") {
      const data = m?.trend_series;
      if (data && data.length > 0)
        {return { state: "live", statusLabel: "Live Data", data: { trend_series: data } };}
      return { state: "empty", statusLabel: "No Data" };
    }
    if (key === "chart_revenue_overview") {
      const data = m?.rev_series;
      if (data && data.length > 0)
        {return { state: "live", statusLabel: "Live Data", data: { rev_series: data } };}
      return { state: "empty", statusLabel: "No Data" };
    }
    const meta = WIDGET_META[key];
    return { state: meta?.state || "empty", statusLabel: meta?.statusLabel || "No Data" };
  };

  const orderedWidgets = createMemo(() => {
    const current = layout();
    const rows = current.order
      .map((key) => WIDGET_DEFINITION_MAP[key])
      .filter((definition): definition is DashboardWidgetDefinition => Boolean(definition))
      .filter((definition) => current.visibility[definition.widgetKey] !== false)
      .filter((definition) => {
        const query = search().trim().toLowerCase();
        if (!query) return true;
        const meta = WIDGET_META[definition.widgetKey];
        return (
          definition.title.toLowerCase().includes(query) ||
          definition.moduleKey.toLowerCase().includes(query) ||
          (meta?.subtitle || "").toLowerCase().includes(query)
        );
      })
      .filter((definition) => {
        const mode = filterMode();
        if (mode === "all") return true;
        return (WIDGET_META[definition.widgetKey]?.type || "summary") === mode;
      });

    const mode = sortMode();
    if (mode === "layout") return rows;

    const next = rows.slice();
    next.sort((a, b) => {
      if (mode === "name") return a.title.localeCompare(b.title);
      const rank = (key: string) => {
        const info = getWidgetState(key);
        if (info.state === "live") return 1;
        if (info.state === "empty") return 2;
        return 3;
      };
      return rank(a.widgetKey) - rank(b.widgetKey);
    });

    return next;
  });

  onMount(async () => {
    try {
      const persistedLayout = await loadAdminDashboardLayout();
      const normalized = sanitizeLayout(persistedLayout || DEFAULT_LAYOUT);
      setLayout(normalized);
      setLastSavedSnapshot(JSON.stringify(normalized));
    } finally {
      setIsHydrating(false);
    }
  });

  createEffect(() => {
    if (isHydrating()) return;
    const nextLayout = layout();
    const nextSnapshot = JSON.stringify(nextLayout);
    if (nextSnapshot === lastSavedSnapshot()) return;

    setIsAutoSaving(true);
    setAutoSaveNotice("");

    const timer = setTimeout(async () => {
      const ok = await saveAdminDashboardLayout(nextLayout);
      setIsAutoSaving(false);
      if (ok) {
        setLastSavedSnapshot(nextSnapshot);
        setAutoSaveNotice("Layout saved automatically.");
      } else {
        setAutoSaveNotice("Auto-save failed. Please try again.");
      }
    }, 450);

    onCleanup(() => clearTimeout(timer));
  });

  const setWidgetVisibility = (widgetKey: string, visible: boolean) => {
    setLayout((current) => ({
      ...current,
      visibility: {
        ...current.visibility,
        [widgetKey]: visible,
      },
    }));
  };

  const resetLayout = () => {
    const normalized = sanitizeLayout(DEFAULT_LAYOUT);
    setLayout(normalized);
    setAutoSaveNotice("Layout reset to default.");
  };

  const handleDragStart = (event: DragEvent, widgetKey: string) => {
    event.dataTransfer?.setData("text/plain", widgetKey);
    if (event.dataTransfer) event.dataTransfer.effectAllowed = "move";
    setDraggingKey(widgetKey);
  };

  const handleDrop = (event: DragEvent, targetKey: string) => {
    event.preventDefault();
    const dragged = event.dataTransfer?.getData("text/plain") || draggingKey();
    if (!dragged) return;

    setLayout((current) => ({
      ...current,
      order: reorderKeys(current.order, dragged, targetKey),
    }));
    setDraggingKey(null);
  };

  return (
    <div class="w-full">
      <Show when={Boolean(searchParams.denied)}>
        <div
          class="rounded-2xl border border-[#E5E7EB] bg-white shadow-sm"
          style="margin-bottom: 18px"
        >
          <p class="notice">
            You don’t have access to {String(searchParams.denied || "").replace(/_/g, " ")}.
          </p>
        </div>
      </Show>
      <Show when={Boolean(metrics.error)}>
        <div
          class="rounded-2xl border border-[#FECACA] bg-[#FEF2F2] px-6 py-4 text-[13px] font-medium text-[#B91C1C] shadow-sm"
          style="margin-bottom: 18px"
        >
          Failed to load dashboard metrics. Widgets below may show stale or missing data — try
          refreshing the page.
        </div>
      </Show>
      <div
        class="rounded-2xl border border-[#E5E7EB] bg-white px-6 py-5 shadow-sm md:px-8"
        style="margin-bottom: 28px"
      >
        <div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <h1 class="text-[22px] font-bold leading-tight text-[#111827]">Dashboard Overview</h1>
            <p class="mt-0.5 text-[13px] text-[#6B7280]">
              Manage widget layout, visibility, sizing, and dashboard presentation
            </p>
          </div>

          <div class="flex shrink-0">
            <button
              type="button"
              class="inline-flex h-9 items-center gap-1.5 whitespace-nowrap rounded-xl bg-[#0D0D2A] px-5 text-[13px] font-semibold leading-none text-white shadow-sm"
              onClick={() => {
                const next = !settingsOpen();
                setSettingsOpen(next);
                if (!next) setOpenMenuId(null);
              }}
            >
              <Settings2 size={14} class="text-[#FA5014]" />
              {settingsOpen() ? "Close Settings" : "Customize Widgets"}
            </button>
          </div>
        </div>
      </div>

      <Show when={settingsOpen()}>
        <div class="rounded-2xl border border-[#E5E7EB] bg-white p-6 shadow-sm md:p-7">
          {/* Settings header */}
          <div class="flex flex-wrap items-start justify-between gap-4">
            <div>
              <h2 class="text-[15px] font-semibold text-[#111827]">Widget Settings</h2>
              <p class="mt-1 text-[13px] text-[#6B7280]">
                Choose visible widgets and select a grid layout.
              </p>
            </div>
            <button
              type="button"
              class="inline-flex h-9 items-center gap-1.5 rounded-lg border border-[#E5E7EB] bg-white px-3 text-xs font-semibold text-[#111827] shadow-sm"
              onClick={resetLayout}
            >
              <RotateCcw size={13} class="text-[#FA5014]" />
              Reset Layout
            </button>
          </div>

          {/* Filter controls */}
          <div class="mt-5 flex flex-wrap gap-3">
            <div class="relative min-w-[200px] flex-1">
              <Search
                size={14}
                class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[#FA5014]"
                style="z-index:1"
              />
              <input
                value={search()}
                onInput={(event) => setSearch(event.currentTarget.value)}
                placeholder="Search widgets"
                class="h-10 w-full rounded-lg border border-[#E5E7EB] bg-white pl-10 pr-3 text-sm text-[#111827] outline-none focus:border-[#FA5014]"
              />
            </div>

            <select
              class="h-10 rounded-lg border border-[#E5E7EB] bg-white px-3 text-sm text-[#111827]"
              value={filterMode()}
              onChange={(event) => setFilterMode(event.currentTarget.value as FilterMode)}
            >
              <option value="all">All Widgets</option>
              <option value="summary">Summary Only</option>
              <option value="analytics">Analytical Only</option>
            </select>

            <select
              class="h-10 rounded-lg border border-[#E5E7EB] bg-white px-3 text-sm text-[#111827]"
              value={sortMode()}
              onChange={(event) => setSortMode(event.currentTarget.value as SortMode)}
            >
              <option value="layout">Layout Order</option>
              <option value="name">Name</option>
              <option value="status">Status</option>
            </select>

            <select
              class="h-10 rounded-lg border border-[#E5E7EB] bg-white px-3 text-sm text-[#111827]"
              value={gridLayout()}
              onChange={(event) => setGridLayout(event.currentTarget.value as GridLayoutMode)}
            >
              <option value="3x4">Grid 3 × 4</option>
              <option value="3x3">Grid 3 × 3</option>
            </select>
          </div>

          {/* Widget list */}
          <div class="mt-5 grid gap-3 md:grid-cols-2">
            <For each={ADMIN_DASHBOARD_WIDGETS}>
              {(definition) => {
                const visible = () => layout().visibility[definition.widgetKey] !== false;
                const meta = WIDGET_META[definition.widgetKey];
                const stateInfo = getWidgetState(definition.widgetKey);
                const state = stateInfo.state;

                return (
                  <div class="flex items-center justify-between gap-4 rounded-xl border border-[#E5E7EB] bg-[#F9FAFB] px-4 py-4">
                    <div class="flex items-center gap-3 min-w-0">
                      <div class="shrink-0 text-[#FA5014]">
                        {iconForWidget(definition.widgetKey)}
                      </div>
                      <div class="min-w-0">
                        <p class="text-sm font-semibold text-[#111827]">{definition.title}</p>
                        <p class="mt-0.5 text-[11px] font-medium uppercase tracking-wide text-[#9CA3AF]">
                          {definition.moduleKey}
                        </p>
                      </div>
                    </div>
                    <div class="flex shrink-0 items-center gap-2">
                      <span
                        class={`hidden rounded-full border px-2 py-0.5 text-[10px] font-semibold sm:inline-flex ${badgeClass(state as WidgetStateKind)}`}
                      >
                        {stateInfo.statusLabel}
                      </span>
                      <button
                        type="button"
                        class={`inline-flex h-8 items-center gap-1.5 rounded-md border px-3 text-xs font-semibold ${
                          visible()
                            ? "border-[#FDBA8C] bg-[#FFF1EB] text-[#FA5014]"
                            : "border-[#E5E7EB] bg-white text-[#6B7280]"
                        }`}
                        onClick={() => setWidgetVisibility(definition.widgetKey, !visible())}
                      >
                        {visible() ? <Eye size={12} /> : <EyeOff size={12} />}
                        {visible() ? "Visible" : "Hidden"}
                      </button>
                    </div>
                  </div>
                );
              }}
            </For>
          </div>

          <Show when={isAutoSaving() || autoSaveNotice()}>
            <p class="mt-4 text-xs text-[#6B7280]">
              {isAutoSaving() ? "Saving layout..." : autoSaveNotice()}
            </p>
          </Show>
        </div>
      </Show>

      <div class="grid grid-cols-1 gap-5 xl:grid-cols-12" style="margin-top: 28px">
        <For each={orderedWidgets()}>
          {(definition) => {
            const meta = WIDGET_META[definition.widgetKey];
            const stateInfo = getWidgetState(definition.widgetKey);
            const state = stateInfo.state;
            const isOpenMenu = () => openMenuId() === definition.widgetKey;

            return (
              <section
                draggable={settingsOpen()}
                onDragStart={(event) => handleDragStart(event, definition.widgetKey)}
                onDragOver={(event) => event.preventDefault()}
                onDrop={(event) => handleDrop(event, definition.widgetKey)}
                onDragEnd={() => setDraggingKey(null)}
                class={`relative aspect-square min-h-[235px] rounded-2xl border border-[#E5E7EB] bg-white p-5 shadow-sm md:min-h-[260px] md:p-6 ${widgetSpan(gridLayout())} ${
                  state === "pending" ? "opacity-95" : ""
                } ${draggingKey() === definition.widgetKey ? "opacity-60" : ""}`}
              >
                <Show when={settingsOpen()}>
                  <>
                    <button
                      type="button"
                      class="absolute left-3 top-3 inline-flex h-8 w-8 items-center justify-center rounded-md border border-[#E5E7EB] bg-white cursor-grab text-[#FA5014]"
                      aria-label="Drag to reorder"
                    >
                      <GripVertical size={14} class="text-[#FA5014]" />
                    </button>
                    <div class="absolute right-3 top-3">
                      <button
                        type="button"
                        class="inline-flex h-8 w-8 items-center justify-center rounded-md border border-[#E5E7EB] bg-white text-[#FA5014]"
                        onClick={() => setOpenMenuId(isOpenMenu() ? null : definition.widgetKey)}
                      >
                        <EllipsisVertical size={14} class="text-[#FA5014]" />
                      </button>

                      <Show when={isOpenMenu()}>
                        <div class="absolute right-0 top-10 z-20 w-40 rounded-lg border border-[#E5E7EB] bg-white p-1 shadow-md">
                          <For each={["Edit Widget", "Duplicate Widget", "Hide Widget", "Remove Widget"]}>
                            {(item) => (
                              <button
                                type="button"
                                class="block w-full rounded-md px-2 py-2 text-left text-xs font-medium text-[#111827] hover:bg-[#F9FAFB]"
                                onClick={() => setOpenMenuId(null)}
                              >
                                {item}
                              </button>
                            )}
                          </For>
                        </div>
                      </Show>
                    </div>
                  </>
                </Show>

                <div class="flex h-full flex-col items-center justify-center px-4">
                  <div class="mb-3 text-[#FA5014]">{iconForWidget(definition.widgetKey)}</div>
                  <h3 class="text-center text-[15px] font-semibold text-[#111827]">
                    {definition.title}
                  </h3>
                  <div class="mt-4 h-[116px] w-full max-w-[210px] rounded-xl border border-[#E5E7EB] bg-[#F9FAFB] p-4">
                    <Show when={state === "live"}>
                      <LivePreview
                        value={stateInfo.data?.value}
                        trend={stateInfo.data?.trend}
                        trendUp={stateInfo.data?.trendUp}
                      />
                    </Show>
                    <Show when={state === "empty"}>
                      <EmptyPreview />
                    </Show>
                    <Show when={state === "pending"}>
                      <PendingPreview />
                    </Show>
                  </div>
                  <span
                    class={`mt-4 inline-flex rounded-full border px-2 py-1 text-[11px] font-semibold ${badgeClass(state as WidgetStateKind)}`}
                  >
                    {stateInfo.statusLabel}
                  </span>
                </div>
              </section>
            );
          }}
        </For>
      </div>
    </div>
  );
}
