import React, { useRef, useMemo, useEffect, useState } from 'react';
import { Canvas, useFrame, useLoader } from '@react-three/fiber';
import { OrbitControls, Grid, Text, Line } from '@react-three/drei';
import * as THREE from 'three';
import { useTurtleStore } from '../store/turtleStore';

// Texture mapping for Minecraft blocks
const TEXTURE_MAP = {
  // Basic blocks
  'minecraft:stone': 'stone',
  'minecraft:cobblestone': 'cobblestone',
  'minecraft:dirt': 'dirt',
  'minecraft:grass_block': 'grass_block_side',
  'minecraft:sand': 'sand',
  'minecraft:red_sand': 'red_sand',
  'minecraft:gravel': 'gravel',
  'minecraft:bedrock': 'bedrock',
  'minecraft:oak_log': 'oak_log',
  'minecraft:oak_planks': 'oak_planks',
  'minecraft:glass': 'glass',
  
  // Stone variants
  'minecraft:granite': 'granite',
  'minecraft:diorite': 'diorite',
  'minecraft:andesite': 'andesite',
  'minecraft:deepslate': 'deepslate',
  'minecraft:tuff': 'tuff',
  'minecraft:calcite': 'calcite',
  'minecraft:dripstone_block': 'dripstone_block',
  
  // Ores (overworld)
  'minecraft:coal_ore': 'coal_ore',
  'minecraft:iron_ore': 'iron_ore',
  'minecraft:gold_ore': 'gold_ore',
  'minecraft:diamond_ore': 'diamond_ore',
  'minecraft:emerald_ore': 'emerald_ore',
  'minecraft:redstone_ore': 'redstone_ore',
  'minecraft:lapis_ore': 'lapis_ore',
  'minecraft:copper_ore': 'copper_ore',
  
  // Deepslate ores
  'minecraft:deepslate_coal_ore': 'deepslate_coal_ore',
  'minecraft:deepslate_iron_ore': 'deepslate_iron_ore',
  'minecraft:deepslate_gold_ore': 'deepslate_gold_ore',
  'minecraft:deepslate_diamond_ore': 'deepslate_diamond_ore',
  'minecraft:deepslate_emerald_ore': 'deepslate_emerald_ore',
  'minecraft:deepslate_redstone_ore': 'deepslate_redstone_ore',
  'minecraft:deepslate_lapis_ore': 'deepslate_lapis_ore',
  'minecraft:deepslate_copper_ore': 'deepslate_copper_ore',
  
  // Special blocks
  'minecraft:obsidian': 'obsidian',
  'minecraft:netherrack': 'netherrack',
  'minecraft:soul_sand': 'soul_sand',
  'minecraft:glowstone': 'glowstone',
  'minecraft:end_stone': 'end_stone',
  'minecraft:water': 'water_still',
  'minecraft:lava': 'lava_still',
  
  // Building blocks
  'minecraft:bricks': 'bricks',
  'minecraft:stone_bricks': 'stone_bricks',
  'minecraft:mossy_cobblestone': 'mossy_cobblestone',
  'minecraft:mossy_stone_bricks': 'mossy_stone_bricks',
  'minecraft:prismarine': 'prismarine',
  'minecraft:dark_prismarine': 'dark_prismarine',
};

// Function to get texture URL from a Minecraft texture service
function getTextureURL(blockName) {
  const textureName = TEXTURE_MAP[blockName] || 'stone';
  // Using a public Minecraft texture API
  return `https://raw.githubusercontent.com/InventivetalentDev/minecraft-assets/1.20.4/assets/minecraft/textures/block/${textureName}.png`;
}

