"use client";

import React, { useRef, useState, useEffect } from "react";
import { ComponentData } from "@/types/screen";
import { useResponsive } from "@/lib/hooks/useResponsive";
import { cn } from "@/lib/utils";

interface ResponsiveGridRendererProps {
  components: ComponentData[];
  canvasWidth: number;
  canvasHeight: number;
  renderComponent: (component: ComponentData) => React.ReactNode;
}

const FULL_WIDTH_TYPES = new Set([
  "table-list",
  "v2-table-list",
  "table-search-widget",
  "v2-table-search-widget",
  "conditional-container",
  "split-panel-layout",
  "split-panel-layout2",
  "v2-split-panel-layout",
  "screen-split-panel",
  "v2-split-line",
  "flow-widget",
  "v2-tab-container",
  "tab-container",
  "tabs-widget",
  "v2-tabs-widget",
]);

const FLEX_GROW_TYPES = new Set([
  "table-list",
  "v2-table-list",
  "split-panel-layout",
  "split-panel-layout2",
  "v2-split-panel-layout",
  "screen-split-panel",
  "v2-tab-container",
  "tab-container",
  "tabs-widget",
  "v2-tabs-widget",
]);

function groupComponentsIntoRows(
  components: ComponentData[],
  threshold: number = 30
): ComponentData[][] {
  if (components.length === 0) return [];
  const sorted = [...components].sort((a, b) => a.position.y - b.position.y);
  const rows: ComponentData[][] = [];
  let currentRow: ComponentData[] = [];
  let currentRowY = -Infinity;

  for (const comp of sorted) {
    if (comp.position.y - currentRowY > threshold) {
      if (currentRow.length > 0) rows.push(currentRow);
      currentRow = [comp];
      currentRowY = comp.position.y;
    } else {
      currentRow.push(comp);
    }
  }
  if (currentRow.length > 0) rows.push(currentRow);
  return rows.map((row) => row.sort((a, b) => a.position.x - b.position.x));
}

function getComponentTypeId(component: ComponentData): string {
  const direct =
    (component as any).componentType || (component as any).widgetType;
  if (direct) return direct;
  const url = (component as any).url;
  if (url && typeof url === "string") {
    const parts = url.split("/");
    return parts[parts.length - 1];
  }
  return component.type || "";
}

function isButtonComponent(component: ComponentData): boolean {
  return getComponentTypeId(component).includes("button");
}

function isFullWidthComponent(component: ComponentData): boolean {
  return FULL_WIDTH_TYPES.has(getComponentTypeId(component));
}

function shouldFlexGrow(component: ComponentData): boolean {
  return FLEX_GROW_TYPES.has(getComponentTypeId(component));
}

function getPercentageWidth(componentWidth: number, canvasWidth: number): number {
  const pct = (componentWidth / canvasWidth) * 100;
  return pct >= 95 ? 100 : pct;
}

function getRowGap(row: ComponentData[], canvasWidth: number): number {
  if (row.length < 2) return 0;
  const totalW = row.reduce((s, c) => s + (c.size?.width || 100), 0);
  const gap = canvasWidth - totalW;
  const cnt = row.length - 1;
  if (gap <= 0 || cnt <= 0) return 8;
  return Math.min(Math.max(Math.round(gap / cnt), 4), 24);
}

interface ProcessedRow {
  type: "normal" | "fullwidth";
  mainComponent?: ComponentData;
  overlayComps: ComponentData[];
  normalComps: ComponentData[];
}

