/* global React */
// Pixel Floors — shared building blocks

// Icon: load a brand icon from /design-system/icons/<name>.svg, current-color tinted via filter when possible.
function PFIcon({ name, size = 24, color }) {
  const src = `design-system/icons/${name}.svg`;
  return (
    <img
      src={src}
      alt=""
      width={size}
      height={size}
      style={{
        display: "block",
        width: size, height: size,
        objectFit: "contain",
        filter: color ? "none" : "none"
      }} />);


}



// Glass header w/ language switcher
function PFHeader({ lang, setLang, content, onCta }) {
  const [activeSection, setActiveSection] = React.useState("hero");

  React.useEffect(() => {
    const ids = ["products", "references", "comparison", "why", "contact"];
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) setActiveSection(e.target.id);
        });
      },
      { rootMargin: "-40% 0px -55% 0px", threshold: 0 }
    );
    ids.forEach((id) => {
      const el = document.getElementById(id);
      if (el) obs.observe(el);
    });
    return () => obs.disconnect();
  }, []);

  const items = [
  { id: "products", label: content.nav.products },
  { id: "references", label: content.nav.references },
  { id: "why", label: content.nav.why },
  { id: "comparison", label: content.nav.comparison },
  { id: "contact", label: content.nav.contact }];


  return (
    <div className="pf-header-wrap">
      <header className="pf-header">
        <a href="#hero" className="logo" aria-label="Pixel Floors home">
          <img src="design-system/logos/horizontal-logo.svg" alt="Pixel Floors" />
        </a>
        <nav>
          {items.map((it) =>
          <a key={it.id} href={`#${it.id}`}
          className={activeSection === it.id ? "active" : ""}>
              {it.label}
            </a>
          )}
        </nav>
        <div className="right">
          <div className="lang-switch" role="tablist" aria-label="Language">
            <button className={lang === "cs" ? "active" : ""} onClick={() => setLang("cs")}>CZ</button>
            <button className={lang === "en" ? "active" : ""} onClick={() => setLang("en")}>EN</button>
          </div>
          <button className="pf-btn primary small" onClick={onCta}>
            {content.nav.cta} →
          </button>
        </div>
      </header>
    </div>);

}