// Custom hook to load multiple textures
function useMinecraftTextures(blocks) {
  const [textures, setTextures] = useState({});
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const textureLoader = new THREE.TextureLoader();
    const uniqueBlocks = [...new Set(blocks.map(b => b.name))];
    const loadedTextures = {};
    let loadedCount = 0;

    if (uniqueBlocks.length === 0) {
      setLoading(false);
      return;
    }

    uniqueBlocks.forEach(blockName => {
      const url = getTextureURL(blockName);
      
      textureLoader.load(
        url,
        (texture) => {
          texture.magFilter = THREE.NearestFilter;
          texture.minFilter = THREE.NearestFilter;
          texture.wrapS = THREE.RepeatWrapping;
          texture.wrapT = THREE.RepeatWrapping;
          loadedTextures[blockName] = texture;
          loadedCount++;
          
          if (loadedCount === uniqueBlocks.length) {
            setTextures(loadedTextures);
            setLoading(false);
          }
        },
        undefined,
        (error) => {
          console.warn(`Failed to load texture for ${blockName}, using color fallback`);
          loadedCount++;
          
          if (loadedCount === uniqueBlocks.length) {
            setTextures(loadedTextures);
            setLoading(false);
          }
        }
      );
    });
  }, [blocks]);

  return { textures, loading };
}

// Minecraft-style turtle model
function TurtleModel({ turtle, isSelected, onClick }) {
  const groupRef = useRef();
  const { position, facing, mode } = turtle;

  useFrame((state) => {
    if (groupRef.current && isSelected) {
      groupRef.current.children[0].position.y = Math.sin(state.clock.elapsedTime * 2) * 0.05;
    }
  });

  if (!position) return null;

  // Calculate rotation based on facing (0=North(-Z), 1=East(+X), 2=South(+Z), 3=West(-X))
  // Add 180 degrees (Math.PI) to face the head forward initially, then apply facing rotation
  const rotation = facing !== undefined ? [0, (facing * Math.PI / 2) + Math.PI, 0] : [0, Math.PI, 0];

  const color = mode === 'mining' ? '#4ade80' :
                mode === 'exploring' ? '#60a5fa' :
                mode === 'returning' ? '#f59e0b' :
                '#9ca3af';

  return (
    <group ref={groupRef} position={[position.x, position.y, position.z]} rotation={rotation} onClick={onClick}>
      <group>
        {/* Shell (main body) */}
        <mesh position={[0, 0.2, 0]}>
          <boxGeometry args={[0.8, 0.5, 0.9]} />
          <meshStandardMaterial 
            color={color} 
            emissive={color}
            emissiveIntensity={isSelected ? 0.4 : 0.2}
            roughness={0.4}
          />
        </mesh>
        
        {/* Head */}
        <mesh position={[0, 0.15, 0.55]}>
          <boxGeometry args={[0.5, 0.35, 0.3]} />
          <meshStandardMaterial color={color} roughness={0.3} />
        </mesh>
        
        {/* Eyes */}
        <mesh position={[-0.12, 0.2, 0.7]}>
          <boxGeometry args={[0.1, 0.1, 0.05]} />
          <meshStandardMaterial color="#ffffff" emissive="#ffff00" emissiveIntensity={0.5} />
        </mesh>
        <mesh position={[0.12, 0.2, 0.7]}>
          <boxGeometry args={[0.1, 0.1, 0.05]} />
          <meshStandardMaterial color="#ffffff" emissive="#ffff00" emissiveIntensity={0.5} />
        </mesh>
        
        {/* Legs */}
        <mesh position={[-0.3, -0.15, 0.25]}>
          <boxGeometry args={[0.2, 0.2, 0.2]} />
          <meshStandardMaterial color="#666" />
        </mesh>
        <mesh position={[0.3, -0.15, 0.25]}>
          <boxGeometry args={[0.2, 0.2, 0.2]} />
          <meshStandardMaterial color="#666" />
        </mesh>
        <mesh position={[-0.3, -0.15, -0.25]}>
          <boxGeometry args={[0.2, 0.2, 0.2]} />
          <meshStandardMaterial color="#666" />
        </mesh>
        <mesh position={[0.3, -0.15, -0.25]}>
          <boxGeometry args={[0.2, 0.2, 0.2]} />
          <meshStandardMaterial color="#666" />
        </mesh>
        
        {/* Tail */}
        <mesh position={[0, 0.1, -0.55]}>
          <boxGeometry args={[0.15, 0.15, 0.2]} />
          <meshStandardMaterial color={color} />
        </mesh>
      </group>
      
      {/* Selection indicator */}
      {isSelected && (
        <>
          <mesh position={[0, 1.2, 0]}>
            <coneGeometry args={[0.3, 0.5, 4]} />
            <meshStandardMaterial color="#ffffff" emissive="#ffffff" emissiveIntensity={0.8} />
          </mesh>
          
          {/* Selection ring */}
          <mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.5, 0]}>
            <ringGeometry args={[1, 1.2, 32]} />
            <meshBasicMaterial color="#ffffff" side={THREE.DoubleSide} transparent opacity={0.5} />
          </mesh>
        </>
      )}

      {/* Turtle ID label */}
      <Text
        position={[0, 1.5, 0]}
        fontSize={0.4}
        color="white"
        anchorX="center"
        anchorY="middle"
      >
        🐢 {turtle.turtleID}
      </Text>
    </group>
  );
}

