// Open Octi — Coming Soon aquarium scene
const { useState, useEffect, useRef, useMemo } = React;

// ─── Caustic projection (animated SVG turbulence as a full-bleed layer) ───
function Caustics() {
  return (
    <>
      <svg className="caustics" preserveAspectRatio="none" viewBox="0 0 100 100">
        <rect width="100" height="100" filter="url(#caustic)" />
      </svg>
      <svg className="caustics" preserveAspectRatio="none" viewBox="0 0 100 100" style={{opacity: 0.35, mixBlendMode:'screen', filter:'blur(4px)'}}>
        <rect width="100" height="100" filter="url(#caustic2)" />
      </svg>
    </>
  );
}

// ─── God rays ───
function GodRays() {
  const rays = [
    {x: 12, w: 70, rot: -8, op: 0.65},
    {x: 28, w: 50, rot: -4, op: 0.5},
    {x: 45, w: 90, rot: 2,  op: 0.7},
    {x: 62, w: 60, rot: 6,  op: 0.55},
    {x: 78, w: 80, rot: 10, op: 0.6},
    {x: 88, w: 40, rot: 14, op: 0.4},
  ];
  return (
    <svg className="rays" preserveAspectRatio="none" viewBox="0 0 100 100">
      {rays.map((r,i) => (
        <polygon key={i}
          points={`${r.x-r.w*0.05},0 ${r.x+r.w*0.05},0 ${r.x+r.w*0.5},100 ${r.x-r.w*0.5},100`}
          fill="url(#ray)"
          opacity={r.op}
          transform={`rotate(${r.rot} ${r.x} 0)`}
          style={{
            animation: `rayPulse ${6+i*1.3}s ease-in-out infinite alternate`,
            transformOrigin: `${r.x}% 0%`,
          }}
        />
      ))}
      <style>{`
        @keyframes rayPulse {
          0%   { opacity: 0.25; }
          100% { opacity: 0.8;  }
        }
      `}</style>
    </svg>
  );
}

// ─── Bubbles rising ───
function Bubbles() {
  const bubbles = useMemo(() => {
    return Array.from({length: 38}).map((_, i) => {
      const size = 4 + Math.random() * 22;
      return {
        size,
        left: Math.random() * 100,
        dur: 9 + Math.random() * 16,
        delay: -Math.random() * 25,
        drift: (Math.random() - 0.5) * 80,
      };
    });
  }, []);
  return (
    <div className="bubbles">
      {bubbles.map((b, i) => (
        <span key={i} className="bubble"
          style={{
            width: b.size, height: b.size,
            left: `${b.left}%`,
            animationDuration: `${b.dur}s`,
            animationDelay: `${b.delay}s`,
            '--drift': `${b.drift}px`,
          }}
        />
      ))}
    </div>
  );
}

// ─── Marine snow ───
function Snow() {
  const motes = useMemo(() => Array.from({length: 70}).map(() => ({
    left: Math.random() * 100,
    top: -10 - Math.random() * 30,
    size: 1 + Math.random() * 2.5,
    dur: 25 + Math.random() * 40,
    delay: -Math.random() * 50,
    opacity: 0.3 + Math.random() * 0.5,
  })), []);
  return (
    <div className="snow">
      {motes.map((m, i) => (
        <span key={i} className="mote"
          style={{
            left: `${m.left}%`,
            top: `${m.top}%`,
            width: m.size, height: m.size,
            animationDuration: `${m.dur}s`,
            animationDelay: `${m.delay}s`,
            opacity: m.opacity,
          }}
        />
      ))}
    </div>
  );
}

// ─── Kelp ───
function KelpStrand({ left, height, hue, delay, scale }) {
  // a single kelp drawn as a series of overlapping ovals (leaves)
  const leaves = Math.floor(height / 22);
  return (
    <div className="kelp" style={{
      left: `${left}%`,
      height: `${height}vh`,
      animationDelay: `${delay}s`,
      transform: `scaleX(${scale})`,
    }}>
      <svg width="60" height={`${height}vh`} viewBox={`0 0 60 ${leaves*22}`} style={{display:'block', overflow:'visible'}}>
        {/* stalk */}
        <path d={`M30 ${leaves*22} Q ${28 + Math.sin(delay)*6} ${leaves*11} ${30 - Math.sin(delay)*3} 0`}
              stroke={`hsl(${hue}, 60%, 14%)`} strokeWidth="3" fill="none" strokeLinecap="round"/>
        {Array.from({length: leaves}).map((_, i) => {
          const y = leaves*22 - i*22;
          const side = i % 2 === 0 ? 1 : -1;
          return (
            <ellipse key={i} cx={30 + side * (10 + Math.random()*4)} cy={y - 6}
                     rx="14" ry="4"
                     fill={`hsl(${hue}, 55%, ${10 + i*1.2}%)`}
                     transform={`rotate(${side * 25} ${30 + side*10} ${y-6})`}
                     opacity="0.85"/>
          );
        })}
      </svg>
    </div>
  );
}

