'use client';

import {useEffect,useId,useRef,type CSSProperties} from 'react';
import {HeroTagline} from './hero-tagline';
import {createHeroMagicRings} from './hero-magic-rings';
import {HeroAssetMap,type HeroAssetMapHandle} from './hero-asset-map';
import {heroAnimationFrame,HERO_ORBIT_TRAVEL_MS} from '@/lib/hero-animation';
import {heroAssetFrame,HERO_ASSETS} from '@/lib/hero-assets';

const ARC = 'M 40 650 A 560 560 0 0 1 1160 650';
const FULL_ORBIT = `${ARC} A 560 560 0 0 1 40 650`;

export function Orbit({caption,direction='rtl',paused=false,reducedMotion=false,onThemeProgress,onTogglePause}:{
  caption:string;
  direction?:'rtl'|'ltr';
  paused?:boolean;
  reducedMotion?:boolean;
  onThemeProgress?:(progress:number)=>void;
  onTogglePause:()=>void;
}) {
  const id=useId().replace(/:/g,'');
  const field=useRef<HTMLDivElement>(null);
  const path=useRef<SVGPathElement>(null);
  const particle=useRef<SVGGElement>(null);
  const ringsCanvas=useRef<HTMLCanvasElement>(null);
  const rings=useRef<ReturnType<typeof createHeroMagicRings>>(null);
  const elapsed=useRef(0);
  const map=useRef<HeroAssetMapHandle>(null);
  const assetCaption=useRef<HTMLSpanElement>(null);
  const assetName=useRef<HTMLSpanElement>(null);

  useEffect(()=>{
    const canvas=ringsCanvas.current;
    if(!canvas)return;
    rings.current=createHeroMagicRings(canvas);
    return()=>{rings.current?.dispose();rings.current=null;};
  },[]);

  useEffect(()=>{
    const arc=path.current;
    if(!arc)return;
    const length=arc.getTotalLength();
    let lastMix=-1;
    const render=()=>{
      const frame=heroAnimationFrame(elapsed.current);
      const point=arc.getPointAtLength(length*frame.position);
      particle.current?.setAttribute('transform',`translate(${point.x} ${point.y})`);
      particle.current?.setAttribute('opacity',String(frame.opacity));
      rings.current?.render(frame.elapsedMs,frame.lightMix);
      map.current?.render(frame);
      const asset=heroAssetFrame(frame.elapsedMs,reducedMotion);
      if(assetCaption.current){
        assetCaption.current.style.opacity=String(asset.opacity);
        assetCaption.current.style.setProperty('--asset-color',asset.item.color);
        assetCaption.current.style.setProperty('--asset-light-color',asset.item.lightColor);
      }
      if(assetName.current){
        const name=direction==='ltr'?asset.item.en:asset.item.fa;
        if(assetName.current.textContent!==name)assetName.current.textContent=name;
      }
      if(frame.lightMix!==lastMix){
        field.current?.style.setProperty('--hero-plank-mix',String(frame.lightMix));
        onThemeProgress?.(frame.lightMix);
        lastMix=frame.lightMix;
      }
    };
    if(reducedMotion){
      elapsed.current=HERO_ORBIT_TRAVEL_MS/2;
      render();
      return;
    }
    render();
    if(paused)return;
    let frame=0;
    let previous:number|null=null;
    let visible=true;
    const tick=(now:number)=>{
      if(previous!==null)elapsed.current+=Math.min(now-previous,64);
      previous=now;
      render();
      frame=requestAnimationFrame(tick);
    };
    const visibility=()=>{
      cancelAnimationFrame(frame);
      previous=null;
      if(!document.hidden&&visible)frame=requestAnimationFrame(tick);
    };
    const observer=new IntersectionObserver(([entry])=>{visible=entry.isIntersecting;visibility();});
    if(field.current)observer.observe(field.current);
    visibility();
    document.addEventListener('visibilitychange',visibility);
    return()=>{cancelAnimationFrame(frame);observer.disconnect();document.removeEventListener('visibilitychange',visibility)};
  },[paused,reducedMotion,onThemeProgress,direction]);

  return <div ref={field} className="orbit-field">
    <div className="orbit-magic-rings" aria-hidden="true"><canvas ref={ringsCanvas}/></div>
    <HeroAssetMap ref={map} paused={paused} reducedMotion={reducedMotion} onTogglePause={onTogglePause}/>
    <div className="orbit-caption" dir={direction}>
      <HeroTagline text={caption} direction={direction} paused={paused} reducedMotion={reducedMotion}/>
      <span ref={assetCaption} className="hero-asset-caption" style={{'--asset-color':HERO_ASSETS[0].color,'--asset-light-color':HERO_ASSETS[0].lightColor,opacity:reducedMotion?1:0} as CSSProperties}>
        <i className="hero-asset-dot" aria-hidden="true"/>
        <span ref={assetName}>{direction==='ltr'?HERO_ASSETS[0].en:HERO_ASSETS[0].fa}</span>
      </span>
    </div>
    <svg viewBox="0 0 1200 710" aria-hidden="true" focusable="false">
      <defs>
        <path ref={path} d={FULL_ORBIT}/>
        <linearGradient id={`${id}-warm`}><stop stopColor="#345b97"/><stop offset=".37" stopColor="#91bbed"/><stop offset=".6" stopColor="#648ad0"/><stop offset="1" stopColor="#1b315f"/></linearGradient>
        <linearGradient id={`${id}-plank`}><stop stopColor="#518bce"/><stop offset=".45" stopColor="#a3c9ee"/><stop offset="1" stopColor="#294e91"/></linearGradient>
        <linearGradient id={`${id}-inner`}><stop stopColor="#1d355c" stopOpacity="0"/><stop offset=".5" stopColor="#718fbc" stopOpacity=".25"/><stop offset="1" stopColor="#152544" stopOpacity="0"/></linearGradient>
        <linearGradient id={`${id}-bottom-fade`} gradientUnits="userSpaceOnUse" x1="0" y1="440" x2="0" y2="650">
          <stop stopColor="white"/>
          <stop offset=".30" stopColor="white" stopOpacity=".85"/>
          <stop offset=".65" stopColor="white" stopOpacity=".35"/>
          <stop offset=".86" stopColor="white" stopOpacity=".07"/>
          <stop offset="1" stopColor="white" stopOpacity="0"/>
        </linearGradient>
        <mask id={`${id}-soft-bottom`} maskUnits="userSpaceOnUse" x="-120" y="-80" width="1440" height="880" style={{maskType:'alpha'}}>
          <rect x="-120" y="-80" width="1440" height="880" fill={`url(#${id}-bottom-fade)`}/>
        </mask>
        <clipPath id={`${id}-dome`}><path d={`${ARC} Z`}/></clipPath>
        <filter id={`${id}-glow`} x="-120" y="-80" width="1440" height="880" filterUnits="userSpaceOnUse" colorInterpolationFilters="sRGB">
          <feGaussianBlur stdDeviation="24"/>
        </filter>
      </defs>
      <g mask={`url(#${id}-soft-bottom)`}>
        <g className="orbit-underglow" clipPath={`url(#${id}-dome)`}>
          <path className="orbit-warm" d={ARC} fill="none" stroke={`url(#${id}-warm)`} strokeWidth="76" filter={`url(#${id}-glow)`}/>
          <path className="orbit-plank" d={ARC} fill="none" stroke={`url(#${id}-plank)`} strokeWidth="76" filter={`url(#${id}-glow)`}/>
        </g>
        <path className="orbit-warm" d={ARC} fill="none" stroke={`url(#${id}-warm)`} strokeWidth="1.2"/>
        <path className="orbit-plank" d={ARC} fill="none" stroke={`url(#${id}-plank)`} strokeWidth="1.4"/>
        <path className="orbit-warm" d="M 78 650 A 522 522 0 0 1 1122 650" fill="none" stroke={`url(#${id}-inner)`} strokeWidth=".7"/>
        <path className="orbit-plank orbit-inner-plank" d="M 78 650 A 522 522 0 0 1 1122 650" fill="none" stroke={`url(#${id}-plank)`} strokeWidth=".7"/>
      </g>
      <g ref={particle} className="orbit-particle" transform="translate(40 650)" opacity="0">
        <image href="/images/plank-logo-white.svg" x="-17" y="-22" width="34" height="44" preserveAspectRatio="xMidYMid meet"/>
        <image href="/images/plank-symbol.svg" x="-17" y="-22" width="34" height="44" preserveAspectRatio="xMidYMid meet"/>
      </g>
    </svg>
  </div>;
}