// Path trail component
function PathTrail({ turtle }) {
  const { position, homePosition } = turtle;

  if (!position || !homePosition) return null;

  const points = [
    new THREE.Vector3(position.x, position.y, position.z),
    new THREE.Vector3(homePosition.x, homePosition.y, homePosition.z)
  ];

  return (
    <Line
      points={points}
      color="#60a5fa"
      lineWidth={2}
      transparent
      opacity={0.3}
      dashed
      dashScale={2}
    />
  );
}

// Get color and texture info for block type
function getBlockAppearance(blockName) {
  if (!blockName) return { color: '#888', pattern: 'solid' };
  
  const name = blockName.toLowerCase();
  
  // Ores - bright colors with sparkle
  if (name.includes('diamond')) return { color: '#00ffff', pattern: 'ore', emissive: '#00ffff', intensity: 0.3 };
  if (name.includes('emerald')) return { color: '#00ff00', pattern: 'ore', emissive: '#00ff00', intensity: 0.3 };
  if (name.includes('gold')) return { color: '#ffd700', pattern: 'ore', emissive: '#ffd700', intensity: 0.2 };
  if (name.includes('iron')) return { color: '#d4d4d4', pattern: 'ore' };
  if (name.includes('coal')) return { color: '#1a1a1a', pattern: 'ore' };
  if (name.includes('redstone')) return { color: '#ff0000', pattern: 'ore', emissive: '#ff0000', intensity: 0.2 };
  if (name.includes('lapis')) return { color: '#1e40af', pattern: 'ore' };
  if (name.includes('copper')) return { color: '#ff8c00', pattern: 'ore' };
  
  // Common blocks - textured
  if (name.includes('stone') && !name.includes('cobble')) return { color: '#7f7f7f', pattern: 'stone' };
  if (name.includes('cobblestone')) return { color: '#808080', pattern: 'cobble' };
  if (name.includes('dirt')) return { color: '#8b4513', pattern: 'dirt' };
  if (name.includes('grass')) return { color: '#228b22', pattern: 'grass' };
  if (name.includes('sand')) return { color: '#f4a460', pattern: 'sand' };
  if (name.includes('gravel')) return { color: '#808080', pattern: 'gravel' };
  if (name.includes('bedrock')) return { color: '#222', pattern: 'solid' };
  if (name.includes('obsidian')) return { color: '#1a0033', pattern: 'solid' };
  if (name.includes('netherrack')) return { color: '#8b0000', pattern: 'netherrack' };
  
  return { color: '#666666', pattern: 'solid' };
}

