import React, { useEffect, useMemo, useRef, useState } from "react";
import { useWidgetStore } from "../../../store/useWidgetStore";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import { DraggableWidget } from "./DraggableWidget";
import { arrayMove } from "@dnd-kit/sortable";
import { addingWidgets } from "../../../services/realTimeVisulization/zoneData/addWidgets";
import { useAsset3dWidget, useSocketStore } from "../../../store/store";

type Side = "top" | "bottom" | "left" | "right";

interface Widget {
  id: string;
  type: string;
  title: string;
  panel: Side;
  data: any;
}

interface PanelProps {
  selectedZone: {
    zoneName: string;
    activeSides: Side[];
    panelOrder: Side[];
    lockedPanels: Side[];
    zoneId: string;
    zoneViewPortTarget: number[];
    zoneViewPortPosition: number[];
    widgets: Widget[];
  };
  setSelectedZone: React.Dispatch<
    React.SetStateAction<{
      zoneName: string;
      activeSides: Side[];
      panelOrder: Side[];

      lockedPanels: Side[];
      zoneId: string;
      zoneViewPortTarget: number[];
      zoneViewPortPosition: number[];
      widgets: Widget[];
    }>
  >;
  hiddenPanels: string[];
  setZonesData: React.Dispatch<React.SetStateAction<any>>; // Add this line
}