// Scroll-driven glass cubes that travel across the whole page.
// Three cubes (cyan, violet, orange) follow independent organic paths defined
// by keyframes at scroll-progress checkpoints; sizes swap so the smallest /
// medium / largest role rotates between them — never mechanical, never in sync.
function PFScrollCubes() {
  const layerRef = React.useRef(null);
  const cubeRefs = React.useRef([]);
  const stateRef = React.useRef({
    progress: 0,    // smoothed scroll progress 0..1
    target: 0,      // raw scroll progress
    time: 0,        // wallclock for the gentle idle bob
    raf: 0,
  });

  // Path keyframes. Coordinates are vw/vh of the viewport (cube center).
  // Scales rotate between ~0.45 (small) → ~0.9 (medium) → ~1.35 (large) at
  // staggered checkpoints so the trio never holds the same hierarchy.
  // Base size of each cube comes from CSS (--base-size) and is multiplied by scale.
  const PATHS = React.useMemo(() => ({
    cyan: [
      { p: 0.00, x:  8, y:  18, s: 0.55, r:  -6 },
      { p: 0.18, x: 78, y:  34, s: 0.80, r:   8 },
      { p: 0.34, x: 22, y:  62, s: 1.40, r: -14 },  // becomes largest
      { p: 0.52, x: 72, y:  44, s: 0.65, r:  20 },
      { p: 0.68, x: 14, y:  74, s: 1.05, r:  -4 },
      { p: 0.84, x: 84, y:  22, s: 0.50, r:  12 },
      { p: 1.00, x: 20, y:  40, s: 0.85, r:  -8 },
    ],
    violet: [
      { p: 0.00, x: 46, y:  82, s: 0.95, r:   6 },  // starts medium
      { p: 0.16, x: 18, y:  20, s: 0.55, r: -10 },
      { p: 0.32, x: 86, y:  56, s: 1.35, r:  16 },  // becomes largest
      { p: 0.50, x: 10, y:  48, s: 0.70, r:  -8 },
      { p: 0.66, x: 60, y:  14, s: 0.50, r:  18 },
      { p: 0.82, x: 30, y:  78, s: 1.20, r:  -6 },
      { p: 1.00, x: 78, y:  60, s: 0.75, r:  10 },
    ],
    orange: [
      { p: 0.00, x: 96, y:  30, s: 1.30, r:   4 },  // starts largest, offscreen R
      { p: 0.18, x: -8, y:  58, s: 0.65, r: -12 },  // dives off-left small
      { p: 0.34, x: 56, y:  18, s: 0.50, r:  10 },  // becomes smallest
      { p: 0.50, x: 22, y:  76, s: 1.05, r:  -8 },
      { p: 0.66, x: 92, y:  42, s: 1.40, r:  14 },  // big again, offscreen R
      { p: 0.82, x:  4, y:  20, s: 0.70, r:  -4 },
      { p: 1.00, x: 90, y:  78, s: 1.15, r:   8 },
    ],
  }), []);

  // smoothstep — softens the linear segment between keyframes
  const easeIO = (t) => t * t * (3 - 2 * t);

  const sample = React.useCallback((kfs, p) => {
    // clamp + binary find segment
    if (p <= kfs[0].p) return kfs[0];
    if (p >= kfs[kfs.length - 1].p) return kfs[kfs.length - 1];
    let i = 0;
    while (i < kfs.length - 1 && kfs[i + 1].p < p) i++;
    const a = kfs[i], b = kfs[i + 1];
    const t = easeIO((p - a.p) / (b.p - a.p));
    return {
      x: a.x + (b.x - a.x) * t,
      y: a.y + (b.y - a.y) * t,
      s: a.s + (b.s - a.s) * t,
      r: a.r + (b.r - a.r) * t,
    };
  }, []);

  React.useEffect(() => {
    const readScroll = () => {
      const doc = document.documentElement;
      const max = Math.max(1, doc.scrollHeight - window.innerHeight);
      stateRef.current.target = Math.min(1, Math.max(0, window.scrollY / max));
    };
    readScroll();
    window.addEventListener("scroll", readScroll, { passive: true });
    window.addEventListener("resize", readScroll);

    const cubes = [
      { key: "cyan",   el: cubeRefs.current[0], path: PATHS.cyan,   bobX: 1.3, bobY: 1.6, bobR: 1.8, phase: 0.0 },
      { key: "violet", el: cubeRefs.current[1], path: PATHS.violet, bobX: 1.8, bobY: 2.0, bobR: 1.4, phase: 1.7 },
      { key: "orange", el: cubeRefs.current[2], path: PATHS.orange, bobX: 2.2, bobY: 2.4, bobR: 2.2, phase: 3.3 },
    ];

    const tick = (now) => {
      const st = stateRef.current;
      // Smooth toward scroll target — lerp factor gives "weight"; lower = lazier
      st.progress += (st.target - st.progress) * 0.085;
      st.time = (now || performance.now()) / 1000;

      cubes.forEach((c, i) => {
        if (!c.el) return;
        const k = sample(c.path, st.progress);
        // Add small per-cube idle wobble so each one breathes independently
        const t = st.time + c.phase;
        const wx = Math.sin(t * 0.45) * c.bobX;
        const wy = Math.cos(t * 0.38) * c.bobY;
        const wr = Math.sin(t * 0.31) * c.bobR;
        const x = k.x + wx;
        const y = k.y + wy;
        const r = k.r + wr;
        c.el.style.transform =
          `translate(-50%, -50%) translate(${x}vw, ${y}vh) rotate(${r.toFixed(2)}deg) scale(${k.s.toFixed(3)})`;
        // Subtle depth: larger cubes a touch more opaque + heavier shadow via CSS var
        c.el.style.setProperty("--cube-scale", k.s.toFixed(3));
      });

      stateRef.current.raf = requestAnimationFrame(tick);
    };
    stateRef.current.raf = requestAnimationFrame(tick);

    return () => {
      cancelAnimationFrame(stateRef.current.raf);
      window.removeEventListener("scroll", readScroll);
      window.removeEventListener("resize", readScroll);
    };
  }, [PATHS, sample]);

  return (
    <div className="pf-scroll-cubes" aria-hidden="true" ref={layerRef}>
      <img className="cube cube-cyan"   src="assets/cube-cyan.webp"   alt="" ref={(el) => (cubeRefs.current[0] = el)} />
      <img className="cube cube-violet" src="assets/cube-violet.webp" alt="" ref={(el) => (cubeRefs.current[1] = el)} />
      <img className="cube cube-orange" src="assets/cube-orange.webp" alt="" ref={(el) => (cubeRefs.current[2] = el)} />
    </div>
  );
}