function KelpForest() {
  const strands = useMemo(() => ([
    {left: 2,  height: 70, hue: 200, delay: 0,   scale: 1},
    {left: 8,  height: 55, hue: 195, delay: 1.5, scale: -1},
    {left: 14, height: 45, hue: 205, delay: 0.7, scale: 1},
    {left: 88, height: 60, hue: 200, delay: 0.3, scale: -1},
    {left: 94, height: 75, hue: 198, delay: 1.1, scale: 1},
  ]), []);
  return (
    <div className="kelp-layer">
      {strands.map((s, i) => <KelpStrand key={i} {...s} />)}
    </div>
  );
}

// ─── Fish schools ───
function School({ klass }) {
  const sizes = ['', 's2', 's3', '', 's2', '', 's3', 's2'];
  return (
    <div className={`school ${klass||''}`}>
      {sizes.map((s,i) => <span key={i} className={`fish ${s}`} style={{
        transform: `translateY(${Math.sin(i)*6}px)`,
      }}/>)}
    </div>
  );
}

// ─── Countdown ───
function useCountdown(targetISO) {
  const [t, setT] = useState(() => computeT(targetISO));
  useEffect(() => {
    const id = setInterval(() => setT(computeT(targetISO)), 1000);
    return () => clearInterval(id);
  }, [targetISO]);
  return t;
}
function computeT(targetISO) {
  const target = new Date(targetISO).getTime();
  const now = Date.now();
  let diff = Math.max(0, target - now);
  const days = Math.floor(diff / 86400000); diff -= days * 86400000;
  const hours = Math.floor(diff / 3600000); diff -= hours * 3600000;
  const mins = Math.floor(diff / 60000); diff -= mins * 60000;
  const secs = Math.floor(diff / 1000);
  return { days, hours, mins, secs };
}
function pad(n) { return String(n).padStart(2,'0'); }

function Countdown({ target }) {
  const { days, hours, mins, secs } = useCountdown(target);
  return (
    <div className="countdown">
      <div className="cd-cell"><div className="num">{pad(days)}</div><div className="lbl">Days</div></div>
      <div className="cd-cell"><div className="num">{pad(hours)}</div><div className="lbl">Hours</div></div>
      <div className="cd-cell"><div className="num">{pad(mins)}</div><div className="lbl">Min</div></div>
      <div className="cd-cell"><div className="num">{pad(secs)}</div><div className="lbl">Sec</div></div>
    </div>
  );
}

// ─── Signup ───
function Signup() {
  const [email, setEmail] = useState('');
  const [status, setStatus] = useState('idle'); // idle | loading | success | error
  const onSubmit = async (e) => {
    e.preventDefault();
    if (!email.includes('@')) return;
    setStatus('loading');

    try {
      const controller = new AbortController();
      const timeout = setTimeout(() => controller.abort(), 12000);
      const response = await fetch('/api/notify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email }),
        signal: controller.signal
      });
      clearTimeout(timeout);

      if (!response.ok) throw new Error('Signup failed');

      setStatus('success');
      setTimeout(() => { setEmail(''); setStatus('idle'); }, 5000);
    } catch (error) {
      setStatus('error');
    }
  };

  const placeholder = {
    idle: 'your@email.com',
    loading: 'Sending...',
    success: 'Thank you. You are on the list.',
    error: 'Something went sideways. Try again.'
  }[status];

  return (
    <form className={`signup ${status === 'success' ? 'success' : ''}`} onSubmit={onSubmit}>
      <input
        type="email"
        placeholder={placeholder}
        value={email}
        onChange={e => setEmail(e.target.value)}
        disabled={status === 'loading' || status === 'success'}
      />
      <button type="submit" disabled={status === 'loading'}>
        {status === 'loading' ? 'Sending...' : status === 'success' ? 'Thank you' : 'Notify Me'}
      </button>
    </form>
  );
}