// WorldBlocks component to render discovered blocks with Minecraft textures
function WorldBlocks({ blocks }) {
  const [hoveredBlock, setHoveredBlock] = useState(null);
  const { textures, loading } = useMinecraftTextures(blocks);
  
  // Group blocks by block name for better performance
  const blockGroups = useMemo(() => {
    const groups = new Map();
    
    blocks.forEach(block => {
      if (!groups.has(block.name)) {
        groups.set(block.name, []);
      }
      groups.get(block.name).push(block);
    });
    
    return Array.from(groups.entries());
  }, [blocks]);

  if (loading) {
    return <Text position={[0, 5, 0]} fontSize={0.5} color="white">Loading textures...</Text>;
  }

  return (
    <group>
      {blockGroups.map(([blockName, blockList]) => {
        const appearance = getBlockAppearance(blockName);
        const texture = textures[blockName];
        
        return (
          <group key={blockName}>
            {blockList.map((block) => {
              const blockKey = `${block.x},${block.y},${block.z}`;
              const isHovered = hoveredBlock === blockKey;
              
              return (
                <group key={blockKey}>
                  <mesh 
                    position={[block.x, block.y, block.z]}
                    onPointerOver={(e) => {
                      e.stopPropagation();
                      setHoveredBlock(blockKey);
                    }}
                    onPointerOut={() => setHoveredBlock(null)}
                  >
                    <boxGeometry args={[1.0, 1.0, 1.0]} />
                    <meshStandardMaterial 
                      map={texture}
                      color={texture ? '#ffffff' : appearance.color}
                      emissive={appearance.emissive || appearance.color}
                      emissiveIntensity={isHovered ? (appearance.intensity || 0.05) + 0.2 : (appearance.intensity || 0.05)}
                      roughness={appearance.pattern === 'ore' ? 0.4 : 0.8}
                      metalness={appearance.pattern === 'ore' ? 0.2 : 0.0}
                      transparent 
                      opacity={isHovered ? 0.98 : 0.9}
                    />
                  </mesh>
                  
                  {/* Block label on hover */}
                  {isHovered && (
                    <Text
                      position={[block.x, block.y + 0.8, block.z]}
                      fontSize={0.3}
                      color="white"
                      anchorX="center"
                      anchorY="middle"
                      outlineWidth={0.05}
                      outlineColor="#000000"
                    >
                      {block.name.replace('minecraft:', '').replace(/_/g, ' ').toUpperCase()}
                    </Text>
                  )}
                </group>
              );
            })}
          </group>
        );
      })}
    </group>
  );
}

// Path trail component (old version removed above)
function OldPathTrail({ turtle }) {
  const { position, homePosition } = turtle;

  if (!position || !homePosition) return null;

  const points = [
    new THREE.Vector3(position.x, position.y, position.z),
    new THREE.Vector3(homePosition.x, homePosition.y, homePosition.z)
  ];

  return (
    <Line
      points={points}
      color="#60a5fa"
      lineWidth={2}
      dashed
      dashScale={2}
      transparent
      opacity={0.5}
    />
  );
}

// Home marker component
function HomeMarker({ position }) {
  if (!position) return null;

  return (
    <group position={[position.x, position.y, position.z]}>
      <mesh>
        <cylinderGeometry args={[1, 0.5, 0.5, 6]} />
        <meshStandardMaterial color="#10b981" emissive="#10b981" emissiveIntensity={0.3} />
      </mesh>
      <Text
        position={[0, 1.2, 0]}
        fontSize={0.5}
        color="#10b981"
        anchorX="center"
        anchorY="middle"
      >
        HOME
      </Text>
    </group>
  );
}

