// Animations module - keyframes + reveal hooks

// 1) Inject keyframes once
(() => {
  if (document.getElementById('deevy-anims')) return;
  const style = document.createElement('style');
  style.id = 'deevy-anims';
  style.textContent = `
    /* Glimmer line traveling around the border of the DV card */
    .dv-glimmer {
      position: relative;
      isolation: isolate;
    }
    .dv-glimmer-svg {
      position: absolute;
      inset: -1px;
      width: calc(100% + 2px);
      height: calc(100% + 2px);
      pointer-events: none;
      z-index: 3;
      overflow: visible;
    }
    .dv-glimmer-track {
      fill: none;
      stroke: rgba(24, 95, 165, 0.0);
      stroke-width: 1.5;
    }
    .dv-glimmer-trace {
      fill: none;
      stroke: #85B7EB;
      stroke-width: 1.5;
      stroke-linecap: round;
      filter: drop-shadow(0 0 4px rgba(133, 183, 235, 0.9))
              drop-shadow(0 0 12px rgba(133, 183, 235, 0.5));
      animation: dv-trace 4.5s cubic-bezier(0.65, 0, 0.35, 1) infinite;
    }
    @keyframes dv-trace {
      0%   { stroke-dashoffset: var(--perim, 800); }
      100% { stroke-dashoffset: 0; }
    }

    /* Status panel transitions */
    @keyframes status-slide-in {
      0%   { opacity: 0; transform: translateY(8px); }
      100% { opacity: 1; transform: translateY(0); }
    }
    @keyframes status-pulse {
      0%, 100% { opacity: 0.4; }
      50%      { opacity: 1; }
    }
    @keyframes check-pop {
      0%   { transform: scale(0); }
      60%  { transform: scale(1.3); }
      100% { transform: scale(1); }
    }

    /* Subtle scroll-fade-in */
    .anim-rise {
      opacity: 0;
      transform: translateY(16px);
      transition: opacity 800ms cubic-bezier(0.2, 0.7, 0.2, 1),
                  transform 800ms cubic-bezier(0.2, 0.7, 0.2, 1);
    }
    .anim-rise.is-visible {
      opacity: 1;
      transform: translateY(0);
    }

    /* Bar fill animation */
    .bar-fill {
      transform-origin: left center;
      transform: scaleX(0);
      transition: transform 1400ms cubic-bezier(0.65, 0, 0.35, 1);
    }
    .bar-fill.is-visible {
      transform: scaleX(1);
    }

    /* Headline cursor blink */
    .headline-cursor {
      display: inline-block;
      width: 3px;
      height: 0.85em;
      background: #85B7EB;
      margin-left: 6px;
      vertical-align: -0.05em;
      animation: cursor-blink 1.1s step-end infinite;
    }
    @keyframes cursor-blink {
      0%, 60% { opacity: 1; }
      61%, 100% { opacity: 0; }
    }

    /* Map cell shimmer on landing */
    .map-cell {
      animation: cell-pop 600ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
    }
    @keyframes cell-pop {
      from { opacity: 0; transform: scale(0.6); transform-box: fill-box; transform-origin: center; }
      to { opacity: 1; transform: scale(1); }
    }

    /* Methodology logos drift */
    .methodology-strip:hover .meth-logo {
      transition: transform 400ms ease, opacity 400ms ease;
    }

    /* Form field focus glow */
    .form-input:focus {
      animation: input-glow 700ms ease-out;
    }
    @keyframes input-glow {
      0% { box-shadow: 0 0 0 0 rgba(24, 95, 165, 0.4); }
      100% { box-shadow: 0 0 0 8px rgba(24, 95, 165, 0); }
    }

    @media (prefers-reduced-motion: reduce) {
      .dv-glimmer::before,
      .anim-rise,
      .bar-fill,
      .headline-cursor,
      .map-cell { animation: none !important; transition: none !important; opacity: 1 !important; transform: none !important; }
    }
  `;
  document.head.appendChild(style);
})();

// 2) Reveal-on-scroll hook
function useReveal(opts = {}) {
  const ref = React.useRef(null);
  const [visible, setVisible] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current) return;
    const el = ref.current;
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setVisible(true);
        observer.disconnect();
      }
    }, { threshold: opts.threshold ?? 0.25, rootMargin: opts.rootMargin ?? '0px' });
    observer.observe(el);
    return () => observer.disconnect();
  }, []);
  return [ref, visible];
}

// 3) Animated counter component
function CountUp({ to, prefix = '', suffix = '', duration = 1600, decimals = 0 }) {
  const [ref, visible] = useReveal({ threshold: 0.5 });
  const [val, setVal] = React.useState(0);

  React.useEffect(() => {
    if (!visible) return;
    const target = parseFloat(String(to).replace(/[^\d.]/g, ''));
    const start = performance.now();
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setVal(target * eased);
      if (t < 1) raf = requestAnimationFrame(tick);
      else setVal(target);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [visible, to, duration]);

  const formatted = visible
    ? val.toLocaleString('en-US', {
        minimumFractionDigits: decimals,
        maximumFractionDigits: decimals,
      })
    : '0';

  return <span ref={ref}>{prefix}{formatted}{suffix}</span>;
}

// Border-tracing glimmer for DV card
function DVGlimmerSVG() {
  const ref = React.useRef(null);
  const [dims, setDims] = React.useState({ w: 0, h: 0 });

  React.useEffect(() => {
    if (!ref.current) return;
    const measure = () => {
      const parent = ref.current?.parentElement;
      if (!parent) return;
      const r = parent.getBoundingClientRect();
      setDims({ w: r.width, h: r.height });
    };
    measure();
    const ro = new ResizeObserver(measure);
    if (ref.current?.parentElement) ro.observe(ref.current.parentElement);
    return () => ro.disconnect();
  }, []);

  const { w, h } = dims;
  if (!w || !h) return <svg ref={ref} className="dv-glimmer-svg" />;

  // Path traces full perimeter starting top-left, going clockwise
  const inset = 0.75;
  const x0 = inset, y0 = inset;
  const x1 = w - inset, y1 = h - inset;
  const d = `M ${x0} ${y0} L ${x1} ${y0} L ${x1} ${y1} L ${x0} ${y1} Z`;
  const perim = 2 * (w - inset * 2) + 2 * (h - inset * 2);
  // Trace length is ~25% of perimeter - a comet streak, not a full underline
  const trace = perim * 0.22;
  const dashArray = `${trace} ${perim - trace}`;

  return (
    <svg
      ref={ref}
      className="dv-glimmer-svg"
      viewBox={`0 0 ${w} ${h}`}
      preserveAspectRatio="none"
      style={{ '--perim': perim }}
    >
      <path className="dv-glimmer-track" d={d} />
      <path
        className="dv-glimmer-trace"
        d={d}
        strokeDasharray={dashArray}
        strokeDashoffset={perim}
      />
    </svg>
  );
}

Object.assign(window, { useReveal, CountUp, DVGlimmerSVG });
