// Aurora — WebGL fragment shader that renders a flowing, video-like blue/violet
// gradient loop. Pure GLSL, fully original. Replaces the static CSS blobs.
//
// Falls back gracefully to a static CSS gradient if WebGL is unavailable.

const { useEffect: useEffectA, useRef: useRefA } = React;

const PALETTES = {
  // [colA, colB, colC, colD] — vec3 RGB 0..1.  Mix is in shader.
  blue: [
    [0.04, 0.06, 0.12],   // deep ink
    [0.13, 0.20, 0.62],   // royal blue
    [0.42, 0.55, 1.00],   // light blue
    [0.48, 0.42, 0.95],   // violet accent
  ],
  periwinkle: [
    [0.04, 0.05, 0.10],
    [0.30, 0.24, 0.78],
    [0.65, 0.55, 1.00],
    [0.78, 0.69, 1.00],
  ],
  cool: [
    [0.03, 0.04, 0.10],
    [0.18, 0.23, 0.53],
    [0.48, 0.42, 0.95],
    [0.56, 0.66, 1.00],
  ],
  vinho: [
    [0.04, 0.02, 0.04],
    [0.42, 0.10, 0.18],
    [0.71, 0.27, 0.40],
    [0.13, 0.20, 0.62],
  ],
};

const VERT = `
attribute vec2 a_pos;
varying vec2 v_uv;
void main(){
  v_uv = a_pos * 0.5 + 0.5;
  gl_Position = vec4(a_pos, 0.0, 1.0);
}`;

const FRAG = `
precision highp float;
varying vec2 v_uv;
uniform float u_time;
uniform vec2  u_res;
uniform vec3  u_c0;
uniform vec3  u_c1;
uniform vec3  u_c2;
uniform vec3  u_c3;

// Hash + value noise — small, fast, no textures.
float hash(vec2 p){ return fract(sin(dot(p, vec2(127.1,311.7))) * 43758.5453); }
float vnoise(vec2 p){
  vec2 i = floor(p), f = fract(p);
  float a = hash(i);
  float b = hash(i + vec2(1.0,0.0));
  float c = hash(i + vec2(0.0,1.0));
  float d = hash(i + vec2(1.0,1.0));
  vec2 u = f*f*(3.0-2.0*f);
  return mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
}
float fbm(vec2 p){
  float v = 0.0;
  float a = 0.5;
  mat2 r = mat2(0.8,-0.6,0.6,0.8);
  for(int i=0;i<5;i++){
    v += a * vnoise(p);
    p = r * p * 2.05;
    a *= 0.5;
  }
  return v;
}

void main(){
  // Aspect-correct coords centered on screen.
  vec2 uv = (gl_FragCoord.xy - 0.5 * u_res) / u_res.y;

  float t = u_time * 0.06;

  // Two slow-moving noise fields — one drives the warp, one the color mix.
  vec2 q = vec2(
    fbm(uv * 1.6 + vec2(t,        -t*0.7)),
    fbm(uv * 1.6 + vec2(-t*0.9,    t*0.5) + 7.3)
  );
  vec2 r = vec2(
    fbm(uv * 2.2 + 4.0*q + vec2(t*0.5,  0.0)),
    fbm(uv * 2.2 + 4.0*q + vec2(0.0,    t*0.6) + 2.1)
  );
  float f = fbm(uv * 1.8 + 3.0*r + t*0.4);

  // Build the gradient from 4 stops by chaining mixes on f and the second noise.
  vec3 col = u_c0;
  col = mix(col, u_c1, smoothstep(0.05, 0.55, f));
  col = mix(col, u_c2, smoothstep(0.40, 0.85, f + 0.10 * r.x));
  col = mix(col, u_c3, smoothstep(0.70, 1.05, f + 0.18 * r.y));

  // Soft vignette so edges fall into the page bg.
  float vig = smoothstep(1.05, 0.45, length(uv * vec2(0.9, 1.0)));
  col *= mix(0.55, 1.05, vig);

  // Subtle grain — keeps it from looking like a flat CSS gradient.
  float g = hash(gl_FragCoord.xy + u_time);
  col += (g - 0.5) * 0.025;

  gl_FragColor = vec4(col, 1.0);
}`;