function FullWidthOverlayRow({
  main,
  overlayComps,
  canvasWidth,
  renderComponent,
}: {
  main: ComponentData;
  overlayComps: ComponentData[];
  canvasWidth: number;
  renderComponent: (component: ComponentData) => React.ReactNode;
}) {
  const containerRef = useRef<HTMLDivElement>(null);
  const [containerW, setContainerW] = useState(0);

  useEffect(() => {
    const el = containerRef.current;
    if (!el) return;
    const ro = new ResizeObserver((entries) => {
      const w = entries[0]?.contentRect.width;
      if (w && w > 0) setContainerW(w);
    });
    ro.observe(el);
    return () => ro.disconnect();
  }, []);

  const compFlexGrow = shouldFlexGrow(main);
  const mainY = main.position.y;
  const scale = containerW > 0 ? containerW / canvasWidth : 1;

  const minButtonY = Math.min(...overlayComps.map((c) => c.position.y));
  const rawYOffset = minButtonY - mainY;
  const maxBtnH = Math.max(
    ...overlayComps.map((c) => c.size?.height || 40)
  );
  const yOffset = rawYOffset + (maxBtnH / 2) * (1 - scale);

  return (
    <div
      ref={containerRef}
      className={cn(
        "relative flex w-full flex-col",
        compFlexGrow ? "min-h-0 flex-1" : "flex-shrink-0"
      )}
    >
      <div
        data-component-id={main.id}
        data-component-type={getComponentTypeId(main)}
        className="min-h-0 min-w-0"
        style={{
          width: "100%",
          height: compFlexGrow ? "100%" : "auto",
          minHeight: compFlexGrow ? "300px" : undefined,
          flexGrow: 1,
        }}
      >
        {renderComponent(main)}
      </div>

      {overlayComps.length > 0 && containerW > 0 && (
        <div
          className="pointer-events-none absolute left-0 z-10"
          style={{
            top: `${yOffset}px`,
            width: `${canvasWidth}px`,
            height: `${maxBtnH}px`,
            transform: `scale(${scale})`,
            transformOrigin: "top left",
          }}
        >
          {overlayComps.map((comp) => (
            <div
              key={comp.id}
              data-component-id={comp.id}
              data-component-type={getComponentTypeId(comp)}
              className="pointer-events-auto absolute"
              style={{
                left: `${comp.position.x}px`,
                top: `${comp.position.y - minButtonY}px`,
                width: `${comp.size?.width || 90}px`,
                height: `${comp.size?.height || 40}px`,
              }}
            >
              {renderComponent(comp)}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

export function ResponsiveGridRenderer({
  components,
  canvasWidth,
  canvasHeight,
  renderComponent,
}: ResponsiveGridRendererProps) {
  const { isMobile } = useResponsive();

  const topLevel = components.filter((c) => !c.parentId);

  const rows = groupComponentsIntoRows(topLevel);
  const processedRows: ProcessedRow[] = [];

  for (const row of rows) {
    const fullWidthComps: ComponentData[] = [];
    const normalComps: ComponentData[] = [];

    for (const comp of row) {
      if (isFullWidthComponent(comp)) {
        fullWidthComps.push(comp);
      } else {
        normalComps.push(comp);
      }
    }

    if (fullWidthComps.length > 0 && normalComps.length > 0) {
      for (const fwComp of fullWidthComps) {
        processedRows.push({
          type: "fullwidth",
          mainComponent: fwComp,
          overlayComps: normalComps,
          normalComps: [],
        });
      }
    } else if (fullWidthComps.length > 0) {
      for (const fwComp of fullWidthComps) {
        processedRows.push({
          type: "fullwidth",
          mainComponent: fwComp,
          overlayComps: [],
          normalComps: [],
        });
      }
    } else {
      processedRows.push({
        type: "normal",
        overlayComps: [],
        normalComps,
      });
    }
  }

  return (
    <div
      data-screen-runtime="true"
      className="bg-background flex h-full w-full flex-col overflow-x-hidden"
      style={{ minHeight: "200px" }}
    >
      {processedRows.map((processedRow, rowIndex) => {
        if (processedRow.type === "fullwidth" && processedRow.mainComponent) {
          return (
            <FullWidthOverlayRow
              key={`row-${rowIndex}`}
              main={processedRow.mainComponent}
              overlayComps={processedRow.overlayComps}
              canvasWidth={canvasWidth}
              renderComponent={renderComponent}
            />
          );
        }

        const { normalComps } = processedRow;
        const allButtons = normalComps.every((c) => isButtonComponent(c));
        const gap = isMobile ? 8 : allButtons ? 8 : getRowGap(normalComps, canvasWidth);

        const hasFlexHeightComp = normalComps.some((c) => {
          const h = c.size?.height || 0;
          return h / canvasHeight >= 0.8;
        });

        return (
          <div
            key={`row-${rowIndex}`}
            className={cn(
              "flex w-full flex-wrap overflow-hidden",
              allButtons && "justify-end px-2 py-1",
              hasFlexHeightComp ? "min-h-0 flex-1" : "flex-shrink-0"
            )}
            style={{ gap: `${gap}px` }}
          >
            {normalComps.map((component) => {
              const typeId = getComponentTypeId(component);
              const isButton = isButtonComponent(component);
              const isFullWidth = isMobile && !isButton;

              if (isButton) {
                return (
                  <div
                    key={component.id}
                    data-component-id={component.id}
                    data-component-type={typeId}
                    className="flex-shrink-0"
                    style={{
                      height: component.size?.height
                        ? `${component.size.height}px`
                        : "40px",
                    }}
                  >
                    {renderComponent(component)}
                  </div>
                );
              }

              const percentWidth = isFullWidth
                ? 100
                : getPercentageWidth(component.size?.width || 100, canvasWidth);
              const flexBasis = isFullWidth
                ? "100%"
                : `calc(${percentWidth}% - ${gap}px)`;

              const heightPct = (component.size?.height || 0) / canvasHeight;
              const useFlexHeight = heightPct >= 0.8;

              return (
                <div
                  key={component.id}
                  data-component-id={component.id}
                  data-component-type={typeId}
                  className={cn("min-w-0 overflow-hidden", useFlexHeight && "min-h-0 flex-1")}
                  style={{
                    width: isFullWidth ? "100%" : undefined,
                    flexBasis: useFlexHeight ? undefined : flexBasis,
                    flexGrow: 1,
                    flexShrink: 1,
                    minWidth: isMobile ? "100%" : undefined,
                    minHeight: useFlexHeight ? "300px" : undefined,
                    height: useFlexHeight ? "100%" : (component.size?.height
                      ? `${component.size.height}px`
                      : "auto"),
                  }}
                >
                  {renderComponent(component)}
                </div>
              );
            })}
          </div>
        );
      })}
    </div>
  );
}

export default ResponsiveGridRenderer;
