import {
  useState,
  useCallback,
  useEffect,
  useRef,
  type ReactNode,
} from "react";
import { Box, alpha } from "@mui/material";
import { PANEL_DRAG_TYPE } from "./ResizablePanel";

interface SidebarDropZoneProps {
  /** Sidebar position */
  position: "left" | "right";
  /** Sidebar width in pixels */
  width: number;
  /** Minimum width */
  minWidth?: number;
  /** Maximum width */
  maxWidth?: number;
  /** Callback when width changes */
  onWidthChange: (width: number) => void;
  /** Children (panels) */
  children: ReactNode;
  /** Callback when a panel is dropped */
  onPanelDrop: (
    panelId: string,
    targetPosition: "left" | "right",
    targetIndex: number,
  ) => void;
  /** Current panel IDs in this sidebar (for calculating drop index) */
  panelIds: string[];
}

export default function SidebarDropZone({
  position,
  width,
  minWidth = 180,
  maxWidth = 500,
  onWidthChange,
  children,
  onPanelDrop,
  panelIds,
}: SidebarDropZoneProps) {
  const [isDragOver, setIsDragOver] = useState(false);
  const [dropIndex, setDropIndex] = useState<number | null>(null);
  const [isResizing, setIsResizing] = useState(false);
  const startXRef = useRef(0);
  const startWidthRef = useRef(width);

  // Handle horizontal resize
  const handleResizeStart = useCallback(
    (e: React.MouseEvent) => {
      e.preventDefault();
      e.stopPropagation();
      setIsResizing(true);
      startXRef.current = e.clientX;
      startWidthRef.current = width;
    },
    [width],
  );

  useEffect(() => {
    if (!isResizing) return;

    const handleMouseMove = (e: MouseEvent) => {
      const delta =
        position === "left"
          ? e.clientX - startXRef.current
          : startXRef.current - e.clientX;

      const newWidth = Math.min(
        maxWidth,
        Math.max(minWidth, startWidthRef.current + delta),
      );
      onWidthChange(newWidth);
    };

    const handleMouseUp = () => {
      setIsResizing(false);
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);

    return () => {
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
    };
  }, [isResizing, position, minWidth, maxWidth, onWidthChange]);

  // Handle drag over
  const handleDragOver = useCallback(
    (e: React.DragEvent) => {
      // Only accept panel drags
      if (!e.dataTransfer.types.includes(PANEL_DRAG_TYPE)) {
        return;
      }

      e.preventDefault();
      e.dataTransfer.dropEffect = "move";
      setIsDragOver(true);

      // Calculate drop index based on mouse position
      const container = e.currentTarget as HTMLElement;
      const rect = container.getBoundingClientRect();
      const mouseY = e.clientY - rect.top;

      // Find which panel slot the mouse is over
      const panelElements = container.querySelectorAll("[data-panel-id]");
      let newDropIndex = panelIds.length; // Default to end

      panelElements.forEach((el, index) => {
        const panelRect = el.getBoundingClientRect();
        const panelMiddle = panelRect.top + panelRect.height / 2 - rect.top;

        if (mouseY < panelMiddle) {
          newDropIndex = Math.min(newDropIndex, index);
        }
      });

      setDropIndex(newDropIndex);
    },
    [panelIds.length],
  );

  // Handle drag leave
  const handleDragLeave = useCallback((e: React.DragEvent) => {
    // Only reset if leaving the container entirely
    const relatedTarget = e.relatedTarget as HTMLElement;
    if (!e.currentTarget.contains(relatedTarget)) {
      setIsDragOver(false);
      setDropIndex(null);
    }
  }, []);

  // Handle drop
  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      setIsDragOver(false);

      const panelId = e.dataTransfer.getData(PANEL_DRAG_TYPE);
      console.log(
        "[SidebarDropZone] Drop:",
        panelId,
        "position:",
        position,
        "dropIndex:",
        dropIndex,
      );
      if (!panelId) return;

      // Calculate final drop index
      const finalIndex = dropIndex ?? panelIds.length;

      // If dropping in same sidebar, adjust index if needed
      const currentIndex = panelIds.indexOf(panelId);
      let adjustedIndex = finalIndex;

      if (currentIndex !== -1 && currentIndex < finalIndex) {
        // If moving down in same sidebar, subtract 1 because the panel will be removed first
        adjustedIndex = finalIndex - 1;
      }

      onPanelDrop(panelId, position, adjustedIndex);
      setDropIndex(null);
    },
    [dropIndex, panelIds, position, onPanelDrop],
  );

  // Calculate drop indicator position
  const getDropIndicatorTop = useCallback(() => {
    if (dropIndex === null) return 0;

    // We need to find the panel elements in the DOM
    const panelElements = document.querySelectorAll(
      `[data-sidebar="${position}"] [data-panel-id]`,
    );

    if (dropIndex === 0) return 0;

    if (dropIndex >= panelElements.length) {
      // Drop at end - position after last panel
      const lastPanel = panelElements[panelElements.length - 1];
      if (lastPanel) {
        const container = lastPanel.parentElement;
        if (container) {
          const rect = lastPanel.getBoundingClientRect();
          const containerRect = container.getBoundingClientRect();
          return rect.bottom - containerRect.top;
        }
      }
      return "auto";
    }

    const targetPanel = panelElements[dropIndex];
    if (targetPanel) {
      const container = targetPanel.parentElement;
      if (container) {
        const rect = targetPanel.getBoundingClientRect();
        const containerRect = container.getBoundingClientRect();
        return rect.top - containerRect.top;
      }
    }
    return 0;
  }, [dropIndex, position]);

  const hasNoPanels = panelIds.length === 0;

  return (
    <Box
      data-sidebar={position}
      onDragOver={handleDragOver}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
      sx={{
        display: "flex",
        flexDirection: "column",
        height: "100%",
        width: width,
        minWidth: hasNoPanels ? 60 : minWidth,
        maxWidth: maxWidth,
        position: "relative",
        flexShrink: 0,
        // Visual feedback during drag
        ...(isDragOver && {
          bgcolor: (theme) => alpha(theme.palette.primary.main, 0.05),
        }),
        transition: "background-color 0.2s",
      }}
    >
      {/* Horizontal resize handle */}
      <Box
        onMouseDown={handleResizeStart}
        sx={{
          position: "absolute",
          top: 0,
          bottom: 0,
          [position === "left" ? "right" : "left"]: -4,
          width: 8,
          cursor: "col-resize",
          zIndex: 1000,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          "&:hover": {
            "& .resize-indicator": {
              opacity: 1,
              bgcolor: "primary.main",
            },
          },
          ...(isResizing && {
            "& .resize-indicator": {
              opacity: 1,
              bgcolor: "primary.main",
            },
          }),
        }}
      >
        <Box
          className="resize-indicator"
          sx={{
            width: 4,
            height: 50,
            borderRadius: 1,
            bgcolor: "divider",
            opacity: 0.7,
            transition: "opacity 0.15s, background-color 0.15s",
          }}
        />
      </Box>

      {/* Drop indicator line */}
      {isDragOver && dropIndex !== null && !hasNoPanels && (
        <Box
          sx={{
            position: "absolute",
            left: 0,
            right: 0,
            height: 3,
            bgcolor: "primary.main",
            borderRadius: 1,
            zIndex: 100,
            top: getDropIndicatorTop(),
            pointerEvents: "none",
            // Box shadow for glow effect
            boxShadow: (theme) =>
              `0 0 8px 2px ${alpha(theme.palette.primary.main, 0.4)}`,
          }}
        />
      )}

      {/* Panels */}
      {children}

      {/* Empty state drop zone (when sidebar has no panels) */}
      {hasNoPanels && (
        <Box
          sx={{
            flex: 1,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            border: isDragOver ? 2 : 1,
            borderColor: isDragOver ? "primary.main" : "divider",
            borderStyle: "dashed",
            borderRadius: 1,
            m: 1,
            p: 2,
            color: "text.secondary",
            fontSize: "0.75rem",
            textAlign: "center",
            transition: "all 0.2s",
            bgcolor: isDragOver
              ? (theme) => alpha(theme.palette.primary.main, 0.1)
              : "transparent",
          }}
        >
          Trascina qui
        </Box>
      )}
    </Box>
  );
}