// 3D HERO VISUAL
function PFHeroVisual3D() {
  const mountRef = React.useRef(null);
  const controlsRef = React.useRef(null);
  const cameraRef = React.useRef(null);
  const [showSpecs, setShowSpecs] = React.useState(false);

  React.useEffect(() => {
    let unmounted = false;
    let renderer, scene, camera, controls;
    let requestID;
    let resizeHandler;

    (async () => {
      try {
        const initThree = (THREE, GLTFLoader, OrbitControls) => {
          if (unmounted) return;

          const width = mountRef.current.clientWidth;
          const height = mountRef.current.clientHeight;

          scene = new THREE.Scene();

          camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100000);
          camera.position.set(15, 10, 15);
          cameraRef.current = camera;

          renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
          renderer.setSize(width, height);
          renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
          renderer.outputColorSpace = THREE.SRGBColorSpace;
          mountRef.current.appendChild(renderer.domElement);

          const ambientLight = new THREE.AmbientLight(0xffffff, 1.5);
          scene.add(ambientLight);

          const dirLight = new THREE.DirectionalLight(0xffffff, 2);
          dirLight.position.set(10, 20, 10);
          scene.add(dirLight);

          const loader = new GLTFLoader();
          loader.load('assets/models/Pixel Floor MINI.glb', (gltf) => {
            const model = gltf.scene;
            
            scene.add(model);
            model.updateMatrixWorld(true);

            const box = new THREE.Box3();
            model.traverse((child) => {
              if (child.isMesh && child.geometry) {
                child.geometry.computeBoundingBox();
                const childBox = child.geometry.boundingBox.clone();
                childBox.applyMatrix4(child.matrixWorld);
                box.union(childBox);
              }
            });
            
            const size = box.getSize(new THREE.Vector3());
            const center = box.getCenter(new THREE.Vector3());
            
            // Vycentrování modelu
            model.position.x -= center.x;
            model.position.y -= center.y;
            model.position.z -= center.z;

            // Automatické nastavení kamery podle velikosti modelu
            const maxDim = Math.max(size.x, size.y, size.z);
            cameraRef.current.userData.modelMaxDim = maxDim;
            
            const distance = maxDim * 2;
            camera.position.set(distance, distance * 0.8, distance);
            camera.lookAt(0, 0, 0);

            controls = new OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.05;
            controls.target.set(0, 0, 0);
            const startDistance = camera.position.length();
            controls.minDistance = startDistance / 2;
            controls.maxDistance = startDistance;
            controls.update();
            controlsRef.current = controls;

            const animate = () => {
              if (unmounted) return;
              requestID = requestAnimationFrame(animate);
              if (controlsRef.current) controlsRef.current.update();
              renderer.render(scene, camera);
            };
            animate();
          });

          resizeHandler = () => {
            if (!mountRef.current || !renderer || !camera) return;
            const w = mountRef.current.clientWidth;
            const h = mountRef.current.clientHeight;
            camera.aspect = w / h;
            camera.updateProjectionMatrix();
            renderer.setSize(w, h);
          };
          window.addEventListener('resize', resizeHandler);
        };

        if (window.THREE && window.GLTFLoader && window.OrbitControls) {
          initThree(window.THREE, window.GLTFLoader, window.OrbitControls);
        } else {
          window.addEventListener('three-loaded', () => {
            initThree(window.THREE, window.GLTFLoader, window.OrbitControls);
          }, { once: true });
        }

      } catch (err) {
        console.error("ThreeJS load error:", err);
      }
    })();

    return () => {
      unmounted = true;
      if (requestID) cancelAnimationFrame(requestID);
      if (resizeHandler) window.removeEventListener('resize', resizeHandler);
      if (renderer && renderer.domElement.parentNode) {
        renderer.domElement.parentNode.removeChild(renderer.domElement);
      }
      if (renderer) renderer.dispose();
    };
  }, []);

  const handleShowSpecs = () => {
    if (!cameraRef.current || !controlsRef.current || !window.gsap) return;
    
    controlsRef.current.enabled = false;
    const maxDim = cameraRef.current.userData.modelMaxDim || 10;
    const topY = maxDim * 2.5; // Přiměřená výška nad modelem
    
    window.gsap.to(cameraRef.current.position, {
      x: 0,
      y: topY,
      z: maxDim * 0.05, // malý offset pro prevenci gimbal lock v OrbitControls
      duration: 1.5,
      ease: "power3.inOut",
      onUpdate: () => {
        cameraRef.current.lookAt(0, 0, 0);
        controlsRef.current.target.set(0, 0, 0);
      },
      onComplete: () => {
        setShowSpecs(true);
      }
    });
  };

  return (
    <div className="pf-hero-visual">
      <div ref={mountRef} className="pf-3d-canvas"></div>
      
      {!showSpecs && (
        <button className="pf-btn glass pf-specs-btn" onClick={handleShowSpecs}>
          Zobrazit technická data
        </button>
      )}

      <div className={`pf-specs-panel ${showSpecs ? 'visible' : ''}`}>
        <h3>Pixel Floor MINI</h3>
        <ul>
          <li><strong>Rozměry:</strong> 500 × 500 × 35 mm</li>
          <li><strong>Hmotnost:</strong> 4.2 kg</li>
          <li><strong>Zátěž:</strong> až 1000 kg / dlaždici</li>
          <li><strong>Konektivita:</strong> Wi-Fi, Ethernet</li>
          <li><strong>Spotřeba:</strong> 15 W (max)</li>
        </ul>
        <button className="pf-btn primary small" onClick={() => {
          setShowSpecs(false);
          controlsRef.current.enabled = true;
        }}>Zavřít</button>
      </div>
    </div>
  );
}

