/* IR Turismo — Rota de voo (flight path) que desce a home no scroll.
   - rastro pontilhado em curva S, cores intercaladas roxo <-> laranja/amarelo
   - aviãozinho top-down em gradiente, nariz seguindo a direção do voo
   - pousa no botão marcado com [data-fp-land]
   Exporta window.FlightPath. Não re-renderiza a cada frame de scroll:
   geometria fica em state; posição do avião + recorte do rastro são
   atualizados direto no DOM via refs dentro de um rAF. */

(function () {
  const PURPLE = '#6E1B96';

  /* injeta CSS uma única vez */
  const CSS = `
  .fp-layer { position:absolute; top:0; left:0; z-index:24; pointer-events:none; overflow:visible; }
  .fp-svg { position:absolute; top:0; left:0; display:block; overflow:visible; }
  .fp-plane { position:absolute; top:0; left:0; offset-anchor:50% 50%; offset-rotate:auto;
              will-change:offset-distance; filter:drop-shadow(0 5px 9px rgba(31,29,38,.20)); }
  .fp-plane__inner { display:block; transform-origin:50% 50%; }
  .fp-plane__inner svg { display:block; }
  @keyframes fp-bob { 0%,100% { transform:translateY(-2px) rotate(-3.5deg) scale(1); }
                      50% { transform:translateY(2px) rotate(3.5deg) scale(1.04); } }
  .fp-plane--bob .fp-plane__inner { animation:fp-bob 3.4s ease-in-out infinite; }
  @media (prefers-reduced-motion: reduce) { .fp-plane--bob .fp-plane__inner { animation:none; } }
  `;
  let cssInjected = false;
  function injectCss() {
    if (cssInjected || typeof document === 'undefined') return;
    const el = document.createElement('style');
    el.setAttribute('data-ir', 'flightpath');
    el.textContent = CSS;
    document.head.appendChild(el);
    cssInjected = true;
  }

  const clamp = (v, a, b) => Math.max(a, Math.min(b, v));

  /* avião top-down apontando para a DIREITA (+x); offset-rotate:auto vira o nariz pro rumo do voo */
  function Airliner({ size }) {
    const gid = 'fp-plane-grad';
    return (
      <svg viewBox="0 0 56 56" width={size} height={size} xmlns="http://www.w3.org/2000/svg">
        <defs>
          <linearGradient id={gid} x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stopColor={PURPLE} />
            <stop offset="0.55" stopColor="#C0398B" />
            <stop offset="1" stopColor="#F2911E" />
          </linearGradient>
        </defs>
        <path
          d="M53 28 L33 24 L27 5 L23 5 L29 25 L13 25 L8 15 L5 15 L10 28 L5 41 L8 41 L13 31 L29 31 L23 51 L27 51 L33 32 Z"
          fill={`url(#${gid})`}
          stroke="rgba(255,255,255,0.85)"
          strokeWidth="1.1"
          strokeLinejoin="round"
        />
      </svg>
    );
  }

  /* monta a curva S oscilando em torno de gx, do topo até o ponto de pouso (ex,ey) */
  function buildRoute(startY, endY, gx, amp, ex) {
    if (endY <= startY + 40) return `M ${gx} ${startY} L ${ex} ${endY}`;
    const span = endY - startY;
    const tail = Math.min(260, span * 0.32);   // trecho final reservado para "descer" até o botão
    const waveEnd = endY - tail;
    const wspan = waveEnd - startY;
    const segs = Math.max(2, Math.round(wspan / 300));
    const dy = wspan / segs;
    let d = `M ${gx.toFixed(1)} ${startY.toFixed(1)}`;
    let cur = startY;
    for (let i = 0; i < segs; i++) {
      const dir = i % 2 === 0 ? -1 : 1;          // começa curvando pra dentro (esquerda)
      const y1 = cur + dy;
      const cx = gx + dir * amp;
      d += ` C ${cx.toFixed(1)} ${(cur + dy * 0.35).toFixed(1)}, ${cx.toFixed(1)} ${(cur + dy * 0.65).toFixed(1)}, ${gx.toFixed(1)} ${y1.toFixed(1)}`;
      cur = y1;
    }
    // descida suave até o botão
    const m1y = cur + (endY - cur) * 0.45;
    const m2y = endY - (endY - cur) * 0.35;
    d += ` C ${gx.toFixed(1)} ${m1y.toFixed(1)}, ${ex.toFixed(1)} ${m2y.toFixed(1)}, ${ex.toFixed(1)} ${endY.toFixed(1)}`;
    return d;
  }

  function FlightPath(props) {
    const cfg = props.cfg;                 // { amp, planeSize, sw, dash, gap, bob, aheadOpacity }
    const accent = props.accent || '#F2911E';
    const routeAhead = props.routeAhead !== false;
    const land = props.land !== false;

    const [geo, setGeo] = React.useState(null);
    const planeRef = React.useRef(null);
    const clipRef = React.useRef(null);
    const pathRef = React.useRef(null);
    const stateRef = React.useRef({ startY: 0, endY: 0 });

    React.useEffect(injectCss, []);

    /* recalcula a geometria (rota, tamanho, ponto de pouso) */
    const measure = React.useCallback(() => {
      const docEl = document.documentElement;
      const W = docEl.clientWidth;
      const H = docEl.scrollHeight;
      const vh = window.innerWidth ? window.innerHeight : 800;
      const narrow = W < 900;

      // gutter: na margem direita, fora do container de 1240px quando há espaço
      const contentRight = Math.min(W - 18, (W + 1240) / 2);
      let gx = narrow ? W - 26 : (contentRight + W) / 2;
      const amp = narrow ? Math.min(cfg.amp, 26) : cfg.amp;
      gx = clamp(gx, amp + 14, W - amp - 14);

      const startY = Math.min(vh * 0.5, 340);

      // ponto de pouso
      let ex = W * 0.5, ey = H - 320;
      const target = land ? document.querySelector('[data-fp-land]') : null;
      if (target) {
        const r = target.getBoundingClientRect();
        ex = r.left + window.scrollX + r.width / 2;
        ey = r.top + window.scrollY + r.height / 2 - 4;
      }
      ex = clamp(ex, 30, W - 30);
      ey = clamp(ey, startY + 200, H - 40);

      const route = buildRoute(startY, ey, gx, amp, ex);
      stateRef.current = { startY, endY: ey };
      setGeo({ W, H, route, planeSize: cfg.planeSize });
    }, [cfg.amp, cfg.planeSize, land]);

    React.useLayoutEffect(() => {
      measure();
      const onResize = () => measure();
      window.addEventListener('resize', onResize);
      // recaptura depois que imagens/fontes mudam a altura
      const t1 = setTimeout(measure, 400);
      const t2 = setTimeout(measure, 1400);
      let ro;
      if ('ResizeObserver' in window) {
        ro = new ResizeObserver(() => measure());
        ro.observe(document.body);
      }
      return () => {
        window.removeEventListener('resize', onResize);
        clearTimeout(t1); clearTimeout(t2);
        if (ro) ro.disconnect();
      };
    }, [measure]);

    /* posição no scroll — atualizada direto no DOM, sem re-render.
       O avião fica preso a ~48% da altura da tela (acompanha o scroll, não corre),
       e o recorte do rastro termina exatamente no ponto onde o avião está
       (medido na própria curva via getPointAtLength) — sem trecho sem cor atrás dele. */
    React.useEffect(() => {
      if (!geo) return;
      const pathEl = pathRef.current;
      const len = pathEl ? pathEl.getTotalLength() : 0;
      // distância (no comprimento da curva) cujo ponto tem y == targetY (curva é monotônica em y)
      const distAtY = (targetY) => {
        let lo = 0, hi = len;
        for (let i = 0; i < 20; i++) {
          const mid = (lo + hi) / 2;
          if (pathEl.getPointAtLength(mid).y < targetY) lo = mid; else hi = mid;
        }
        return (lo + hi) / 2;
      };
      let raf = 0;
      const apply = () => {
        raf = 0;
        const { startY, endY } = stateRef.current;
        const vh = window.innerHeight;
        let targetY = clamp(window.scrollY + vh * 0.48, startY, endY);
        let distPct, planeY;
        if (len > 0) {
          const d = distAtY(targetY);
          planeY = pathEl.getPointAtLength(d).y;   // y real do avião na curva
          distPct = (d / len) * 100;
        } else {
          const p = (targetY - startY) / Math.max(1, endY - startY);
          distPct = p * 100; planeY = targetY;
        }
        if (planeRef.current) planeRef.current.style.offsetDistance = distPct.toFixed(2) + '%';
        if (clipRef.current) clipRef.current.setAttribute('height', Math.max(0, planeY).toFixed(1));
      };
      const onScroll = () => { if (!raf) raf = requestAnimationFrame(apply); };
      apply();
      window.addEventListener('scroll', onScroll, { passive: true });
      return () => { window.removeEventListener('scroll', onScroll); if (raf) cancelAnimationFrame(raf); };
    }, [geo]);

    if (!geo) return null;
    const { W, H, route, planeSize } = geo;
    const period = cfg.dash + cfg.gap;

    return (
      <div className="fp-layer" style={{ width: W, height: H }} aria-hidden="true">
        <svg className="fp-svg" width={W} height={H} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
          <defs>
            <clipPath id="fp-clip">
              <rect ref={clipRef} x="0" y="0" width={W} height="0" />
            </clipPath>
          </defs>
          {routeAhead && (
            <path d={route} fill="none" stroke={PURPLE} strokeOpacity={cfg.aheadOpacity}
                  strokeWidth="2" strokeDasharray="2 13" strokeLinecap="round" />
          )}
          <g clipPath="url(#fp-clip)">
            <path ref={pathRef} d={route} fill="none" stroke={PURPLE} strokeWidth={cfg.sw}
                  strokeDasharray={`${cfg.dash} ${cfg.gap}`} strokeLinecap="round" />
            <path d={route} fill="none" stroke={accent} strokeWidth={cfg.sw}
                  strokeDasharray={`${cfg.dash} ${cfg.gap}`} strokeDashoffset={-(period / 2)}
                  strokeLinecap="round" />
          </g>
        </svg>
        <div
          ref={planeRef}
          className={`fp-plane ${cfg.bob ? 'fp-plane--bob' : ''}`}
          style={{ offsetPath: `path("${route}")`, offsetDistance: '0%' }}
        >
          <span className="fp-plane__inner"><Airliner size={planeSize} /></span>
        </div>
      </div>
    );
  }

  window.FlightPath = FlightPath;
})();
