/**
 * Stars component - renders nearby stars in 3D space
 */
import { useEffect, useState, useMemo } from 'react';
import { Billboard, Html } from '@react-three/drei';
import * as THREE from 'three';
import { request } from '../utils/request';
import { createLabelTexture } from '../utils/labelTexture';

interface Star {
  name: string;
  name_zh: string;
  distance_ly: number;
  ra: number; // Right Ascension in degrees
  dec: number; // Declination in degrees
  magnitude: number;
  color: string;
  position: THREE.Vector3;
  size: number;
  rawData?: any; // Add optional rawData field
}

/**
 * Convert RA/Dec to Cartesian coordinates
 * RA: Right Ascension (0-360 degrees)
 * Dec: Declination (-90 to 90 degrees)
 * Distance: fixed distance for celestial sphere
 */
function raDecToCartesian(ra: number, dec: number, distance: number = 5000) {
  // Convert to radians
  const raRad = (ra * Math.PI) / 180;
  const decRad = (dec * Math.PI) / 180;

  // Convert to Cartesian coordinates
  const x = distance * Math.cos(decRad) * Math.cos(raRad);
  const y = distance * Math.cos(decRad) * Math.sin(raRad);
  const z = distance * Math.sin(decRad);

  return new THREE.Vector3(x, y, z);
}

/**
 * Scale star brightness based on magnitude
 * Lower magnitude = brighter star
 */
function magnitudeToSize(magnitude: number): number {
  // Brighter stars (lower magnitude) should be slightly larger
  // But all stars should be very small compared to planets
  const normalized = Math.max(-2, Math.min(12, magnitude));
  return Math.max(5, 20 - normalized * 1.2);
}

// Sub-component for individual star to handle label texture efficiently
function StarObject({ star, geometry, mode, onStarClick }: { 
  star: Star; 
  geometry: THREE.SphereGeometry; 
  mode: 'sky' | 'galaxy';
  onStarClick?: (star: Star) => void;
}) {
  const [hovered, setHovered] = useState(false);

  // Generate label texture
  const labelTexture = useMemo(() => {
    // For galaxy mode, use a slightly different label style if needed
    // Currently reusing same generator
    return createLabelTexture(star.name_zh, null, "", "#FFFFFF");
  }, [star.name_zh]);

  // Adjust visual parameters based on mode
  const baseSize = mode === 'galaxy' ? star.size * 8 : star.size; // Make stars larger in galaxy mode
  const visualSize = hovered ? baseSize * 1.5 : baseSize; // Scale up on hover
  
  const labelScale: [number, number, number] = mode === 'galaxy' ? [50, 25, 1] : [200, 100, 1]; // Smaller labels in galaxy mode
  const labelOffset = mode === 'galaxy' ? 4 : 1.05; // Offset factor

  // Handle cursor
  useEffect(() => {
    document.body.style.cursor = hovered ? 'pointer' : 'auto';
    return () => { document.body.style.cursor = 'auto'; };
  }, [hovered]);

  return (
    <group
      onClick={(e) => {
        console.log('Star clicked:', star.name);
        e.stopPropagation();
        onStarClick?.(star);
      }}
      onPointerOver={(e) => {
        console.log('Pointer over:', star.name);
        e.stopPropagation();
        setHovered(true);
      }}
      onPointerOut={(e) => {
        e.stopPropagation();
        setHovered(false);
      }}
    >
      {/* Star sphere */}
      <mesh position={star.position} geometry={geometry} scale={[visualSize, visualSize, visualSize]}>
        <meshBasicMaterial
          color={hovered ? '#ffaa00' : star.color} // Highlight color on hover
          transparent
          opacity={0.9}
          blending={THREE.AdditiveBlending}
        />
      </mesh>

      {/* Star glow */}
      <mesh position={star.position} geometry={geometry} scale={[visualSize * 2, visualSize * 2, visualSize * 2]}>
        <meshBasicMaterial
          color={hovered ? '#ffaa00' : star.color}
          transparent
          opacity={0.2}
          blending={THREE.AdditiveBlending}
        />
      </mesh>

      {/* Star name label */}
      {labelTexture && (
        <Billboard position={mode === 'galaxy'
          ? new THREE.Vector3(star.position.x, star.position.y + visualSize + 2, star.position.z)
          : star.position.clone().multiplyScalar(labelOffset)
        }>
          <mesh scale={labelScale}>
            <planeGeometry />
            <meshBasicMaterial
              map={labelTexture}
              transparent
              opacity={hovered ? 1.0 : (mode === 'galaxy' ? 0.6 : 1.0)} // Fully opaque on hover
              depthWrite={false}
              toneMapped={false}
            />
          </mesh>
        </Billboard>
      )}

      {/* Hover Tooltip in Galaxy Mode */}
      {mode === 'galaxy' && hovered && star.rawData && (
        <Html
          position={[star.position.x, star.position.y + visualSize + 8, star.position.z]}
          center
          style={{
            pointerEvents: 'none',
            userSelect: 'none',
          }}
        >
          <div className="bg-black/90 border border-blue-400/50 rounded-lg px-4 py-3 text-white text-xs shadow-2xl backdrop-blur-sm min-w-[280px]">
            <div className="font-bold text-sm mb-2 text-blue-300">{star.name_zh || star.name}</div>
            <div className="space-y-1">
              <div className="flex justify-between">
                <span className="text-gray-400">距离:</span>
                <span>{star.rawData.distance_pc?.toFixed(2) ?? 'N/A'} pc (~{star.distance_ly?.toFixed(2) ?? 'N/A'} ly)</span>
              </div>
              {star.rawData.spectral_type && (
                <div className="flex justify-between">
                  <span className="text-gray-400">光谱类型:</span>
                  <span>{star.rawData.spectral_type}</span>
                </div>
              )}
              {star.rawData.radius_solar && (
                <div className="flex justify-between">
                  <span className="text-gray-400">半径:</span>
                  <span>{star.rawData.radius_solar.toFixed(2)} R☉</span>
                </div>
              )}
              {star.rawData.mass_solar && (
                <div className="flex justify-between">
                  <span className="text-gray-400">质量:</span>
                  <span>{star.rawData.mass_solar.toFixed(2)} M☉</span>
                </div>
              )}
              {star.rawData.temperature_k && (
                <div className="flex justify-between">
                  <span className="text-gray-400">温度:</span>
                  <span>{star.rawData.temperature_k.toFixed(0)} K</span>
                </div>
              )}
              {star.rawData.planet_count !== undefined && (
                <div className="flex justify-between">
                  <span className="text-gray-400">行星数量:</span>
                  <span className="text-green-400 font-semibold">{star.rawData.planet_count}</span>
                </div>
              )}
            </div>
            <div className="text-gray-500 text-[10px] mt-2 text-center">点击查看详细信息</div>
          </div>
        </Html>
      )}
    </group>
  );
}