// Mining area wireframe component
function MiningArea({ area, turtle, isSelected, onClick }) {
  const meshRef = useRef();
  const [hovered, setHovered] = useState(false);

  // Calculate dimensions
  const width = Math.abs(area.endX - area.startX) + 1;
  const height = Math.abs(area.endY - area.startY) + 1;
  const depth = Math.abs(area.endZ - area.startZ) + 1;

  // Calculate center position
  const centerX = (area.startX + area.endX) / 2;
  const centerY = (area.startY + area.endY) / 2;
  const centerZ = (area.startZ + area.endZ) / 2;

  // Color based on turtle or status
  const getColor = () => {
    if (area.status === 'completed') return '#10b981'; // green
    if (area.status === 'mining') return '#f59e0b'; // orange
    if (turtle) return turtle.color || '#3b82f6'; // turtle color or blue
    return '#6366f1'; // default purple
  };

  const color = getColor();
  const opacity = isSelected ? 0.3 : hovered ? 0.2 : 0.1;
  const lineWidth = isSelected ? 2.5 : hovered ? 2 : 1.5;

  // Animate rotation slightly
  useFrame((state) => {
    if (meshRef.current && isSelected) {
      meshRef.current.rotation.y = Math.sin(state.clock.elapsedTime * 0.5) * 0.1;
    }
  });

  return (
    <group 
      position={[centerX, centerY, centerZ]}
      onClick={onClick}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
      ref={meshRef}
    >
      {/* Wireframe box */}
      <lineSegments>
        <edgesGeometry args={[new THREE.BoxGeometry(width, height, depth)]} />
        <lineBasicMaterial color={color} linewidth={lineWidth} />
      </lineSegments>

      {/* Semi-transparent fill */}
      <mesh>
        <boxGeometry args={[width, height, depth]} />
        <meshStandardMaterial
          color={color}
          transparent
          opacity={opacity}
          side={THREE.DoubleSide}
        />
      </mesh>

      {/* Label */}
      <Text
        position={[0, height / 2 + 1, 0]}
        fontSize={0.5}
        color={color}
        anchorX="center"
        anchorY="middle"
      >
        {area.areaName || `Area ${area.areaID}`}
      </Text>

      {/* Dimensions label */}
      <Text
        position={[0, height / 2 + 0.3, 0]}
        fontSize={0.3}
        color="white"
        anchorX="center"
        anchorY="middle"
      >
        {width}×{height}×{depth}
      </Text>

      {/* Status indicator */}
      {area.status === 'mining' && (
        <mesh position={[0, height / 2 + 1.8, 0]}>
          <sphereGeometry args={[0.2, 16, 16]} />
          <meshStandardMaterial color="#f59e0b" emissive="#f59e0b" emissiveIntensity={0.8} />
        </mesh>
      )}
    </group>
  );
}

// Player marker component
function PlayerMarker({ player }) {
  const meshRef = useRef();
  
  // Bobbing animation
  useFrame((state) => {
    if (meshRef.current) {
      meshRef.current.position.y = player.position.y + Math.sin(state.clock.elapsedTime * 2) * 0.1;
    }
  });

  return (
    <group position={[player.position.x, player.position.y, player.position.z]}>
      {/* Player head (Steve-like) */}
      <mesh ref={meshRef} position={[0, 1, 0]}>
        <boxGeometry args={[0.6, 0.6, 0.6]} />
        <meshStandardMaterial 
          color="#8b7355"
          emissive="#4a90e2"
          emissiveIntensity={0.3}
        />
      </mesh>

      {/* Body */}
      <mesh position={[0, 0.2, 0]}>
        <boxGeometry args={[0.6, 0.9, 0.3]} />
        <meshStandardMaterial color="#4a90e2" />
      </mesh>

      {/* Glow effect */}
      <pointLight color="#4a90e2" intensity={1} distance={3} />

      {/* Label */}
      <Text
        position={[0, 2, 0]}
        fontSize={0.4}
        color="#4a90e2"
        anchorX="center"
        anchorY="middle"
        outlineWidth={0.05}
        outlineColor="#000000"
      >
        Player {player.playerID}
      </Text>
    </group>
  );
}

