'use client'

import { useRef, useMemo, Suspense } from 'react'
import { Canvas, useFrame, useThree } from '@react-three/fiber'
import { Stars, useTexture } from '@react-three/drei'
import * as THREE from 'three'

/* ----------------------------- Starfield drift ---------------------------- */
function DriftingStars() {
  const ref = useRef<THREE.Group>(null)
  useFrame((_, delta) => {
    if (ref.current) {
      ref.current.rotation.y += delta * 0.006
      ref.current.rotation.x += delta * 0.002
    }
  })
  return (
    <group ref={ref}>
      <Stars
        radius={120}
        depth={70}
        count={6000}
        factor={4}
        saturation={0}
        fade
        speed={0.6}
      />
    </group>
  )
}

/* ------------------------------ Nebula clouds ----------------------------- */
function Nebula() {
  const tex = useMemo(() => {
    const size = 256
    const canvas = document.createElement('canvas')
    canvas.width = canvas.height = size
    const ctx = canvas.getContext('2d')!
    const grad = ctx.createRadialGradient(
      size / 2,
      size / 2,
      0,
      size / 2,
      size / 2,
      size / 2,
    )
    grad.addColorStop(0, 'rgba(124,58,237,0.55)')
    grad.addColorStop(0.4, 'rgba(0,229,255,0.18)')
    grad.addColorStop(1, 'rgba(3,7,18,0)')
    ctx.fillStyle = grad
    ctx.fillRect(0, 0, size, size)
    return new THREE.CanvasTexture(canvas)
  }, [])

  const clouds = useMemo(
    () =>
      Array.from({ length: 7 }).map(() => ({
        position: [
          (Math.random() - 0.5) * 90,
          (Math.random() - 0.5) * 50,
          -30 - Math.random() * 50,
        ] as [number, number, number],
        scale: 25 + Math.random() * 40,
        rot: Math.random() * Math.PI,
      })),
    [],
  )

  return (
    <group>
      {clouds.map((c, i) => (
        <sprite key={i} position={c.position} scale={[c.scale, c.scale, 1]}>
          <spriteMaterial
            map={tex}
            transparent
            opacity={0.4}
            depthWrite={false}
            blending={THREE.AdditiveBlending}
          />
        </sprite>
      ))}
    </group>
  )
}

/* --------------------------- Textured Saturn ring -------------------------- */
function SaturnRing({ inner, outer }: { inner: number; outer: number }) {
  const tex = useTexture('/textures/saturn-ring.png')

  // Build a ring geometry whose UVs map radially so the strip texture
  // reads from inner edge -> outer edge.
  const geometry = useMemo(() => {
    const g = new THREE.RingGeometry(inner, outer, 128)
    const pos = g.attributes.position
    const uv = g.attributes.uv
    const v = new THREE.Vector3()
    for (let i = 0; i < pos.count; i++) {
      v.fromBufferAttribute(pos, i)
      const dist = v.length()
      const u = (dist - inner) / (outer - inner)
      uv.setXY(i, u, 0.5)
    }
    return g
  }, [inner, outer])

  return (
    <mesh geometry={geometry} rotation={[Math.PI / 2.4, 0, 0]}>
      <meshStandardMaterial
        map={tex}
        transparent
        opacity={0.92}
        side={THREE.DoubleSide}
        roughness={0.9}
        alphaTest={0.05}
      />
    </mesh>
  )
}

/* ------------------------------ Textured planet --------------------------- */
function Planet({
  radius,
  texture,
  cloudTexture,
  glow,
  orbitRadius,
  speed,
  startAngle = 0,
  y = 0,
  ring = false,
  tilt = 0,
}: {
  radius: number
  texture: string
  cloudTexture?: string
  glow: string
  orbitRadius: number
  speed: number
  startAngle?: number
  y?: number
  ring?: boolean
  tilt?: number
}) {
  const group = useRef<THREE.Group>(null)
  const mesh = useRef<THREE.Mesh>(null)
  const clouds = useRef<THREE.Mesh>(null)

  const map = useTexture(texture)
  map.colorSpace = THREE.SRGBColorSpace
  map.anisotropy = 8

  const cloudMap = cloudTexture ? useTexture(cloudTexture) : null
  if (cloudMap) cloudMap.colorSpace = THREE.SRGBColorSpace

  useFrame((state) => {
    const t = state.clock.getElapsedTime() * speed + startAngle
    if (group.current) {
      group.current.position.x = Math.cos(t) * orbitRadius
      group.current.position.z = Math.sin(t) * orbitRadius * 0.5
    }
    if (mesh.current) mesh.current.rotation.y += 0.0025
    if (clouds.current) clouds.current.rotation.y += 0.0034
  })

  return (
    <group ref={group} position={[orbitRadius, y, 0]} rotation={[0, 0, tilt]}>
      {/* planet body */}
      <mesh ref={mesh}>
        <sphereGeometry args={[radius, 64, 64]} />
        <meshStandardMaterial
          map={map}
          emissiveMap={map}
          emissive="#ffffff"
          emissiveIntensity={0.65}
          roughness={0.85}
          metalness={0.05}
        />
      </mesh>

      {/* cloud layer */}
      {cloudMap && (
        <mesh ref={clouds} scale={1.02}>
          <sphereGeometry args={[radius, 48, 48]} />
          <meshStandardMaterial
            map={cloudMap}
            transparent
            opacity={0.55}
            depthWrite={false}
            blending={THREE.AdditiveBlending}
          />
        </mesh>
      )}

      {ring && <SaturnRing inner={radius * 1.35} outer={radius * 2.2} />}
    </group>
  )
}

