// ───────────────────────────────────────────────
// Shader background — fixed canvas behind everything
// Three.js fragment shader (aurora) tinted to teal accent
// ───────────────────────────────────────────────

const SHADER_VERT = `void main(){gl_Position=vec4(position,1.0);}`;

const SHADER_FRAG = `precision mediump float;
uniform float iTime;
uniform vec2  iResolution;

float rand(vec2 n){return fract(sin(dot(n,vec2(12.9898,4.1414)))*43758.5453);}
float noise(vec2 p){
  vec2 ip=floor(p); vec2 u=fract(p); u=u*u*(3.0-2.0*u);
  return mix(mix(rand(ip),rand(ip+vec2(1.,0.)),u.x),mix(rand(ip+vec2(0.,1.)),rand(ip+vec2(1.,1.)),u.x),u.y);
}
float fbm(vec2 x){
  float v=0.0; float a=0.3;
  mat2 rot=mat2(cos(0.5),sin(0.5),-sin(0.5),cos(0.5));
  for(int i=0;i<3;i++){ v+=a*noise(x); x=rot*x*2.0+vec2(100.0); a*=0.4; }
  return v;
}

void main(){
  vec2 p=((gl_FragCoord.xy)-iResolution.xy*0.5)/iResolution.y*mat2(6.0,-4.0,4.0,6.0);
  vec2 v;
  vec4 o=vec4(0.0);
  float f=2.0+fbm(p+vec2(iTime*5.0,0.0))*0.5;
  for(float i=0.0;i<22.0;i++){
    v=p+cos(i*i+(iTime+p.x*0.08)*0.025+i*vec2(13.0,11.0))*3.5;
    float tn=fbm(v+vec2(iTime*0.5,i))*0.25*(1.0-(i/22.0));
    vec4 c=vec4(
      0.05+0.08*sin(i*0.2+iTime*0.4),
      0.55+0.35*cos(i*0.3+iTime*0.5),
      0.55+0.30*sin(i*0.4+iTime*0.3),
      1.0);
    vec4 cc=c*exp(sin(i*i+iTime*0.8))/length(max(v,vec2(v.x*f*0.015,v.y*1.5)));
    float t=smoothstep(0.0,1.0,i/22.0)*0.6;
    o+=cc*(1.0+tn*0.8)*t;
  }
  o = tanh(pow(o / 60.0, vec4(1.4)));
  vec3 c = o.rgb * 2.5;
  // alpha = brightness so dark areas stay transparent
  float a = clamp(max(max(c.r, c.g), c.b), 0.0, 1.0);
  gl_FragColor = vec4(c, a);
}`;

function ShaderBackground() {
  const ref = React.useRef(null);

  React.useEffect(() => {
    if (!ref.current) return;
    const THREE = window.THREE;
    if (!THREE) {
      console.warn('[shader-bg] THREE not loaded');
      return;
    }

    const container = ref.current;
    let renderer, mesh, geometry, material, raf = 0;
    let running = true;

    try {
      const w = Math.max(1, window.innerWidth);
      const h = Math.max(1, window.innerHeight);

      renderer = new THREE.WebGLRenderer({ antialias: false, alpha: true, powerPreference: 'low-power' });
      renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 1.25));
      renderer.setSize(w, h, false);
      const dom = renderer.domElement;
      dom.style.display = 'block';
      dom.style.width = '100%';
      dom.style.height = '100%';
      container.appendChild(dom);

      const scene = new THREE.Scene();
      const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
      const uniforms = {
        iTime:       { value: 0 },
        iResolution: { value: new THREE.Vector2(w, h) }
      };
      material = new THREE.ShaderMaterial({
        uniforms,
        vertexShader:   SHADER_VERT,
        fragmentShader: SHADER_FRAG,
        transparent:    true
      });
      geometry = new THREE.PlaneGeometry(2, 2);
      mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);

      let last = performance.now();
      const tick = (now) => {
        if (!running) return;
        const dt = Math.min(0.05, (now - last) / 1000);
        last = now;
        uniforms.iTime.value += dt;
        try {
          renderer.render(scene, camera);
        } catch (e) {
          console.warn('[shader-bg] render error', e);
          running = false;
          return;
        }
        raf = requestAnimationFrame(tick);
      };
      raf = requestAnimationFrame(tick);

      // pause when tab hidden
      const onVis = () => {
        if (document.hidden) {
          running = false;
          cancelAnimationFrame(raf);
        } else if (!running) {
          running = true;
          last = performance.now();
          raf = requestAnimationFrame(tick);
        }
      };
      document.addEventListener('visibilitychange', onVis);

      // throttled resize
      let resizeT = 0;
      const onResize = () => {
        clearTimeout(resizeT);
        resizeT = setTimeout(() => {
          const nw = Math.max(1, window.innerWidth);
          const nh = Math.max(1, window.innerHeight);
          renderer.setSize(nw, nh, false);
          uniforms.iResolution.value.set(nw, nh);
        }, 150);
      };
      window.addEventListener('resize', onResize);

      return () => {
        running = false;
        cancelAnimationFrame(raf);
        clearTimeout(resizeT);
        document.removeEventListener('visibilitychange', onVis);
        window.removeEventListener('resize', onResize);
        if (dom.parentNode) dom.parentNode.removeChild(dom);
        geometry && geometry.dispose();
        material && material.dispose();
        renderer && renderer.dispose();
      };
    } catch (e) {
      console.warn('[shader-bg] init failed', e);
      running = false;
      if (renderer) { try { renderer.dispose(); } catch(_){} }
    }
  }, []);

  return <div ref={ref} className="pp-shader-bg" aria-hidden="true" />;
}

window.ShaderBackground = ShaderBackground;
