"use client";

import type { ComponentType, ReactNode } from "react";
import { useCallback, useMemo, useRef, useState } from "react";
import { Responsive, WidthProvider } from "react-grid-layout/legacy";
import type { DashboardGridWidget, DashboardLayoutItem } from "@/lib/dashboard-layout";

export type DashboardGridProps = {
  widgets: DashboardGridWidget[];
  editMode: boolean;
  activeMenuWidgetId?: string | null;
  renderWidget: (widget: DashboardGridWidget) => ReactNode;
  onLayoutChange: (layout: DashboardLayoutItem[]) => void;
};

const ResponsiveGridLayout = WidthProvider(Responsive) as ComponentType<any>;

const BREAKPOINTS = { lg: 1200, md: 900, sm: 600, xs: 0 };
const COLS = { lg: 48, md: 24, sm: 12, xs: 6 };

function clamp(value: number, min: number, max: number): number {
  return Math.max(min, Math.min(max, value));
}

function getWidgetMinimumSize(widget: DashboardGridWidget): { minW: number; minH: number } {
  if (widget.type === "search") {
    return { minW: 8, minH: 5 };
  }

  if (widget.type === "clock") {
    return { minW: 4, minH: 4 };
  }

  if (widget.type === "calendar") {
    return { minW: 8, minH: 6 };
  }

  if (widget.type === "calculator") {
    return { minW: 8, minH: 6 };
  }

  if (widget.type === "note") {
    return { minW: 4, minH: 5 };
  }

  return { minW: 4, minH: 4 };
}

function widgetsToLayout(widgets: DashboardGridWidget[]): DashboardLayoutItem[] {
  return widgets.map((widget) => {
    const minimumSize = getWidgetMinimumSize(widget);
    const width = clamp(widget.w, minimumSize.minW, 48);
    const height = clamp(widget.h, minimumSize.minH, 180);
    const x = clamp(widget.x, 0, 48 - width);
    const y = clamp(widget.y, 0, 10000);

    return {
      i: widget.id,
      x,
      y,
      w: width,
      h: height,
      minW: minimumSize.minW,
      minH: minimumSize.minH,
      maxW: 48,
      maxH: 180
    };
  });
}

function normalizeLayout(layout: readonly DashboardLayoutItem[]): DashboardLayoutItem[] {
  return layout.map((item) => ({
    i: String(item.i),
    x: Number.isFinite(item.x) ? item.x : 0,
    y: Number.isFinite(item.y) ? item.y : 0,
    w: Number.isFinite(item.w) ? item.w : 1,
    h: Number.isFinite(item.h) ? item.h : 1,
    minW: item.minW,
    minH: item.minH,
    maxW: item.maxW,
    maxH: item.maxH
  }));
}

export default function DashboardGrid({
  widgets,
  editMode,
  activeMenuWidgetId = null,
  renderWidget,
  onLayoutChange
}: DashboardGridProps) {
  const [currentBreakpoint, setCurrentBreakpoint] = useState("lg");
  const breakpointRef = useRef("lg");

  const isDesktop = currentBreakpoint === "lg";

  const layouts = useMemo(() => ({
    lg: widgetsToLayout(widgets)
  }), [widgets]);

  const handleBreakpointChange = useCallback((breakpoint: string) => {
    breakpointRef.current = breakpoint;
    setCurrentBreakpoint(breakpoint);
  }, []);

  const handleLayoutChange = useCallback((layout: DashboardLayoutItem[]) => {
    if (breakpointRef.current === "lg") {
      onLayoutChange(normalizeLayout(layout));
    }
  }, [onLayoutChange]);

  return (
    <div className="widgetGridShell">
      {widgets.length === 0 ? (
        <div className="emptyDashboard">
          <h2>Keine Widgets aktiv</h2>
          <p className="muted">Schalte den Bearbeitungsmodus ein und füge Widgets hinzu.</p>
        </div>
      ) : null}

      {widgets.length > 0 ? (
        <ResponsiveGridLayout
          className="widgetGrid"
          layouts={layouts}
          breakpoints={BREAKPOINTS}
          cols={COLS}
          rowHeight={8}
          margin={[12, 12]}
          containerPadding={[0, 0]}
          compactType={isDesktop ? null : "vertical"}
          preventCollision={isDesktop}
          isBounded={false}
          autoSize={true}
          isDraggable={editMode && isDesktop}
          isResizable={editMode && isDesktop}
          draggableHandle=".widgetDragHandle"
          draggableCancel=".widgetNoDrag"
          resizeHandles={["se"]}
          measureBeforeMount={true}
          onBreakpointChange={handleBreakpointChange}
          onLayoutChange={handleLayoutChange}
        >
          {widgets.map((widget) => (
            <div
              key={widget.id}
              className={activeMenuWidgetId === widget.id ? "gridItemMenuOpen" : ""}
            >
              {renderWidget(widget)}
            </div>
          ))}
        </ResponsiveGridLayout>
      ) : null}
    </div>
  );
}
