"use client";

import { useEffect, useRef } from "react";
import { Renderer, Program, Mesh, Triangle, Vec2 } from "ogl";

/**
 * Custom WebGL signature: a flowing "revenue field" — animated contour
 * lines that rise and surge like a growth chart / topographic gain map,
 * rendered as ink hairlines on paper with an acid-green crest threading
 * through. Reacts gently to the pointer.
 *
 * Constraints honored:
 *  - "use client", all GL created in useEffect, full cleanup
 *  - no window/document access during SSR/render
 *  - pauses RAF when the tab is hidden or canvas is offscreen
 *  - respects prefers-reduced-motion (renders one static frame, no loop)
 *  - decorative only (aria-hidden); never the sole carrier of meaning
 */
export default function RevenueField() {
  const wrap = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const host = wrap.current;
    if (!host) return;

    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    const renderer = new Renderer({
      alpha: true,
      antialias: true,
      dpr: Math.min(window.devicePixelRatio || 1, 2),
    });
    const gl = renderer.gl;
    gl.clearColor(0, 0, 0, 0);
    host.appendChild(gl.canvas);
    gl.canvas.style.width = "100%";
    gl.canvas.style.height = "100%";
    gl.canvas.style.display = "block";

    const geometry = new Triangle(gl);

    const program = new Program(gl, {
      uniforms: {
        uTime: { value: 0 },
        uRes: { value: new Vec2(1, 1) },
        uMouse: { value: new Vec2(0.5, 0.5) },
        // ink + emerald crest (the hero sits on light paper, so the crest
        // uses the deeper "gain" green to stay perceptible, not invisible lime)
        uInk: { value: [0.078, 0.075, 0.059] },
        uAcid: { value: [0.039, 0.431, 0.278] },
      },
      vertex: /* glsl */ `
        attribute vec2 uv;
        attribute vec2 position;
        varying vec2 vUv;
        void main() {
          vUv = uv;
          gl_Position = vec4(position, 0.0, 1.0);
        }
      `,
      fragment: /* glsl */ `
        precision highp float;
        varying vec2 vUv;
        uniform float uTime;
        uniform vec2 uRes;
        uniform vec2 uMouse;
        uniform vec3 uInk;
        uniform vec3 uAcid;

        // cheap value noise
        float hash(vec2 p){ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
        float noise(vec2 p){
          vec2 i = floor(p); vec2 f = fract(p);
          vec2 u = f*f*(3.0-2.0*f);
          return mix(mix(hash(i), hash(i+vec2(1,0)), u.x),
                     mix(hash(i+vec2(0,1)), hash(i+vec2(1,1)), u.x), u.y);
        }
        float fbm(vec2 p){
          float v = 0.0; float a = 0.5;
          for(int i=0;i<5;i++){ v += a*noise(p); p *= 2.0; a *= 0.5; }
          return v;
        }

        void main() {
          vec2 uv = vUv;
          float aspect = uRes.x / max(uRes.y, 1.0);
          vec2 p = uv;
          p.x *= aspect;

          // mouse influence — a gentle lift around the pointer
          vec2 m = uMouse; m.x *= aspect;
          float md = distance(p, m);
          float lift = smoothstep(0.6, 0.0, md) * 0.18;

          float t = uTime * 0.06;

          // a rising surface: base height climbs left->right (growth)
          float climb = uv.x * 0.55;
          float field = fbm(p * 2.4 + vec2(t, t * 0.4)) + climb + lift;
          field += fbm(p * 5.0 - vec2(t * 0.7, 0.0)) * 0.25;

          // contour lines from the height field
          float lines = abs(fract(field * 9.0) - 0.5);
          float w = fwidth(field * 9.0) * 1.2;
          float contour = 1.0 - smoothstep(0.0, w, lines);

          // crest highlight: the topmost band glows acid (the "gain")
          float crest = smoothstep(0.62, 0.86, field) * smoothstep(0.96, 0.7, field);

          vec3 col = mix(uInk, uAcid, crest * 0.9);
          float alpha = contour * (0.20 + crest * 0.85);

          // soft right/top fade so type stays readable, lines vignette off edges
          alpha *= smoothstep(0.0, 0.18, uv.x);
          alpha *= smoothstep(0.0, 0.14, uv.y) * smoothstep(1.0, 0.82, uv.y);

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

    const mesh = new Mesh(gl, { geometry, program });

    const resize = () => {
      const w = host.clientWidth;
      const h = host.clientHeight;
      renderer.setSize(w, h);
      program.uniforms.uRes.value.set(w, h);
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(host);

    // pointer (eased)
    const target = new Vec2(0.5, 0.5);
    const onPointer = (e: PointerEvent) => {
      const r = host.getBoundingClientRect();
      target.set((e.clientX - r.left) / r.width, 1 - (e.clientY - r.top) / r.height);
    };
    window.addEventListener("pointermove", onPointer);

    let raf = 0;
    let running = true;
    const start = performance.now();

    const frame = (now: number) => {
      if (!running) return;
      const u = program.uniforms;
      u.uTime.value = (now - start) / 1000;
      (u.uMouse.value as Vec2).x += (target.x - (u.uMouse.value as Vec2).x) * 0.05;
      (u.uMouse.value as Vec2).y += (target.y - (u.uMouse.value as Vec2).y) * 0.05;
      renderer.render({ scene: mesh });
      raf = requestAnimationFrame(frame);
    };

    // visibility: pause GL when tab hidden or canvas scrolled offscreen
    const onVisibility = () => {
      if (document.hidden) {
        running = false;
        cancelAnimationFrame(raf);
      } else if (!reduce) {
        running = true;
        raf = requestAnimationFrame(frame);
      }
    };
    document.addEventListener("visibilitychange", onVisibility);

    const io = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting && !document.hidden && !reduce) {
          if (!running) {
            running = true;
            raf = requestAnimationFrame(frame);
          }
        } else {
          running = false;
          cancelAnimationFrame(raf);
        }
      },
      { threshold: 0 }
    );
    io.observe(host);

    if (reduce) {
      // single static frame, no animation loop
      program.uniforms.uTime.value = 8;
      renderer.render({ scene: mesh });
    } else {
      raf = requestAnimationFrame(frame);
    }

    return () => {
      running = false;
      cancelAnimationFrame(raf);
      window.removeEventListener("pointermove", onPointer);
      document.removeEventListener("visibilitychange", onVisibility);
      io.disconnect();
      ro.disconnect();
      const ext = gl.getExtension("WEBGL_lose_context");
      if (ext) ext.loseContext();
      if (gl.canvas.parentNode) gl.canvas.parentNode.removeChild(gl.canvas);
    };
  }, []);

  return <div ref={wrap} className="revfield" aria-hidden="true" />;
}