function compileShader(gl, type, src){
  const s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)){
    console.warn('shader error', gl.getShaderInfoLog(s));
    gl.deleteShader(s);
    return null;
  }
  return s;
}

function Aurora({ intensity = 1, variant = 'blue' }) {
  const canvasRef = useRefA(null);
  const stateRef  = useRefA({ raf: 0, t0: 0 });

  // Re-init on variant change so palette switches cleanly.
  useEffectA(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const gl = canvas.getContext('webgl', { antialias: false, premultipliedAlpha: false, alpha: false });
    if (!gl){
      // No WebGL — leave the canvas hidden, the CSS fallback layer shows through.
      canvas.style.display = 'none';
      return;
    }

    const vs = compileShader(gl, gl.VERTEX_SHADER, VERT);
    const fs = compileShader(gl, gl.FRAGMENT_SHADER, FRAG);
    const prog = gl.createProgram();
    gl.attachShader(prog, vs); gl.attachShader(prog, fs); gl.linkProgram(prog);
    if (!gl.getProgramParameter(prog, gl.LINK_STATUS)){
      console.warn('link error', gl.getProgramInfoLog(prog));
      canvas.style.display = 'none';
      return;
    }
    gl.useProgram(prog);

    const buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
      -1,-1,  1,-1,  -1, 1,
      -1, 1,  1,-1,   1, 1,
    ]), gl.STATIC_DRAW);
    const aPos = gl.getAttribLocation(prog, 'a_pos');
    gl.enableVertexAttribArray(aPos);
    gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);

    const uTime = gl.getUniformLocation(prog, 'u_time');
    const uRes  = gl.getUniformLocation(prog, 'u_res');
    const uC0   = gl.getUniformLocation(prog, 'u_c0');
    const uC1   = gl.getUniformLocation(prog, 'u_c1');
    const uC2   = gl.getUniformLocation(prog, 'u_c2');
    const uC3   = gl.getUniformLocation(prog, 'u_c3');

    const pal = PALETTES[variant] || PALETTES.blue;
    gl.uniform3fv(uC0, pal[0]);
    gl.uniform3fv(uC1, pal[1]);
    gl.uniform3fv(uC2, pal[2]);
    gl.uniform3fv(uC3, pal[3]);

    const resize = () => {
      const dpr = Math.min(window.devicePixelRatio || 1, 1.5);
      const w = Math.floor(canvas.clientWidth  * dpr);
      const h = Math.floor(canvas.clientHeight * dpr);
      if (canvas.width !== w || canvas.height !== h){
        canvas.width = w; canvas.height = h;
        gl.viewport(0, 0, w, h);
        gl.uniform2f(uRes, w, h);
      }
    };
    resize();
    window.addEventListener('resize', resize);

    stateRef.current.t0 = performance.now();
    const draw = () => {
      resize();
      const t = (performance.now() - stateRef.current.t0) / 1000;
      gl.uniform1f(uTime, t);
      gl.drawArrays(gl.TRIANGLES, 0, 6);
      stateRef.current.raf = requestAnimationFrame(draw);
    };
    draw();

    return () => {
      cancelAnimationFrame(stateRef.current.raf);
      window.removeEventListener('resize', resize);
      gl.deleteBuffer(buf);
      gl.deleteProgram(prog);
      gl.deleteShader(vs);
      gl.deleteShader(fs);
    };
  }, [variant]);

  return (
    <div className="aurora-root" style={{opacity: intensity}}>
      {/* CSS gradient fallback — only visible if WebGL is off. */}
      <div style={{
        position:'absolute', inset:0,
        background: 'radial-gradient(ellipse 80% 60% at 40% 30%, #2a3aa8 0%, #14186a 35%, #050610 75%)',
      }}/>
      <canvas
        ref={canvasRef}
        style={{position:'absolute', inset:0, width:'100%', height:'100%', display:'block'}}
      />
      {/* fine film-grain overlay, kept as before */}
      <div className="aurora-grain"/>
    </div>
  );
}

window.Aurora = Aurora;