export function Stars({ mode = 'sky', onStarClick }: { mode?: 'sky' | 'galaxy'; onStarClick?: (star: Star) => void }) {
  const [stars, setStars] = useState<Star[]>([]);

  useEffect(() => {
    if (mode === 'galaxy') {
      // Galaxy Mode: Load from new star-systems API
      request.get('/star-systems', { params: { limit: 1000, exclude_solar: false } })
        .then((res) => {
          const { systems } = res.data;
          // Process star systems data
          const starData = systems
            .filter((system: any) => system.position_x != null && system.position_y != null && system.position_z != null)
            .map((system: any) => {
              // Galaxy Mode: Use 3D coordinates from database (Parsecs)
              // Scale factor to make the visualization comfortable
              const SCALE = 100;
              const position = new THREE.Vector3(
                system.position_x * SCALE,
                system.position_y * SCALE,
                system.position_z * SCALE
              );

              // Calculate size based on radius_solar if available
              const radius = system.radius_solar || 1.0;
              const size = Math.max(0.5, Math.log(radius + 1) * 2);

              // Calculate distance_ly if not provided
              const distance_ly = system.distance_ly || (system.distance_pc ? system.distance_pc * 3.26 : null);

              return {
                name: system.name,
                name_zh: system.name_zh,
                distance_ly,
                ra: system.ra,
                dec: system.dec,
                magnitude: system.magnitude,
                color: system.color || '#ffffff',
                position,
                size,
                // Pass complete system data for details view and hover tooltip
                rawData: system
              };
            });
          setStars(starData);
        })
        .catch((err) => console.error('Failed to load star systems:', err));
    } else {
      // Sky Mode: Load from static data API
      request.get('/celestial/static/star')
        .then((res) => {
          const data = res.data;
          const starData = data.items.map((item: any) => {
            // Sky Mode: Project to Celestial Sphere
            const position = raDecToCartesian(item.data.ra, item.data.dec, 5000);
            const size = magnitudeToSize(item.data.magnitude);

            return {
              name: item.name,
              name_zh: item.name_zh,
              distance_ly: item.data.distance_ly || (item.data.distance_pc ? item.data.distance_pc * 3.26 : null),
              ra: item.data.ra,
              dec: item.data.dec,
              magnitude: item.data.magnitude,
              color: item.data.color,
              position,
              size,
              rawData: item.data
            };
          });
          setStars(starData);
        })
        .catch((err) => console.error('Failed to load stars:', err));
    }
  }, [mode]);

  // Reuse geometry for all stars to improve performance
  const sphereGeometry = useMemo(() => new THREE.SphereGeometry(1, 16, 16), []);

  if (stars.length === 0) {
    return null;
  }

  return (
    <group>
      {stars.map((star) => (
        <StarObject 
          key={star.name} 
          star={star} 
          geometry={sphereGeometry} 
          mode={mode} 
          onStarClick={onStarClick}
        />
      ))}
    </group>
  );
}