// ─── Custom cursor + trail ───
function Cursor() {
  const cursorRef = useRef(null);
  const [trails, setTrails] = useState([]);
  const idRef = useRef(0);

  useEffect(() => {
    const onMove = (e) => {
      if (cursorRef.current) {
        cursorRef.current.style.left = e.clientX + 'px';
        cursorRef.current.style.top = e.clientY + 'px';
      }
    };
    const onClick = (e) => {
      // spawn a few bubble trails
      const newTrails = [];
      for (let i = 0; i < 6; i++) {
        const id = ++idRef.current;
        newTrails.push({
          id,
          x: e.clientX + (Math.random()-0.5)*20,
          y: e.clientY + (Math.random()-0.5)*10,
          size: 6 + Math.random()*14,
          dx: (Math.random()-0.5)*60,
        });
      }
      setTrails(prev => [...prev, ...newTrails]);
      setTimeout(() => {
        setTrails(prev => prev.filter(t => !newTrails.find(n => n.id === t.id)));
      }, 2300);
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('click', onClick);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('click', onClick);
    };
  }, []);

  return (
    <>
      <div className="cursor" ref={cursorRef} />
      {trails.map(t => (
        <div key={t.id} className="trail"
          style={{
            left: t.x, top: t.y,
            width: t.size, height: t.size,
            '--dx': `${t.dx}px`,
          }}
        />
      ))}
    </>
  );
}

// ─── Main App ───
function App() {
  const [t, setTweak] = useTweaks(window.TWEAK_DEFAULTS);

  return (
    <>
      <div className="water"/>
      <div className="surface"/>

      {t.showRays && <GodRays/>}
      <Caustics/>
      <Snow/>
      <Bubbles/>

      {t.showFish && (
        <div className="fish-layer">
          <School klass="a"/>
          <School klass="b"/>
          <School klass="c"/>
        </div>
      )}

      {t.showKelp && <KelpForest/>}
      <div className="floor"/>

      {/* Center stage */}
      <div className="stage">
        <div className="logo-wrap">
          <img src="assets/openocti.png" alt="Open Octi"/>
        </div>
        {t.showRipples && (
          <div className="ripples">
            <div className="ring"/>
            <div className="ring"/>
            <div className="ring"/>
          </div>
        )}
        <div className="badge" style={{marginTop: '8px'}}>
          <span className="dot"/> Surfacing soon · Closed Beta · 2026
        </div>
        <div className="tagline">{t.tagline}</div>
        <Countdown target={t.launchDate}/>
        <Signup/>
      </div>

      {/* Top + bottom UI */}
      <div className="top-bar">
        <div className="mark"><span className="hex"/> OPEN · OCTI</div>
        <div>SYS · 8 ARMS · OPEN SOURCE</div>
      </div>
      <div className="bottom-bar">
        <div>Depth · 4200m · 04°C</div>
        <div className="links">
          <a href="#docs">Docs</a>
          <a href="#github">GitHub</a>
          <a href="#discord">Discord</a>
          <a href="#manifesto">Manifesto</a>
        </div>
      </div>

      {/* Tank glass overlay */}
      <div className="scanlines"/>
      <div className="glass"/>
      <div className="corner tl"/><div className="corner tr"/>
      <div className="corner bl"/><div className="corner br"/>

      <Cursor/>

      <TweaksPanel>
        <TweakSection label="Scene"/>
          <TweakToggle label="God rays" value={t.showRays} onChange={v => setTweak('showRays', v)}/>
          <TweakToggle label="Kelp" value={t.showKelp} onChange={v => setTweak('showKelp', v)}/>
          <TweakToggle label="Schools of fish" value={t.showFish} onChange={v => setTweak('showFish', v)}/>
          <TweakToggle label="Ripple rings" value={t.showRipples} onChange={v => setTweak('showRipples', v)}/>
        <TweakSection label="Copy"/>
          <TweakText label="Tagline" value={t.tagline} onChange={v => setTweak('tagline', v)}/>
          <TweakText label="Launch (ISO)" value={t.launchDate} onChange={v => setTweak('launchDate', v)}/>
      </TweaksPanel>
    </>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<App/>);
