import React, {
  useEffect,
  useRef,
  useCallback,
  useState,
  useMemo,
} from "react";
import cytoscape, { Core } from "cytoscape";
import cola from "cytoscape-cola";
import { UniversalGraphData } from "@/types";

// Register the cola extension
cytoscape.use(cola);

// Global error handler to catch cytoscape errors
const originalConsoleError = console.error;
console.error = (...args) => {
  const message = args.join(" ");
  if (
    message.includes("Cannot read properties of null") &&
    (message.includes("notify") || message.includes("isHeadless"))
  ) {
    // Suppress cytoscape null reference errors
    console.warn("Cytoscape error suppressed:", ...args);
    return;
  }
  originalConsoleError(...args);
};

interface SimpleGraphVisualizerProps {
  data: UniversalGraphData;
  width?: number;
  height?: number;
  className?: string;
}

// Inner component that can be completely unmounted
const CytoscapeRenderer: React.FC<{
  data: UniversalGraphData;
  width: number;
  height: number;
  className: string;
  instanceId: string;
}> = ({ data, width, height, className, instanceId }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const cyRef = useRef<Core | null>(null);
  const layoutRef = useRef<any>(null);
  const isMountedRef = useRef(true);

  useEffect(() => {
    isMountedRef.current = true;

    if (!containerRef.current || !data.nodes.length) return;

    // Convert data to Cytoscape format using data attributes
    const elements = [
      ...data.nodes.map((node) => {
        const label = node.label || node.name || node.id;
        const labelLength = label.length;
        const sizeCategory =
          labelLength <= 10 ? "small" : labelLength <= 20 ? "medium" : "large";

        return {
          data: {
            id: `${instanceId}-${node.id}`,
            label: label,
            type: node.type || "default",
            sizeCategory: sizeCategory,
            color: node.color || null,
          },
        };
      }),
      ...data.links.map((link) => ({
        data: {
          id: `${instanceId}-${link.id}`,
          source: `${instanceId}-${
            typeof link.source === "string" ? link.source : link.source.id
          }`,
          target: `${instanceId}-${
            typeof link.target === "string" ? link.target : link.target.id
          }`,
          label: link.label || link.type || "",
          color: link.color || null,
        },
      })),
    ];

    try {
      // Create Cytoscape instance with error handling
      cyRef.current = cytoscape({
        container: containerRef.current,
        elements,
        style: [
          {
            selector: "node",
            style: {
              label: "data(label)",
              "text-valign": "center",
              "text-halign": "center",
              "background-color": "#4f46e5",
              color: "#ffffff",
              "text-outline-width": 1,
              "text-outline-color": "#1e293b",
              "font-size": "16px",
              "font-weight": 600,
              "font-family": "system-ui, -apple-system, sans-serif",
              width: 50,
              height: 50,
              "border-width": 2,
              "border-color": "#1e293b",
              "text-wrap": "wrap",
              "text-max-width": "120px",
            },
          },
          {
            selector: "node[sizeCategory='small']",
            style: { width: 50, height: 50 },
          },
          {
            selector: "node[sizeCategory='medium']",
            style: { width: 65, height: 65 },
          },
          {
            selector: "node[sizeCategory='large']",
            style: { width: 80, height: 80 },
          },
          {
            selector: "edge",
            style: {
              width: 3,
              "line-color": "#64748b",
              "target-arrow-color": "#64748b",
              "target-arrow-shape": "triangle",
              "curve-style": "bezier",
              label: "data(label)",
              "font-size": "12px",
              "font-family": "system-ui, -apple-system, sans-serif",
              color: "#334155",
              "text-background-color": "#ffffff",
              "text-background-opacity": 0.9,
              "text-background-padding": "4px",
              "text-border-width": 1,
              "text-border-color": "#e2e8f0",
            },
          },
          {
            selector: "node:selected",
            style: {
              "border-width": 4,
              "border-color": "#0066cc",
              "background-color": "#1d4ed8",
            },
          },
          {
            selector: "edge:selected",
            style: {
              width: 5,
              "line-color": "#0066cc",
              "target-arrow-color": "#0066cc",
            },
          },
          // Highlighting styles
          {
            selector: "node[color='#22c55e']",
            style: {
              "background-color": "#22c55e",
              "border-color": "#16a34a",
              color: "#ffffff",
            },
          },
          {
            selector: "node[color='#3b82f6']",
            style: {
              "background-color": "#3b82f6",
              "border-color": "#2563eb",
              color: "#ffffff",
            },
          },
          {
            selector: "node[color='#94a3b8']",
            style: {
              "background-color": "#94a3b8",
              "border-color": "#64748b",
              color: "#ffffff",
            },
          },
          {
            selector: "node[color='#f59e0b']",
            style: {
              "background-color": "#f59e0b",
              "border-color": "#d97706",
              color: "#ffffff",
            },
          },
          {
            selector: "edge[color='#22c55e']",
            style: {
              "line-color": "#22c55e",
              "target-arrow-color": "#22c55e",
            },
          },
          {
            selector: "edge[color='#3b82f6']",
            style: {
              "line-color": "#3b82f6",
              "target-arrow-color": "#3b82f6",
            },
          },
          {
            selector: "edge[color='#94a3b8']",
            style: {
              "line-color": "#94a3b8",
              "target-arrow-color": "#94a3b8",
            },
          },
          {
            selector: "edge[color='#f59e0b']",
            style: {
              "line-color": "#f59e0b",
              "target-arrow-color": "#f59e0b",
            },
          },
          {
            selector: "edge[color='#94a3b8']",
            style: {
              "line-color": "#94a3b8",
              "target-arrow-color": "#94a3b8",
            },
          },
        ],
        layout: {
          name: "cose", // Use cose layout instead of cola for better stability
          animate: false, // Disable animation to prevent async issues
          fit: true,
          padding: 40,
          randomize: false,
          componentSpacing: 100,
          nodeRepulsion: () => 400000,
          nodeOverlap: 20,
          idealEdgeLength: () => 150,
          edgeElasticity: () => 100,
          nestingFactor: 5,
          gravity: 80,
          numIter: 1000,
          initialTemp: 200,
          coolingFactor: 0.95,
          minTemp: 1.0,
        },
        minZoom: 0.2,
        maxZoom: 3,
      });

      // Store layout reference for cleanup
      layoutRef.current = cyRef.current.layout({
        name: "cose",
        animate: false,
        fit: true,
        padding: 40,
      });

      // Run the layout
      if (isMountedRef.current) {
        layoutRef.current.run();
      }

      // Fit the graph after a short delay
      setTimeout(() => {
        if (isMountedRef.current && cyRef.current) {
          cyRef.current.fit();
        }
      }, 100);

      // Add error handling for cytoscape events
      cyRef.current.on("*", (event) => {
        try {
          // Let cytoscape handle the event normally
        } catch (error) {
          console.warn("Cytoscape event error caught and suppressed:", error);
          event.stopPropagation();
        }
      });
    } catch (error) {
      console.error("Error creating cytoscape instance:", error);
      cyRef.current = null;
      layoutRef.current = null;
    }

    // Cleanup function
    return () => {
      isMountedRef.current = false;

      // Stop layout first
      if (layoutRef.current) {
        try {
          layoutRef.current.stop();
          layoutRef.current = null;
        } catch (error) {
          console.warn("Error stopping layout:", error);
          layoutRef.current = null;
        }
      }

      if (cyRef.current) {
        try {
          const cy = cyRef.current;

          // Stop all layouts first
          cy.stop();

          // Disable interactions
          cy.userPanningEnabled(false);
          cy.userZoomingEnabled(false);
          cy.boxSelectionEnabled(false);
          cy.autoungrabify(true);
          cy.autolock(true);

          // Remove listeners
          cy.removeAllListeners();

          // Remove elements
          cy.elements().remove();

          // Destroy with a small delay to let any pending operations complete
          setTimeout(() => {
            try {
              if (cyRef.current === cy) {
                cy.destroy();
                cyRef.current = null;
              }
            } catch (destroyError) {
              console.warn("Final destroy error:", destroyError);
              cyRef.current = null;
            }
          }, 50);
        } catch (error) {
          console.warn("Error during cytoscape cleanup:", error);
          cyRef.current = null;
        }
      }
    };
  }, [data, instanceId, width, height]);

  return (
    <div
      ref={containerRef}
      className={`w-full h-full ${className}`}
      style={{
        width: width,
        height: height,
        minHeight: "300px",
        border: "1px solid #e2e8f0",
        borderRadius: "8px",
        backgroundColor: "#fafafa",
      }}
    />
  );
};