// HERO
function PFHero({ content, onPrimary, onSecondary }) {
  return (
    <section className="pf-hero" id="hero">
      <div className="hero-text">
        <a href="#references" className="kicker">
          {content.kicker} · {content.kickerStat} →
        </a>
        <h1>
          {content.h1.map((line, i) =>
          <React.Fragment key={i}>
              {line}
              {i < content.h1.length - 1 ? <br /> : null}
            </React.Fragment>
          )}
        </h1>
        <p className="lead">{content.lead}</p>
        <div className="cta-row">
          <button className="pf-btn primary large" onClick={onPrimary}>{content.primary} →</button>
          <button className="pf-btn glass large" onClick={onSecondary}>{content.secondary}</button>
        </div>
      </div>

      <PFHeroVisual3D />
    </section>);

}

// STATS — bento "scoreboard" grid (static, not a marquee — distinct from refs)
function PFStatsMarquee({ content }) {
  // First three items are quant (numeric), the rest are qualitative proof points.
  const featured = content.items.slice(0, 3); // 5000+, 50+, 12+
  const qualitative = content.items.slice(3); // the rest
  return (
    <section className="pf-section pf-proofgrid" id="proofs-marquee">
      <div className="pf-shell">
        <div className="pf-section-head">
          <span className="eyebrow">{content.eyebrow}</span>
          <h2 className="pf-h2" style={{ fontSize: "clamp(34px, 4.4vw, 60px)" }}>{content.title}</h2>
          <p className="lead" style={{ marginTop: 12 }}>{content.lead}</p>
        </div>

        <div className="pf-scoreboard">
          {/* Featured big stat — spans 2x2 */}
          <a className="pf-score-hero" href="#why" aria-label={featured[0].label}>
            <div className="pf-score-hero-bg" aria-hidden="true" />
            <div className="pf-score-hero-inner">
              <span className="ix">01</span>
              <div className="pf-score-hero-num">{featured[0].num}</div>
              <div className="pf-score-hero-lbl">{featured[0].label}</div>
              <span className="pf-score-arrow" aria-hidden="true">→</span>
            </div>
          </a>

          {/* Two stacked supporting stats — glass */}
          {featured.slice(1).map((it, i) =>
          <a className="pf-score-mid" href="#why" key={i}>
              <span className="ix">{String(i + 2).padStart(2, "0")}</span>
              <div className="pf-score-mid-num">{it.num}</div>
              <div className="pf-score-mid-lbl">{it.label}</div>
              <span className="pf-score-arrow" aria-hidden="true">→</span>
            </a>
          )}

          {/* Qualitative proof chips — 4-col grid below */}
          {qualitative.map((it, i) =>
          <a className="pf-score-chip" href="#why" key={i}>
              <span className="pf-score-chip-icon"><PFIcon name={it.icon} size={20} /></span>
              <span className="pf-score-chip-lbl">{it.label}</span>
              <span className="pf-score-arrow" aria-hidden="true">→</span>
            </a>
          )}
        </div>
      </div>
    </section>);

}

// REFS marquee
function PFRefs({ content }) {
  const doubled = content.logos.concat(content.logos);
  return (
    <section className="pf-refs" id="references">
      <div className="pf-shell">
        <div className="pf-section-head">
          <span className="eyebrow">{content.eyebrow}</span>
          <h2 className="pf-h2">{content.title}</h2>
          <p className="lead">{content.lead}</p>
        </div>
      </div>
      <div className="pf-logo-marquee">
        <div className="track" style={{ gap: "32px" }}>
          {doubled.map((l, i) =>
          <div className="pf-logo-card" key={i}>
              <div className="logo-art">
                <span className="mark" style={{ background: l.color }}>{l.initial}</span>
                {l.name}
              </div>
              <div className="tag">{l.tag}</div>
            </div>
          )}
        </div>
      </div>
    </section>);

}

window.PFIcon = PFIcon;
window.PFScrollCubes = PFScrollCubes;
window.PFHeader = PFHeader;
window.PFHero = PFHero;
window.PFStatsMarquee = PFStatsMarquee;
window.PFRefs = PFRefs;