import { useEffect, useMemo, useState } from "react";
import { RefreshCw, RotateCcw, SlidersHorizontal } from "lucide-react";
import {
  Button,
  Card,
  MetricCard,
  PageTitle,
  dashboardWidgetsForModules,
  hasAnyScope,
  hasScope,
  usePlatformModules,
  type ApiSettings,
  type AuthInfo,
  type DashboardWidgetContribution,
  type DashboardWidgetSize
} from "@govoplan/core-webui";

type DashboardLayout = {
  visible: string[];
  known: string[];
};

export default function DashboardPage({ settings, auth }: { settings: ApiSettings; auth: AuthInfo }) {
  const modules = usePlatformModules();
  const widgets = useMemo(() => dashboardWidgetsForModules(modules).filter((widget) => canUseWidget(auth, widget)), [auth, modules]);
  const widgetSignature = widgets.map((widget) => widget.id).join("|");
  const storageKey = `govoplan.dashboard.layout:${auth.active_tenant?.id ?? auth.tenant.id}:${auth.user.id}`;
  const [layout, setLayout] = useState<DashboardLayout>(() => defaultLayout(widgets));
  const [configuring, setConfiguring] = useState(false);
  const [refreshKey, setRefreshKey] = useState(0);

  useEffect(() => {
    setLayout(readLayout(storageKey) ?? defaultLayout(widgets));
  }, [storageKey, widgetSignature]);

  const visibleWidgetIds = useMemo(() => {
    const known = new Set(layout.known);
    const visible = new Set(layout.visible);
    for (const widget of widgets) {
      if (!known.has(widget.id) && widget.defaultVisible !== false) visible.add(widget.id);
    }
    const availableIds = new Set(widgets.map((widget) => widget.id));
    return widgets.map((widget) => widget.id).filter((id) => availableIds.has(id) && visible.has(id));
  }, [layout, widgets]);
  const visibleWidgets = widgets.filter((widget) => visibleWidgetIds.includes(widget.id));
  const hiddenCount = Math.max(widgets.length - visibleWidgets.length, 0);

  function saveLayout(next: DashboardLayout) {
    setLayout(next);
    writeLayout(storageKey, next);
  }

  function setWidgetVisible(widgetId: string, visible: boolean) {
    const allIds = widgets.map((widget) => widget.id);
    const nextVisible = new Set(visibleWidgetIds);
    if (visible) {
      nextVisible.add(widgetId);
    } else {
      nextVisible.delete(widgetId);
    }
    saveLayout({
      known: allIds,
      visible: allIds.filter((id) => nextVisible.has(id))
    });
  }

  function resetLayout() {
    saveLayout(defaultLayout(widgets));
  }

  return (
    <div className="content-pad workspace-data-page dashboard-page">
      <div className="page-heading split workspace-heading">
        <div>
          <PageTitle>i18n:govoplan-dashboard.dashboard.3f8b4df2</PageTitle>
          <p>Personal workspace assembled from installed module widgets.</p>
        </div>
        <div className="button-row compact-actions">
          <Button onClick={() => setRefreshKey((value) => value + 1)}><RefreshCw size={16} /> Refresh</Button>
          <Button onClick={() => setConfiguring((value) => !value)}><SlidersHorizontal size={16} /> Configure</Button>
        </div>
      </div>

      <div className="metric-grid dashboard-summary-grid">
        <MetricCard label="Installed modules" value={modules.length} tone="info" detail={moduleLabels(modules)} />
        <MetricCard label="Available widgets" value={widgets.length} tone="neutral" detail="Provided by active modules" />
        <MetricCard label="Visible widgets" value={visibleWidgets.length} tone="good" detail={hiddenCount ? `${hiddenCount} hidden` : "All shown"} />
        <MetricCard label="Layout" value="personal" tone="neutral" detail="Saved in this browser" />
      </div>

      {configuring &&
      <Card
        title="Dashboard widgets"
        actions={<Button onClick={resetLayout}><RotateCcw size={16} /> Reset</Button>}>
          {widgets.length === 0 ? <p className="muted">No installed module exposes dashboard widgets yet.</p> :
        <div className="dashboard-widget-picker">
              {widgets.map((widget) =>
          <label key={widget.id} className="dashboard-widget-toggle">
                  <input
              type="checkbox"
              checked={visibleWidgetIds.includes(widget.id)}
              onChange={(event) => setWidgetVisible(widget.id, event.currentTarget.checked)}
            />
                  <span>
                    <strong>{widget.title}</strong>
                    <small>{widget.description ?? widget.id}</small>
                  </span>
                </label>
          )}
            </div>
        }
        </Card>
      }

      {visibleWidgets.length === 0 ?
      <Card title="No widgets selected">
        <p className="muted">Open Configure and select at least one widget. Modules can add more widgets by exposing the dashboard.widgets capability.</p>
      </Card> :
      <div className="dashboard-widget-grid">
          {visibleWidgets.map((widget) =>
        <section key={widget.id} className={`dashboard-widget dashboard-widget-${widgetSize(widget)}`}>
              <Card title={widget.title} collapsible collapseKey={`dashboard-widget:${widget.id}`}>
                {widget.render({
              settings,
              auth,
              modules,
              widgetId: widget.id,
              refreshKey,
              size: widgetSize(widget)
            })}
              </Card>
            </section>
        )}
        </div>
      }
    </div>);
}

function canUseWidget(auth: AuthInfo, widget: DashboardWidgetContribution): boolean {
  if (widget.allOf?.length && !widget.allOf.every((scope) => hasScope(auth, scope))) return false;
  if (widget.anyOf?.length && !hasAnyScope(auth, widget.anyOf)) return false;
  return true;
}

function widgetSize(widget: DashboardWidgetContribution): DashboardWidgetSize {
  return widget.defaultSize ?? "medium";
}

function defaultLayout(widgets: DashboardWidgetContribution[]): DashboardLayout {
  const ids = widgets.map((widget) => widget.id);
  return {
    known: ids,
    visible: widgets.filter((widget) => widget.defaultVisible !== false).map((widget) => widget.id)
  };
}

function readLayout(storageKey: string): DashboardLayout | null {
  if (typeof window === "undefined") return null;
  try {
    const raw = window.localStorage.getItem(storageKey);
    if (!raw) return null;
    const parsed = JSON.parse(raw) as Partial<DashboardLayout>;
    if (!Array.isArray(parsed.visible) || !Array.isArray(parsed.known)) return null;
    return {
      visible: parsed.visible.filter((id): id is string => typeof id === "string"),
      known: parsed.known.filter((id): id is string => typeof id === "string")
    };
  } catch {
    return null;
  }
}

function writeLayout(storageKey: string, layout: DashboardLayout): void {
  if (typeof window === "undefined") return;
  try {
    window.localStorage.setItem(storageKey, JSON.stringify(layout));
  } catch {
    // localStorage may be unavailable in restricted browsing contexts.
  }
}

function moduleLabels(modules: Array<{ id: string }>): string {
  if (!modules.length) return "Core shell only";
  return modules.slice(0, 4).map((module) => module.id).join(", ");
}