// Error boundary component
class CytoscapeErrorBoundary extends React.Component<
  { children: React.ReactNode; onError?: () => void },
  { hasError: boolean }
> {
  constructor(props: { children: React.ReactNode; onError?: () => void }) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.warn("Cytoscape error caught by boundary:", error, errorInfo);
    this.props.onError?.();
  }

  render() {
    if (this.state.hasError) {
      return (
        <div
          className="flex items-center justify-center text-muted-foreground bg-muted/20 rounded-lg border-2 border-dashed border-muted"
          style={{ minHeight: "300px" }}
        >
          Graph visualization temporarily unavailable
        </div>
      );
    }

    return this.props.children;
  }
}

export const SimpleGraphVisualizer: React.FC<SimpleGraphVisualizerProps> = ({
  data,
  width = 400,
  height = 500,
  className = "",
}) => {
  const [renderKey, setRenderKey] = useState(0);
  const instanceId = useMemo(
    () => `cytoscape-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
    [renderKey]
  );

  const handleError = useCallback(() => {
    // Force complete remount on error
    setTimeout(() => {
      setRenderKey((prev) => prev + 1);
    }, 100);
  }, []);

  // Force remount when data changes significantly
  useEffect(() => {
    setRenderKey((prev) => prev + 1);
  }, [data]);

  return (
    <CytoscapeErrorBoundary onError={handleError}>
      <CytoscapeRenderer
        key={renderKey}
        data={data}
        width={width}
        height={height}
        className={className}
        instanceId={instanceId}
      />
    </CytoscapeErrorBoundary>
  );
};
