// ui_kits/site/ShaderField.jsx — animated webgl field driven by p3 brand colors.
// Falls back to a CSS gradient if WebGL is unavailable.
const ShaderField = ({ mode = 'lava', scrollVel = 0 }) => {
  const canvasRef = React.useRef(null);
  const stateRef  = React.useRef({ vel: 0, t: 0 });

  React.useEffect(() => { stateRef.current.vel = scrollVel; }, [scrollVel]);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    const gl = canvas.getContext('webgl', { antialias: true, premultipliedAlpha: false });
    if (!gl) { canvas.classList.add('fallback'); return; }

    const vs = `attribute vec2 p; void main(){ gl_Position = vec4(p, 0.0, 1.0); }`;
    const fs = `
      precision highp float;
      uniform vec2 u_res;
      uniform float u_time;
      uniform float u_vel;
      uniform vec3 u_c1; uniform vec3 u_c2; uniform vec3 u_c3;

      // cheap value noise
      float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123); }
      float noise(vec2 p) {
        vec2 i = floor(p), f = fract(p);
        float a = hash(i), b = hash(i + vec2(1.0, 0.0));
        float c = hash(i + vec2(0.0, 1.0)), 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, a = 0.5;
        for (int i = 0; i < 4; i++) { v += a * noise(p); p *= 2.03; a *= 0.5; }
        return v;
      }

      void main(){
        vec2 uv = (gl_FragCoord.xy - 0.5 * u_res) / u_res.y;
        float t = u_time * 0.07;
        vec2 q = vec2(fbm(uv * 1.3 + t), fbm(uv * 1.3 - t + 7.0));
        vec2 r = vec2(fbm(uv * 2.0 + q + vec2(1.7, 9.2) + u_vel * 0.3),
                      fbm(uv * 2.0 + q + vec2(8.3, 2.8) - u_vel * 0.3));
        float f = fbm(uv * 1.7 + r);

        vec3 col = mix(u_c1, u_c2, smoothstep(0.0, 1.0, f));
        col = mix(col, u_c3, smoothstep(0.5, 0.95, length(r)));
        // subtle vignette
        float d = length(uv);
        col *= 1.0 - smoothstep(0.4, 1.2, d) * 0.4;
        gl_FragColor = vec4(col, 1.0);
      }
    `;
    const compile = (type, src) => { const s = gl.createShader(type); gl.shaderSource(s, src); gl.compileShader(s); return s; };
    const prog = gl.createProgram();
    gl.attachShader(prog, compile(gl.VERTEX_SHADER, vs));
    gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, fs));
    gl.linkProgram(prog); 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]), gl.STATIC_DRAW);
    const loc = gl.getAttribLocation(prog, 'p');
    gl.enableVertexAttribArray(loc); gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);

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

    const palettes = {
      lava:   [[0.96,0.93,0.86], [0.95,0.46,0.18], [0.30,0.14,0.08]],
      abyss:  [[0.02,0.06,0.10], [0.05,0.32,0.42], [0.30,0.85,0.95]],
      plasma: [[0.10,0.04,0.18], [0.85,0.18,0.78], [0.70,0.95,0.20]],
    };

    const resize = () => {
      const dpr = Math.min(devicePixelRatio || 1, 2);
      canvas.width  = canvas.clientWidth * dpr;
      canvas.height = canvas.clientHeight * dpr;
      gl.viewport(0, 0, canvas.width, canvas.height);
      gl.uniform2f(uRes, canvas.width, canvas.height);
    };
    resize();
    addEventListener('resize', resize);

    const start = performance.now();
    let raf;
    const tick = () => {
      const p = palettes[mode] || palettes.lava;
      gl.uniform3f(uC1, p[0][0], p[0][1], p[0][2]);
      gl.uniform3f(uC2, p[1][0], p[1][1], p[1][2]);
      gl.uniform3f(uC3, p[2][0], p[2][1], p[2][2]);
      gl.uniform1f(uTime, (performance.now() - start) / 1000);
      gl.uniform1f(uVel,  stateRef.current.vel);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
      raf = requestAnimationFrame(tick);
    };
    tick();
    return () => { cancelAnimationFrame(raf); removeEventListener('resize', resize); };
  }, [mode]);

  return (
    <>
      <canvas ref={canvasRef} className="koa-shader" aria-hidden="true" />
      <style>{`
        .koa-shader {
          position: absolute; inset: 0; width: 100%; height: 100%;
          display: block; z-index: 0;
        }
        .koa-shader.fallback {
          background: radial-gradient(60% 40% at 30% 40%, var(--accent) 0%, transparent 70%),
                      radial-gradient(80% 60% at 80% 80%, var(--accent-2) 0%, transparent 70%),
                      var(--bg);
        }
      `}</style>
    </>
  );
};

window.ShaderField = ShaderField;