// Main scene component
function Scene() {
  const turtles = useTurtleStore((state) => state.getTurtleArray());
  const players = useTurtleStore((state) => Object.values(state.players || {}));
  const selectedTurtleId = useTurtleStore((state) => state.selectedTurtleId);
  const selectTurtle = useTurtleStore((state) => state.selectTurtle);
  const worldBlocks = useTurtleStore((state) => state.worldBlocks || []);
  
  // Mining areas state
  const [miningAreas, setMiningAreas] = useState([]);
  const [selectedAreaId, setSelectedAreaId] = useState(null);

  // Load mining areas
  useEffect(() => {
    const fetchMiningAreas = async () => {
      try {
        const response = await fetch('http://localhost:3001/api/mining-areas');
        if (response.ok) {
          const data = await response.json();
          setMiningAreas(data);
        }
      } catch (error) {
        console.error('Failed to fetch mining areas:', error);
      }
    };

    fetchMiningAreas();
    const interval = setInterval(fetchMiningAreas, 5000); // Refresh every 5 seconds
    return () => clearInterval(interval);
  }, []);

  // Calculate center point for camera focus
  const centerPoint = useMemo(() => {
    if (turtles.length === 0) return [0, 0, 0];
    
    let sumX = 0, sumY = 0, sumZ = 0;
    let count = 0;

    turtles.forEach(turtle => {
      if (turtle.position) {
        sumX += turtle.position.x;
        sumY += turtle.position.y;
        sumZ += turtle.position.z;
        count++;
      }
    });

    if (count === 0) return [0, 0, 0];
    return [sumX / count, sumY / count, sumZ / count];
  }, [turtles]);

  // Get home position from first turtle
  const homePosition = turtles.find(t => t.homePosition)?.homePosition;

  return (
    <>
      <ambientLight intensity={0.6} />
      <pointLight position={[10, 10, 10]} intensity={1.2} />
      <pointLight position={[-10, -10, -10]} intensity={0.6} />
      <pointLight position={[0, 20, 0]} intensity={0.8} color="#ffffff" />

      {/* Grid */}
      <Grid
        args={[100, 100]}
        cellSize={1}
        cellThickness={0.5}
        cellColor="#1e293b"
        sectionSize={5}
        sectionThickness={1}
        sectionColor="#334155"
        fadeDistance={50}
        fadeStrength={1}
        followCamera={false}
        infiniteGrid
      />

      {/* Render discovered blocks */}
      <WorldBlocks blocks={worldBlocks} />

      {/* Mining areas */}
      {miningAreas.map((area) => {
        const turtle = turtles.find(t => t.turtleID === area.turtleID);
        return (
          <MiningArea
            key={area.areaID}
            area={area}
            turtle={turtle}
            isSelected={selectedAreaId === area.areaID}
            onClick={() => setSelectedAreaId(selectedAreaId === area.areaID ? null : area.areaID)}
          />
        );
      })}

      {/* Home marker */}
      {homePosition && <HomeMarker position={homePosition} />}

      {/* Turtles and paths */}
      {turtles.map((turtle) => (
        <React.Fragment key={turtle.turtleID}>
          <PathTrail turtle={turtle} />
          <TurtleModel
            turtle={turtle}
            isSelected={selectedTurtleId === turtle.turtleID}
            onClick={() => selectTurtle(turtle.turtleID)}
          />
        </React.Fragment>
      ))}

      {/* Players */}
      {players.map((player) => (
        <PlayerMarker key={player.playerID} player={player} />
      ))}

      {/* Camera controls */}
      <OrbitControls
        target={centerPoint}
        enableDamping
        dampingFactor={0.05}
        minDistance={5}
        maxDistance={100}
      />
    </>
  );
}

// Main Map3D component
export default function Map3D() {
  return (
    <div style={{ width: '100%', height: '100%', background: '#0a0e1a' }}>
      <Canvas
        camera={{ position: [15, 15, 15], fov: 60 }}
        style={{ background: '#0a0e1a' }}
      >
        <Scene />
      </Canvas>
    </div>
  );
}
