import React, { useState, useRef, useCallback, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { MapNode } from './MapNode';
import { Connection } from './Connection';
import { useQuery } from '@tanstack/react-query';
import { getSecurityColor } from '../utils/securityColors';
import { Position, Region } from '../lib/types';


const fetchUniverseData = async (): Promise<Region[]> => {
  const response = await fetch('/universe.json');
  if (!response.ok) {
    throw new Error('Failed to fetch universe data');
  }
  return response.json();
};

export const GalaxyMap = () => {
  const navigate = useNavigate();
  const [viewBox, setViewBox] = useState({ x: 0, y: 0, width: 1200, height: 800 });
  const [isPanning, setIsPanning] = useState(false);
  const [lastPanPoint, setLastPanPoint] = useState({ x: 0, y: 0 });
  const [nodePositions, setNodePositions] = useState<Record<string, Position>>({});
  const svgRef = useRef<SVGSVGElement>(null);

  const { data: regions, isLoading, error } = useQuery({
    queryKey: ['universe'],
    queryFn: fetchUniverseData,
  });

  // Initialize node positions when data is loaded
  useEffect(() => {
    if (regions) {
      const positions: Record<string, Position> = {};
      regions.forEach(region => {
        positions[region.regionName] = {
          x: parseInt(region.x),
          y: parseInt(region.y)
        };
      });
      setNodePositions(positions);
    }
  }, [regions]);

  const handleNodeClick = (regionName: string) => {
    // Encode region name to handle spaces and special characters
    const encodedRegion = encodeURIComponent(regionName);
    navigate(`/regions/${encodedRegion}`);
  };

  const handleMouseDown = useCallback((e: React.MouseEvent) => {
    if (!svgRef.current) return;
    setIsPanning(true);
    const rect = svgRef.current.getBoundingClientRect();
    setLastPanPoint({
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    });
  }, []);

  const handleMouseMove = useCallback((e: React.MouseEvent) => {
    if (!isPanning || !svgRef.current) return;

    const rect = svgRef.current.getBoundingClientRect();
    const currentPoint = {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };

    const deltaX = (lastPanPoint.x - currentPoint.x) * (viewBox.width / rect.width);
    const deltaY = (lastPanPoint.y - currentPoint.y) * (viewBox.height / rect.height);

    setViewBox(prev => ({
      ...prev,
      x: prev.x + deltaX,
      y: prev.y + deltaY
    }));

    setLastPanPoint(currentPoint);
  }, [isPanning, lastPanPoint, viewBox.width, viewBox.height]);

  const handleMouseUp = useCallback(() => {
    setIsPanning(false);
  }, []);

  const handleWheel = useCallback((e: React.WheelEvent) => {
    e.preventDefault();
    if (!svgRef.current) return;

    const rect = svgRef.current.getBoundingClientRect();
    const mouseX = e.clientX - rect.left;
    const mouseY = e.clientY - rect.top;

    // Invert scroll direction: negative deltaY (scroll up) zooms out, positive (scroll down) zooms in
    const scale = e.deltaY < 0 ? 1.1 : 0.9;
    const newWidth = viewBox.width * scale;
    const newHeight = viewBox.height * scale;

    const mouseXInSVG = viewBox.x + (mouseX / rect.width) * viewBox.width;
    const mouseYInSVG = viewBox.y + (mouseY / rect.height) * viewBox.height;

    const newX = mouseXInSVG - (mouseX / rect.width) * newWidth;
    const newY = mouseYInSVG - (mouseY / rect.height) * newHeight;

    setViewBox({
      x: newX,
      y: newY,
      width: newWidth,
      height: newHeight
    });
  }, [viewBox]);

  if (isLoading) {
    return (
      <div className="w-full h-full flex items-center justify-center">
        <div className="text-white text-xl">Loading universe data...</div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="w-full h-full flex items-center justify-center">
        <div className="text-red-400 text-xl">Error loading universe data</div>
      </div>
    );
  }

  return (
    <div className="w-full h-full p-4">
      <div className="w-full h-full border border-purple-500/30 rounded-lg overflow-hidden bg-black/20 backdrop-blur-sm">
        <svg
          ref={svgRef}
          width="100%"
          height="100%"
          viewBox={`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`}
          className="cursor-grab active:cursor-grabbing"
          onMouseDown={handleMouseDown}
          onMouseMove={handleMouseMove}
          onMouseUp={handleMouseUp}
          onMouseLeave={handleMouseUp}
          onWheel={handleWheel}
        >
          <defs>
            <filter id="glow">
              <feGaussianBlur stdDeviation="3" result="coloredBlur" />
              <feMerge>
                <feMergeNode in="coloredBlur" />
                <feMergeNode in="SourceGraphic" />
              </feMerge>
            </filter>
          </defs>

          {/* Render connections first (behind nodes) */}
          {regions?.map((region) =>
            region.connectsTo?.split(',').map((connectedRegion) => {
              const fromPos = nodePositions[region.regionName];
              const toPos = nodePositions[connectedRegion];
              if (!fromPos || !toPos) return null;

              // Get colors for both regions
              const toRegion = regions.find(r => r.regionName === connectedRegion);
              const avgSecurity = (region.security + toRegion.security) / 2;
              const color = getSecurityColor(avgSecurity);

              return (
                <Connection
                  key={`${region.regionName}-${connectedRegion}`}
                  from={fromPos}
                  to={toPos}
                  color={color}
                />
              );
            })
          )}

          {/* Render regions */}
          {regions?.map((region) => (
            <MapNode
              key={region.regionName}
              id={region.regionName}
              name={region.regionName}
              position={nodePositions[region.regionName] || { x: 0, y: 0 }}
              onClick={() => handleNodeClick(region.regionName)}
              type="region"
              security={region.security}
            />
          ))}
        </svg>
      </div>
    </div>
  );
};
