/**
 * Galaxies component - renders distant galaxies as billboards
 */
import { useEffect, useState, useMemo } from 'react';
import { Billboard, Text, useTexture } from '@react-three/drei';
import * as THREE from 'three';
import { fetchStaticData } from '../utils/api';

interface Galaxy {
  name: string;
  name_zh: string;
  type: string;
  distance_mly: number; // Distance in millions of light years
  ra: number; // Right Ascension in degrees
  dec: number; // Declination in degrees
  magnitude: number;
  diameter_kly: number; // Diameter in thousands of light years
  color: string;
}

/**
 * Create a procedural galaxy texture
 */
function createGalaxyTexture(color: string, type: string): THREE.Texture {
  const canvas = document.createElement('canvas');
  canvas.width = 256;
  canvas.height = 256;
  const ctx = canvas.getContext('2d')!;

  const centerX = canvas.width / 2;
  const centerY = canvas.height / 2;
  const radius = canvas.width / 2;

  // Create radial gradient for galaxy glow
  const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius);

  // Parse color
  const tempColor = new THREE.Color(color);
  const r = Math.floor(tempColor.r * 255);
  const g = Math.floor(tempColor.g * 255);
  const b = Math.floor(tempColor.b * 255);

  if (type === 'spiral') {
    // Spiral galaxy: bright core with arms
    gradient.addColorStop(0, `rgba(255, 255, 255, 1.0)`);
    gradient.addColorStop(0.1, `rgba(${r}, ${g}, ${b}, 0.9)`);
    gradient.addColorStop(0.3, `rgba(${r}, ${g}, ${b}, 0.6)`);
    gradient.addColorStop(0.6, `rgba(${r}, ${g}, ${b}, 0.3)`);
    gradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 0)`);
  } else if (type === 'irregular') {
    // Irregular galaxy: more diffuse
    gradient.addColorStop(0, `rgba(${r}, ${g}, ${b}, 0.8)`);
    gradient.addColorStop(0.4, `rgba(${r}, ${g}, ${b}, 0.5)`);
    gradient.addColorStop(0.8, `rgba(${r}, ${g}, ${b}, 0.2)`);
    gradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 0)`);
  } else {
    // Galactic center or elliptical: bright concentrated core
    gradient.addColorStop(0, `rgba(255, 255, 220, 1.0)`);
    gradient.addColorStop(0.2, `rgba(${r}, ${g}, ${b}, 0.9)`);
    gradient.addColorStop(0.5, `rgba(${r}, ${g}, ${b}, 0.5)`);
    gradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 0)`);
  }

  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  // Add some star-like points for detail (only for spiral galaxies)
  if (type === 'spiral') {
    ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
    for (let i = 0; i < 50; i++) {
      const angle = Math.random() * Math.PI * 2;
      const dist = Math.random() * radius * 0.7;
      const x = centerX + Math.cos(angle) * dist;
      const y = centerY + Math.sin(angle) * dist;
      const size = Math.random() * 1.5;
      ctx.fillRect(x, y, size, size);
    }
  }

  const texture = new THREE.CanvasTexture(canvas);
  texture.needsUpdate = true;
  return texture;
}

/**
 * Convert RA/Dec to Cartesian coordinates for distant objects
 */
function raDecToCartesian(ra: number, dec: number, distance: number) {
  const raRad = (ra * Math.PI) / 180;
  const decRad = (dec * Math.PI) / 180;

  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);
}

/**
 * Calculate visual size based on actual diameter and distance
 */
function calculateAngularSize(diameterKly: number, distanceMly: number): number {
  // Angular diameter in radians
  const angularDiameter = diameterKly / (distanceMly * 1000);
  // Significantly reduced multiplier for much smaller galaxies
  return Math.max(0.5, angularDiameter * 200);
}

export function Galaxies() {
  const [galaxies, setGalaxies] = useState<Galaxy[]>([]);

  useEffect(() => {
    // Load galaxy data from API
    fetchStaticData('galaxy')
      .then((response) => {
        // Convert API response to Galaxy format
        const galaxyData = response.items.map((item) => ({
          name: item.name,
          name_zh: item.name_zh,
          type: item.data.type,
          distance_mly: item.data.distance_mly,
          ra: item.data.ra,
          dec: item.data.dec,
          magnitude: item.data.magnitude,
          diameter_kly: item.data.diameter_kly,
          color: item.data.color,
        }));
        setGalaxies(galaxyData);
      })
      .catch((err) => console.error('Failed to load galaxies:', err));
  }, []);

  const galaxyData = useMemo(() => {
    return galaxies.map((galaxy) => {
      // Place galaxies on celestial sphere at fixed distance for visualization
      const visualDistance = 200; // Fixed distance for celestial sphere
      const position = raDecToCartesian(galaxy.ra, galaxy.dec, visualDistance);

      // Calculate visual size based on actual properties
      const size = galaxy.type === 'galactic_center'
        ? 2 // Smaller for Milky Way center
        : calculateAngularSize(galaxy.diameter_kly, galaxy.distance_mly);

      // Create procedural texture for this galaxy
      const texture = createGalaxyTexture(galaxy.color, galaxy.type);

      return {
        ...galaxy,
        position,
        size,
        texture,
      };
    });
  }, [galaxies]);

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

  return (
    <group>
      {galaxyData.map((galaxy) => (
        <group key={galaxy.name}>
          <Billboard
            position={galaxy.position}
            follow={true}
            lockX={false}
            lockY={false}
            lockZ={false}
          >
            {/* Galaxy texture */}
            <mesh>
              <planeGeometry args={[galaxy.size * 3, galaxy.size * 3]} />
              <meshBasicMaterial
                map={galaxy.texture}
                transparent
                opacity={0.8}
                blending={THREE.AdditiveBlending}
                depthWrite={false}
              />
            </mesh>
          </Billboard>

          {/* Galaxy name label - positioned slightly outward from galaxy */}
          <Billboard position={galaxy.position.clone().multiplyScalar(1.03)}>
            <Text
              fontSize={1.5}
              color="#DDAAFF"
              anchorX="center"
              anchorY="middle"
              outlineWidth={0.1}
              outlineColor="#000000"
            >
              {galaxy.name_zh}
            </Text>
          </Billboard>
        </group>
      ))}
    </group>
  );
}
