// Hyper · UX extras
// ProgressBar · StickyCTA · ClientLogos · useActiveSection

// ──────────────────────────────────────────────
// Thin scroll progress bar (top of viewport)
// ──────────────────────────────────────────────
function ProgressBar() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const update = () => {
      const h = document.documentElement;
      const max = h.scrollHeight - h.clientHeight;
      const p = max > 0 ? h.scrollTop / max : 0;
      if (ref.current) ref.current.style.transform = `scaleX(${p})`;
    };
    update();
    window.addEventListener('scroll', update, { passive: true });
    window.addEventListener('resize', update);
    return () => {
      window.removeEventListener('scroll', update);
      window.removeEventListener('resize', update);
    };
  }, []);
  return (
    <div className="progress" aria-hidden="true">
      <div className="progress-fill" ref={ref}></div>
    </div>
  );
}

// ──────────────────────────────────────────────
// Sticky CTA (bottom-right, appears after hero)
// ──────────────────────────────────────────────
function StickyCTA() {
  const [visible, setVisible] = React.useState(false);
  React.useEffect(() => {
    const hero = document.querySelector('.hero');
    const contact = document.querySelector('#contact');
    const onScroll = () => {
      const past = hero ? window.scrollY > hero.offsetHeight - 200 : true;
      const inContact =
        contact &&
        window.scrollY + window.innerHeight > contact.offsetTop + 120;
      setVisible(past && !inContact);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  return (
    <button
      type="button"
      onClick={() => window.openLead({ service: 'consult', source: 'Плавающая кнопка «Связаться»' })}
      className={'sticky-cta' + (visible ? ' is-visible' : '')}
      data-cursor
      data-cursor-label="связаться"
      aria-label="Связаться">
      <span className="sticky-cta-dot" aria-hidden="true"></span>
      <span className="sticky-cta-label">Связаться</span>
      <span className="sticky-cta-arrow" aria-hidden="true">→</span>
    </button>
  );
}

// ──────────────────────────────────────────────
// NavDock — постоянный «возврат» (низ-слева, всегда под рукой)
// back: { label, onClick, hint } | null · home: href | null (self)
// ──────────────────────────────────────────────
function NavDock({ back = null, home = 'index.html', topId = null }) {
  const [visible, setVisible] = React.useState(false);
  const hasBack = !!back;
  React.useEffect(() => {
    const onScroll = () => {
      const trig = Math.min((window.innerHeight || 800) * 0.55, 360);
      const past = hasBack || window.scrollY > trig;
      // прячем, когда подъезжаем к подвалу, чтобы не перекрывать его текст
      const foot = document.querySelector('.foot, .footer');
      const atFoot = foot && foot.getBoundingClientRect().top < (window.innerHeight || 800) - 8;
      setVisible(past && !atFoot);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, [hasBack]);

  const toTop = () => {
    const el = topId && document.getElementById(topId);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
    else window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  return (
    <nav className={'navdock' + (visible ? ' is-visible' : '') + (back ? ' has-back' : '')} aria-label="Быстрая навигация">
      {back && (
        <button
          className="navdock-btn navdock-back"
          data-cursor data-cursor-label={back.hint || 'назад'}
          onClick={back.onClick}>
          <span className="navdock-ico" aria-hidden="true">←</span>
          <span className="navdock-txt">{back.label}</span>
        </button>
      )}
      <button
        className="navdock-btn navdock-top"
        data-cursor data-cursor-label="наверх"
        onClick={toTop}>
        <span className="navdock-ico" aria-hidden="true">↑</span>
        <span className="navdock-txt">Наверх</span>
      </button>
      {home && (
        <a
          className="navdock-btn navdock-home"
          href={home}
          data-cursor data-cursor-label="на главную">
          <span className="navdock-ico" aria-hidden="true">⌂</span>
          <span className="navdock-txt">Главная</span>
        </a>
      )}
    </nav>
  );
}

// ──────────────────────────────────────────────
// Active section highlight in nav (scroll spy)
// ──────────────────────────────────────────────
function useActiveSection() {
  React.useEffect(() => {
    const links = [...document.querySelectorAll('.nav-links a[href^="#"]')];
    const map = new Map();
    links.forEach((a) => {
      const id = a.getAttribute('href').slice(1);
      const sec = document.getElementById(id);
      if (sec) map.set(sec, a);
    });
    if (map.size === 0) return;

    const onScroll = () => {
      const y = window.scrollY + 120; // offset for nav height
      let active = null;
      map.forEach((_, sec) => {
        if (sec.offsetTop <= y) active = sec;
      });
      links.forEach((a) => a.classList.remove('is-active'));
      if (active) {
        const link = map.get(active);
        if (link) link.classList.add('is-active');
      }
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, []);
}

// ──────────────────────────────────────────────
// Client logos — DIOX (wordmark) + real client logos (mono)
// ──────────────────────────────────────────────
function ClientLogos() {
  const logos = [
    { kind: 'text', name: 'DIOX', cls: 'serif-bold' },
    { kind: 'img', src: 'assets/clients/pavlonia.png', name: 'Павлония', ratio: 'tall' },
    { kind: 'img', src: 'assets/clients/fuel.png', name: 'Fuel 1', ratio: 'wide' },
    { kind: 'img', src: 'assets/clients/versus.png', name: 'Versus', ratio: 'wide' },
    { kind: 'img', src: 'assets/clients/glaz.png', name: 'Глаз Алмаз — салон оптики', ratio: 'tall' },
    { kind: 'img', src: 'assets/clients/manymo.png', name: 'ManyMo', ratio: 'square' },
    { kind: 'img', src: 'assets/clients/homeplaza.png', name: 'Home Plaza', ratio: 'tall' },
    { kind: 'img', src: 'assets/clients/elektrobyt.png', name: 'Электробыт', ratio: 'wide' },
    { kind: 'img', src: 'assets/clients/stadium.png', name: 'Клиент', ratio: 'wide' },
    { kind: 'img', src: 'assets/clients/strollers.png', name: 'Лёгкие коляски', ratio: 'wide' },
    { kind: 'img', src: 'assets/clients/fabrista.png', name: 'Fabrista', ratio: 'wide', blend: true },
    { kind: 'img', src: 'assets/clients/ajva.png', name: 'AJVA', ratio: 'square' },
    { kind: 'img', src: 'assets/clients/ayvazov.png', name: 'Ayvazov', ratio: 'wide' },
    { kind: 'img', src: 'assets/clients/coffee29.png', name: '29 · кофейня', ratio: 'tall', blend: true },
  ];

  const gridRef = React.useRef(null);

  // Scroll-driven "constructor": every tile sits a little further out from its
  // grid slot (uniform gaps, no tilt, no jitter) and slides straight back in,
  // edges meeting, as the block scrolls up into view — clean assembly, already
  // locked together by the time you reach it; opens back up when you leave.
  React.useEffect(() => {
    const grid = gridRef.current;
    if (!grid) return;
    const cells = [...grid.querySelectorAll('.logo-cell')];
    const n = cells.length;

    const clamp = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
    // Remotion-style easeInOut (smooth start AND finish — no abrupt snap)
    const ease = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;

    const EXPAND = 0.16;   // how far apart tiles start, as a fraction of their offset from grid centre

    // each tile's offset from the grid centre (layout coords, transform-independent);
    // re-measured on resize so it tracks the 7→4→2 column breakpoints
    let off = [];
    const measure = () => {
      const cx = grid.clientWidth / 2, cy = grid.clientHeight / 2;
      off = cells.map(c => ({
        x: c.offsetLeft + c.offsetWidth / 2 - cx,
        y: c.offsetTop + c.offsetHeight / 2 - cy,
      }));
    };
    measure();
    window.addEventListener('resize', measure);

    let raf = 0, last = -1;
    const tick = () => {
      const rect = grid.getBoundingClientRect();
      const vh = window.innerHeight || 1;
      const v = (rect.top + rect.height / 2) / vh;   // 1 = block centre at viewport bottom, 0 = at top
      // 0 = apart, 1 = locked. Reaches 1 at v=0.55 (lower-middle) → together before you reach it.
      const p = ease(clamp((1.05 - v) / (1.05 - 0.55)));

      if (Math.abs(p - last) > 0.0008) {
        last = p;
        const k = EXPAND * (1 - p);                  // shrinks to 0 → tiles meet
        for (let i = 0; i < n; i++) {
          const o = off[i];
          cells[i].style.transform =
            `translate3d(${(o.x * k).toFixed(2)}px, ${(o.y * k).toFixed(2)}px, 0)`;
        }
      }
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', measure); };
  }, []);

  return (
    <section className="logos fade-up" aria-label="Клиенты">
      <div className="shell">
        <div className="logos-head">
          <span className="logos-label">Доверились</span>
          <span className="logos-rule"></span>
          <span className="logos-meta">100+ брендов · 7 лет работы</span>
        </div>
        <div className="logos-grid" ref={gridRef}>
          {logos.map((l, i) => (
            <div key={i} className="logo-cell" data-cursor data-cursor-label={l.name}>
              {l.kind === 'text'
                ? <span className={'lg-mark lg-' + l.cls}>{l.name}</span>
                : <img className={'lg-img lg-' + l.ratio + (l.blend ? ' lg-blend' : '')} src={l.src} alt={l.name} loading="lazy" />}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { ProgressBar, StickyCTA, ClientLogos, useActiveSection, NavDock });