const generateUniqueId = () =>
  `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

const Panel: React.FC<PanelProps> = ({
  selectedZone,
  setSelectedZone,
  hiddenPanels,
  setZonesData,
}) => {
  const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
  const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
  const [panelDimensions, setPanelDimensions] = useState<{
    [side in Side]?: { width: number; height: number };
  }>({});
  const [openKebabId, setOpenKebabId] = useState<string | null>(null);

  const { isPlaying } = usePlayButtonStore();
  const { visualizationSocket } = useSocketStore();

  const [canvasDimensions, setCanvasDimensions] = useState({
    width: 0,
    height: 0,
  });
  // Track canvas dimensions
  useEffect(() => {
    const canvas = document.getElementById("real-time-vis-canvas");
    if (!canvas) return;

    const updateCanvasDimensions = () => {
      const rect = canvas.getBoundingClientRect();
      setCanvasDimensions({
        width: rect.width,
        height: rect.height,
      });
    };

    // Initial measurement
    updateCanvasDimensions();

    // Set up ResizeObserver to track changes
    const resizeObserver = new ResizeObserver(updateCanvasDimensions);
    resizeObserver.observe(canvas);

    return () => {
      resizeObserver.unobserve(canvas);
    };
  }, []);

  useEffect(() => {
    const canvas = document.getElementById("real-time-vis-canvas");
    if (!canvas) return;

    const updateCanvasDimensions = () => {
      const rect = canvas.getBoundingClientRect();
      setCanvasDimensions({
        width: rect.width,
        height: rect.height,
      });
    };

    // Initial measurement
    updateCanvasDimensions();

    // Set up ResizeObserver to track changes
    const resizeObserver = new ResizeObserver(updateCanvasDimensions);
    resizeObserver.observe(canvas);

    return () => {
      resizeObserver.unobserve(canvas);
    };
  }, []);

  const getPanelStyle = useMemo(
    () => (side: Side) => {
      const currentIndex = selectedZone.panelOrder.indexOf(side);
      const previousPanels = selectedZone.panelOrder.slice(0, currentIndex);
      const leftActive = previousPanels.includes("left");
      const rightActive = previousPanels.includes("right");
      const topActive = previousPanels.includes("top");
      const bottomActive = previousPanels.includes("bottom");

      // Dynamic panel sizes based on canvas width
      const panelSizeWidth = isPlaying ? Math.max(canvasDimensions.width * 0.14, 200) : Math.max(canvasDimensions.width * 0.165, 200); // Ensure minimum width of 200px
      const panelSizeHeight = isPlaying ? Math.max(canvasDimensions.width * 0.13, 200) : Math.max(canvasDimensions.width * 0.13, 200); // Ensure minimum height of 200px

      switch (side) {
        case "top":
        case "bottom":
          return {
            // minWidth: "200px", // Minimum width constraint
            width: `calc(100% - ${(leftActive ? panelSizeWidth : 0) +
              (rightActive ? panelSizeWidth : 0)
              }px)`,
            minHeight: "200px", // Minimum height constraint
            height: `${panelSizeHeight - 2}px`, // Subtracting for border or margin
            left: leftActive ? `${panelSizeWidth}px` : "0",
            right: rightActive ? `${panelSizeWidth}px` : "0",
            [side]: "0",
          };

        case "left":
        case "right":
          return {
            minWidth: "200px", // Minimum width constraint
            width: `${panelSizeWidth - 2}px`, // Subtracting for border or margin
            // minHeight: "200px", // Minimum height constraint
            height: `calc(100% - ${(topActive ? panelSizeHeight : 0) +
              (bottomActive ? panelSizeHeight : 0)
              }px)`,
            top: topActive ? `${panelSizeHeight}px` : "0",
            bottom: bottomActive ? `${panelSizeHeight}px` : "0",
            [side]: "0",
          };

        default:
          return {};
      }
    },
    [
      selectedZone.panelOrder,
      isPlaying,
      canvasDimensions.width,
      canvasDimensions.height,
    ]
  );

  const handleDrop = (e: React.DragEvent, panel: Side) => {
    e.preventDefault();
    const { draggedAsset } = useWidgetStore.getState();
    if (!draggedAsset) return;
    if (isPanelLocked(panel)) return;

    const currentWidgetsCount = getCurrentWidgetCount(panel);
    const maxCapacity = calculatePanelCapacity(panel);

    if (currentWidgetsCount >= maxCapacity) return;
    addWidgetToPanel(draggedAsset, panel);
  };

  const isPanelLocked = (panel: Side) =>
    selectedZone.lockedPanels.includes(panel);

  const getCurrentWidgetCount = (panel: Side) =>
    selectedZone.widgets.filter((w) => w.panel === panel).length;

  const calculatePanelCapacity = (panel: Side) => {
    const CHART_WIDTH = 170;
    const CHART_HEIGHT = 170;
    const FALLBACK_HORIZONTAL_CAPACITY = 5;
    const FALLBACK_VERTICAL_CAPACITY = 3;

    const dimensions = panelDimensions[panel];
    if (!dimensions) {
      return panel === "top" || panel === "bottom"
        ? FALLBACK_HORIZONTAL_CAPACITY
        : FALLBACK_VERTICAL_CAPACITY;
    }

    return panel === "top" || panel === "bottom"
      ? Math.floor(dimensions.width / CHART_WIDTH)
      : Math.floor(dimensions.height / CHART_HEIGHT);
  };

  // while dublicate check this and add
  const addWidgetToPanel = async (asset: any, panel: Side) => {
    const email = localStorage.getItem("email") || "";
    const organization = email?.split("@")[1]?.split(".")[0];
    const newWidget = {
      ...asset,
      id: generateUniqueId(),
      panel,
    };
    let addWidget = {
      organization: organization,
      zoneId: selectedZone.zoneId,
      widget: newWidget,
    };
    if (visualizationSocket) {
      visualizationSocket.emit("v2:viz-widget:add", addWidget);
    }
    setSelectedZone((prev) => ({
      ...prev,
      widgets: [...prev.widgets, newWidget],
    }));

    try {
      // let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
      // if (response.message === "Widget created successfully") {
      //   setSelectedZone((prev) => ({
      //     ...prev,
      //     widgets: [...prev.widgets, newWidget],
      //   }));
      // }
    } catch (error) {
      console.error("Error adding widget:", error);
    }
  };

  useEffect(() => {
    const observers: ResizeObserver[] = [];
    const currentPanelRefs = panelRefs.current;

    selectedZone.activeSides.forEach((side) => {
      const element = currentPanelRefs[side];
      if (element) {
        const observer = new ResizeObserver((entries) => {
          for (const entry of entries) {
            const { width, height } = entry.contentRect;
            setPanelDimensions((prev) => ({
              ...prev,
              [side]: { width, height },
            }));
          }
        });
        observer.observe(element);
        observers.push(observer);
      }
    });

    return () => {
      observers.forEach((observer) => observer.disconnect());
    };
  }, [selectedZone.activeSides]);

  const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
    if (!selectedZone) return; // Ensure selectedZone is not null

    setSelectedZone((prev) => {
      if (!prev) return prev; // Ensure prev is not null

      // Filter widgets for the specified panel
      const widgetsInPanel = prev.widgets.filter((w) => w.panel === panel);

      // Reorder widgets within the same panel
      const reorderedWidgets = arrayMove(widgetsInPanel, fromIndex, toIndex);

      // Merge the reordered widgets back into the full list while preserving the order
      const updatedWidgets = prev.widgets
        .filter((widget) => widget.panel !== panel) // Keep widgets from other panels
        .concat(reorderedWidgets); // Add the reordered widgets for the specified panel

      return {
        ...prev,
        widgets: updatedWidgets,
      };
    });
  };

  return (
    <>
      {selectedZone.activeSides.map((side) => (
        <div
          key={side}
          className={`panel ${side}-panel absolute ${isPlaying ? "" : ""} ${hiddenPanels.includes(side) ? "hidePanel" : ""
            }`}
          style={getPanelStyle(side)}
          onDrop={(e) => handleDrop(e, side)}
          onDragOver={(e) => e.preventDefault()}
          ref={(el) => {
            if (el) {
              panelRefs.current[side] = el;
            } else {
              delete panelRefs.current[side];
            }
          }}
        >
          <div
            className={`panel-content ${isPlaying && "fullScreen"}`}
            style={{
              pointerEvents: selectedZone.lockedPanels.includes(side)
                ? "none"
                : "auto",
              opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
            }}
          >
            {selectedZone.widgets
              .filter((w) => w.panel === side)
              .map((widget, index) => (
                <DraggableWidget
                  hiddenPanels={hiddenPanels}
                  widget={widget}
                  key={widget.id}
                  index={index}
                  onReorder={(fromIndex, toIndex) =>
                    handleReorder(fromIndex, toIndex, side)
                  }
                  openKebabId={openKebabId}
                  setOpenKebabId={setOpenKebabId}
                  selectedZone={selectedZone}
                  setSelectedZone={setSelectedZone}
                />
              ))}
          </div>
        </div>
      ))}
    </>
  );
};

export default Panel;

// canvasDimensions.width as percent