/* ------------------------------- Sun (bright) ----------------------------- */
function Sun() {
  const ref = useRef<THREE.Mesh>(null)
  const map = useTexture('/textures/sun.png')
  map.colorSpace = THREE.SRGBColorSpace
  useFrame((_, d) => {
    if (ref.current) ref.current.rotation.y += d * 0.04
  })
  return (
    <group position={[26, 9, -10]}>
      <pointLight intensity={3} distance={140} color="#ffcaa0" />
      <mesh ref={ref}>
        <sphereGeometry args={[3.4, 64, 64]} />
        <meshBasicMaterial map={map} toneMapped={false} />
      </mesh>
    </group>
  )
}

/* ------------------------------ Mouse parallax ---------------------------- */
function ParallaxRig() {
  const { camera } = useThree()
  useFrame((state) => {
    const x = state.pointer.x * 2.2
    const y = state.pointer.y * 1.4
    camera.position.x += (x - camera.position.x) * 0.03
    camera.position.y += (y - camera.position.y) * 0.03
    camera.lookAt(0, 0, 0)
  })
  return null
}

function Scene() {
  return (
    <>
      <ambientLight intensity={1.1} />
      {/* fill light to keep planets fully lit (no dark side) */}
      <directionalLight position={[26, 9, -10]} intensity={1.2} color="#fff3e0" />
      <DriftingStars />
      <Nebula />
      <Sun />
      {/* Earth */}
      <Planet
        radius={1.6}
        texture="/textures/earth.png"
        cloudTexture="/textures/earth-clouds.png"
        glow="#3b82f6"
        orbitRadius={20}
        speed={0.12}
        startAngle={2.4}
        y={5}
        tilt={0.41}
      />
      {/* Moon */}
      <Planet
        radius={0.9}
        texture="/textures/moon.png"
        glow="#94a3b8"
        orbitRadius={16}
        speed={0.22}
        startAngle={4.8}
        y={-7}
      />
      {/* Saturn */}
      <Planet
        radius={1.9}
        texture="/textures/saturn.png"
        glow="#d8b878"
        orbitRadius={24}
        speed={0.08}
        startAngle={3.6}
        y={-4}
        ring
        tilt={0.47}
      />
      <ParallaxRig />
    </>
  )
}

export default function GalaxyBackground() {
  return (
    <div className="fixed inset-0 -z-10">
      <Canvas
        camera={{ position: [0, 0, 30], fov: 60 }}
        dpr={[1, 1.6]}
        gl={{ antialias: true, alpha: true, powerPreference: 'high-performance' }}
      >
        <color attach="background" args={['#030712']} />
        <fog attach="fog" args={['#030712', 35, 90]} />
        <Suspense fallback={null}>
          <Scene />
        </Suspense>
      </Canvas>
      {/* vignette + glow overlays */}
      <div
        className="pointer-events-none absolute inset-0"
        style={{
          background:
            'radial-gradient(circle at 50% 45%, rgba(0,229,255,0.06), transparent 45%), radial-gradient(circle at 80% 20%, rgba(255,138,60,0.08), transparent 35%), radial-gradient(ellipse at 50% 100%, rgba(124,58,237,0.1), transparent 55%)',
        }}
      />
      <div
        className="pointer-events-none absolute inset-0"
        style={{
          boxShadow: 'inset 0 0 220px 60px rgba(3,7,18,0.9)',
        }}
      />
    </div>
  )
}
