import { useCallback, useEffect, useRef, useState } from 'react';
import type { Network } from 'vis-network/standalone';
import Button from '@/components/ui/Button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';

interface GraphNode {
  id: string;
  label: string;
  type: string;
  properties: Record<string, unknown>;
}

interface GraphEdge {
  id: string;
  source: string;
  target: string;
  type: string;
  properties?: Record<string, unknown>;
}

interface GraphData {
  nodes: GraphNode[];
  edges: GraphEdge[];
}

interface NetworkGraphProps {
  organizationId: string;
  organizationName: string;
  depth?: number;
  onNodeClick?: (nodeId: string, nodeType: string) => void;
}

export function NetworkGraph({
  organizationId,
  organizationName,
  depth = 2,
  onNodeClick,
}: NetworkGraphProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const networkRef = useRef<Network | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [graphData, setGraphData] = useState<GraphData | null>(null);
  const [currentDepth, setCurrentDepth] = useState(depth);

  const fetchNetworkData = useCallback(
    async (depthLevel: number) => {
      setIsLoading(true);
      setError(null);

      try {
        const response = await fetch(
          `/api/graph/organizations/${organizationId}/network?depth=${depthLevel}`
        );

        if (!response.ok) {
          throw new Error('Failed to fetch network data');
        }

        const data = await response.json();
        setGraphData(data.graph);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load network graph');
        console.error('Network graph error:', err);
      } finally {
        setIsLoading(false);
      }
    },
    [organizationId]
  );

  useEffect(() => {
    fetchNetworkData(currentDepth);
  }, [fetchNetworkData, currentDepth]);

  useEffect(() => {
    if (!graphData || !containerRef.current) return;

    // Dynamically import vis-network and vis-data only when needed
    Promise.all([import('vis-network'), import('vis-data')])
      .then(([{ Network }, { DataSet }]) => {
        const nodes = new DataSet(
          graphData.nodes.map((node) => ({
            id: node.id,
            label: node.label,
            title: `${node.type}: ${node.label}`,
            color: getNodeColor(node.type),
            shape: getNodeShape(node.type),
            font: {
              size: 14,
              color: '#334155',
            },
          }))
        );

        const edges = new DataSet(
          graphData.edges.map((edge) => ({
            id: edge.id,
            from: edge.source,
            to: edge.target,
            label: edge.type.replace('_', ' '),
            arrows: 'to',
            color: {
              color: '#94a3b8',
              highlight: '#3b82f6',
            },
            font: {
              size: 10,
              align: 'middle',
            },
          }))
        );

        const data = { nodes, edges };

        const options = {
          physics: {
            enabled: true,
            stabilization: {
              enabled: true,
              iterations: 100,
            },
            barnesHut: {
              gravitationalConstant: -2000,
              centralGravity: 0.3,
              springLength: 150,
              springConstant: 0.04,
              damping: 0.09,
            },
          },
          interaction: {
            hover: true,
            tooltipDelay: 100,
            navigationButtons: true,
            keyboard: true,
          },
          nodes: {
            borderWidth: 2,
            borderWidthSelected: 3,
            size: 25,
          },
          edges: {
            width: 2,
            smooth: {
              enabled: true,
              type: 'continuous',
              roundness: 0.5,
            },
          },
        };

        if (networkRef.current) {
          networkRef.current.destroy();
        }

        networkRef.current = new Network(containerRef.current!, data, options);

        // Handle node clicks
        networkRef.current.on('click', (params) => {
          if (params.nodes.length > 0) {
            const nodeId = params.nodes[0] as string;
            const node = graphData.nodes.find((n) => n.id === nodeId);
            if (node && onNodeClick) {
              onNodeClick(node.id, node.type);
            }
          }
        });

        // Highlight the source organization - only if the node exists in the graph
        const nodeExists = graphData.nodes.some((n) => n.id === organizationId);
        if (nodeExists) {
          networkRef.current.selectNodes([organizationId]);
        }
      })
      .catch((err) => {
        console.error('Failed to load vis-network or vis-data:', err);
        setError('Graph visualization libraries not loaded. Run: npm install vis-network vis-data');
      });

    return () => {
      if (networkRef.current) {
        networkRef.current.destroy();
        networkRef.current = null;
      }
    };
  }, [graphData, organizationId, onNodeClick]);

  const getNodeColor = (type: string): string => {
    const colors: Record<string, string> = {
      Organization: '#3b82f6',
      Site: '#10b981',
      ResourceFlow: '#f59e0b',
      Match: '#8b5cf6',
      SharedAsset: '#ec4899',
    };
    return colors[type] || '#6b7280';
  };

  const getNodeShape = (type: string): string => {
    const shapes: Record<string, string> = {
      Organization: 'dot',
      Site: 'square',
      ResourceFlow: 'diamond',
      Match: 'star',
      SharedAsset: 'triangle',
    };
    return shapes[type] || 'dot';
  };

  const handleDepthChange = (newDepth: number) => {
    setCurrentDepth(newDepth);
  };

  return (
    <Card>
      <CardHeader>
        <CardTitle>{t('organization.networkGraph')}</CardTitle>
        <p className="text-sm text-muted-foreground">
          {t('organization.networkGraphDescription', { name: organizationName })}
        </p>
        <div className="flex gap-2 mt-4">
          {[1, 2, 3].map((d) => (
            <Button
              key={d}
              size="sm"
              variant={currentDepth === d ? 'default' : 'outline'}
              onClick={() => handleDepthChange(d)}
              disabled={isLoading}
            >
              Depth {d}
            </Button>
          ))}
        </div>
      </CardHeader>
      <CardContent>
        {error && (
          <div className="bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded">
            <p className="font-semibold">{t('organization.networkGraphError')}</p>
            <p className="text-sm">{error}</p>
          </div>
        )}

        {isLoading && (
          <div className="flex items-center justify-center h-96 bg-muted/30 rounded-lg">
            <div className="text-center">
              <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4"></div>
              <p className="text-muted-foreground">{t('organization.networkGraphLoading')}</p>
            </div>
          </div>
        )}

        {!isLoading && !error && graphData && (
          <>
            <div
              ref={containerRef}
              className="w-full h-96 border border-border rounded-lg bg-white"
            />
            <div className="mt-4 flex items-center justify-between text-sm text-muted-foreground">
              <div className="flex gap-4">
                <span>{t('organization.nodesCount', { count: graphData.nodes.length })}</span>
                <span>{t('organization.connectionsCount', { count: graphData.edges.length })}</span>
              </div>
              <div className="flex gap-3 text-xs">
                <div className="flex items-center gap-1">
                  <div className="w-3 h-3 rounded-full bg-[#3b82f6]"></div>
                  <span>{t('organization.legend.organization')}</span>
                </div>
                <div className="flex items-center gap-1">
                  <div className="w-3 h-3 bg-[#10b981]"></div>
                  <span>{t('organization.legend.site')}</span>
                </div>
                <div className="flex items-center gap-1">
                  <div className="w-3 h-3 bg-[#f59e0b] rotate-45"></div>
                  <span>{t('organization.legend.resource')}</span>
                </div>
              </div>
            </div>
          </>
        )}
      </CardContent>
    </Card>
  );
}
