/**
 * OrbitRenderer - Unified orbit rendering component
 * Renders precomputed orbital paths for all celestial bodies (planets and dwarf planets)
 */
import { useEffect, useState } from 'react';
import { Line } from '@react-three/drei';
import * as THREE from 'three';
import { scalePosition } from '../utils/scaleDistance';
import { request } from '../utils/request';

interface OrbitData {
  bodyId: string;
  bodyName: string;
  bodyNameZh: string | null;
  points: THREE.Vector3[];
  color: string;
  numPoints: number;
  periodDays: number | null;
}

interface OrbitRendererProps {
  visible?: boolean;
}

export function OrbitRenderer({ visible = true }: OrbitRendererProps) {
  const [orbits, setOrbits] = useState<OrbitData[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchOrbits = async () => {
      try {
        // Fetch precomputed orbits from backend
        const response = await request.get('/celestial/orbits');
        const data = response.data;

        if (!data.orbits || data.orbits.length === 0) {
          console.warn('⚠️ No orbital data found in database');
          setLoading(false);
          setError('No orbital data available. Please generate orbits first.');
          return;
        }

        // Convert to Three.js format
        const orbitData: OrbitData[] = data.orbits.map((orbit: any) => {
          // Convert position points to Vector3 with scaling
          const points = orbit.points.map((p: any) => {
            const scaled = scalePosition(p.x, p.y, p.z);
            // Convert to Three.js coordinate system (x, z, y)
            return new THREE.Vector3(scaled.x, scaled.z, scaled.y);
          });

          // Close the orbit loop if first and last points are close
          if (points.length > 1) {
            const firstPoint = points[0];
            const lastPoint = points[points.length - 1];
            const distance = firstPoint.distanceTo(lastPoint);

            // If endpoints are close (within 5 units), close the loop
            if (distance < 5) {
              points.push(firstPoint.clone());
            }
          }

          return {
            bodyId: orbit.body_id,
            bodyName: orbit.body_name,
            bodyNameZh: orbit.body_name_zh,
            points,
            color: orbit.color || '#CCCCCC',
            numPoints: orbit.num_points,
            periodDays: orbit.period_days,
          };
        });

        setOrbits(orbitData);
        setLoading(false);

      } catch (err) {
        console.error('❌ Failed to load orbits:', err);
        setError(err instanceof Error ? err.message : 'Unknown error');
        setLoading(false);
      }
    };

    fetchOrbits();
  }, []);

  if (loading) {
    return null;
  }

  if (error) {
    console.error('⚠️ Orbit rendering error:', error);
    return null;
  }

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

  return (
    <group visible={visible}>
      {orbits.map((orbit) => (
        <Line
          key={orbit.bodyId}
          points={orbit.points}
          color={orbit.color}
          lineWidth={1.5}
          opacity={0.4}
          transparent
        />
      ))}
    </group>
  );
}
