/* global React */
const { useState, useEffect, useRef, useCallback, useMemo } = React;

// ============================================
// HERO 1 — MOSAICO ROMÁ → LOGO (canònic)
// Tessel·lació completa sense espais. El scroll (wheel) avança
// d'un camp de rajoles caòtiques (gris / blau / taronja / blanc)
// cap a un mosaic ordenat amb el logo Talos a sobre.
// ============================================
const COLS = 10;
const ROWS = 8;

const MOSAIC_PALETTE = [
  '#E5E7EB', // gris clar
  '#CBD5E1', // gris mig
  '#FFFFFF', // blanc
  '#003C70', // navy
  '#005096', // navy-light
  '#FF4E00', // orange
];

// Genera un estat de caos: rotacions, desplaçaments petits, colors barrejats
const makeMosaicState = () => {
  const rnd = (min, max) => min + Math.random() * (max - min);
  const cells = [];
  for (let r = 0; r < ROWS; r++) {
    for (let c = 0; c < COLS; c++) {
      // Tria caòtica de color
      const chaosColor = MOSAIC_PALETTE[Math.floor(Math.random() * MOSAIC_PALETTE.length)];
      // Ordre: patró tipus tauler romà — majoria gris/blanc amb navy i un accent taronja
      const isCheck = (r + c) % 2 === 0;
      let orderColor;
      // Logo mask: cel·les centrals reservades per el logo horizontal
      const inLogoRow = r >= 3 && r <= 4;
      const inLogoCol = c >= 2 && c <= COLS - 3;
      if (inLogoRow && inLogoCol) {
        orderColor = '#FFFFFF';
      } else {
        // Tauler: alternança gris/blanc amb navy puntuat i taronja rar
        const navyPick = ((r * 3 + c * 5) % 7 === 0);
        const orangePick = ((r * 7 + c * 11) % 23 === 0);
        if (orangePick) orderColor = '#FF4E00';
        else if (navyPick) orderColor = '#003C70';
        else orderColor = isCheck ? '#E5E7EB' : '#FFFFFF';
      }
      cells.push({
        r, c,
        cOffsetX: rnd(-28, 28),
        cOffsetY: rnd(-28, 28),
        cRot: rnd(-18, 18),
        cScale: rnd(0.82, 1.08),
        chaosColor,
        orderColor,
        inLogo: inLogoRow && inLogoCol,
      });
    }
  }
  return cells;
};

const HeroMosaic = ({ progress: externalProgress }) => {
  const [internalProgress, setInternalProgress] = useState(0); // 0 = caos, 1 = ordre
  const cells = useMemo(makeMosaicState, []);
  const stageRef = useRef(null);
  const progress = typeof externalProgress === 'number' ? externalProgress : internalProgress;

  // Scroll-driven: només scroll, sense slider
  useEffect(() => {
    if (typeof externalProgress === 'number') return;
    const onScroll = () => {
      const stage = stageRef.current;
      if (!stage) return;
      const rect = stage.getBoundingClientRect();
      const vh = window.innerHeight;
      // Fade: progress va de 0 a 1 a mesura que l'stage puja cap amunt
      // 0 quan l'element està centrat al viewport, 1 quan el seu centre arriba al 20% superior
      const center = rect.top + rect.height / 2;
      const p = Math.max(0, Math.min(1, 1 - (center - vh * 0.2) / (vh * 0.5)));
      setInternalProgress(p);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, [externalProgress]);

  const showLogo = progress > 0.82;

  return (
    <div ref={stageRef} className="mosaic-stage">
      <div
        className="mosaic-grid"
        style={{
          '--cols': COLS,
          '--rows': ROWS,
        }}
      >
        {cells.map((cell, i) => {
          const x = cell.cOffsetX * (1 - progress);
          const y = cell.cOffsetY * (1 - progress);
          const rot = cell.cRot * (1 - progress);
          const scale = 1 + (cell.cScale - 1) * (1 - progress);
          // Interpolació de color (hex mix rudimentari)
          const color = progress > 0.5 ? cell.orderColor : cell.chaosColor;
          // Cel·les del logo: fade out just abans d'aparèixer el logo, per deixar espai blanc
          const logoMaskOpacity = cell.inLogo && progress > 0.75
            ? Math.max(0, 1 - (progress - 0.75) * 4)
            : 1;
          return (
            <div
              key={i}
              className="mosaic-cell-shell"
              style={{
                transform: `translate(${x}px, ${y}px) rotate(${rot}deg) scale(${scale})`,
                opacity: logoMaskOpacity,
                zIndex: cell.inLogo ? 1 : 2,
              }}
            >
              <div
                className="mosaic-cell"
                style={{
                  background: color,
                  '--float-x': `${cell.cOffsetX * 0.18}px`,
                  '--float-y': `${cell.cOffsetY * 0.18}px`,
                  '--float-r': `${cell.cRot * 0.2}deg`,
                  '--float-d': `${(i % 11) * -0.37}s`,
                }}
              />
            </div>
          );
        })}
      </div>

      <div className={`mosaic-logo ${showLogo ? 'is-visible' : ''}`}>
        <img src="assets/logo-horizontal.svg" alt="Talos" />
      </div>
    </div>
  );
};

// Alias per compatibilitat amb el switcher
const HeroChaos = HeroMosaic;

// ============================================
// HERO 2 — DASHBOARD EN VIVO
// ============================================
const HeroDashboard = () => {
  const [tick, setTick] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setTick(t => t + 1), 1800);
    return () => clearInterval(id);
  }, []);

  // Generate a sparkline
  const points = useMemo(() => {
    const arr = [];
    for (let i = 0; i < 20; i++) {
      arr.push(50 + Math.sin((i + tick) * 0.4) * 18 + Math.random() * 8);
    }
    return arr;
  }, [tick]);
  const path = points.map((y, i) => `${i === 0 ? 'M' : 'L'} ${(i / 19) * 100} ${y}`).join(' ');

  const rows = [
    { s: 'g', name: 'ERP · Facturación',     v: 'OK' },
    { s: 'g', name: 'SharePoint · Contratos', v: 'OK' },
    { s: 'a', name: 'CRM · Leads',           v: 'Revisión' },
    { s: 'g', name: 'Nómina · RGPD',         v: 'OK' },
    { s: 'r', name: 'Legacy · BBDD',         v: 'Acción' },
  ];

  return (
    <div className="dash-stage">
      <div className="dash-header">
        <span className="dash-title">Panel de gobernanza</span>
        <span className="dash-live">En vivo</span>
      </div>
      <div className="dash-kpis">
        <div className="dash-kpi">
          <div className="n">12.4K</div>
          <div className="l">Registros auditados</div>
          <div className="d">+8% semana</div>
        </div>
        <div className="dash-kpi">
          <div className="n">98%</div>
          <div className="l">Cumplimiento</div>
          <div className="d">+2 pts</div>
        </div>
        <div className="dash-kpi">
          <div className="n">37h</div>
          <div className="l">Ahorradas/sem</div>
          <div className="d">+14h</div>
        </div>
      </div>
      <div className="dash-chart">
        <span className="dash-chart-title">Flujo de procesos · últimas 24h</span>
        <svg viewBox="0 0 100 80" preserveAspectRatio="none" style={{ width: '100%', height: 80 }}>
          <defs>
            <linearGradient id="grad" x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%" stopColor="#003C70" stopOpacity="0.25" />
              <stop offset="100%" stopColor="#003C70" stopOpacity="0" />
            </linearGradient>
          </defs>
          <path d={`${path} L 100 80 L 0 80 Z`} fill="url(#grad)" />
          <path d={path} fill="none" stroke="#003C70" strokeWidth="1" vectorEffect="non-scaling-stroke" />
          <path d={path.replace(/ [\d.]+ [\d.]+/g, (m, i) => m)} fill="none" stroke="#FF4E00" strokeWidth="0.5" strokeDasharray="2 2" opacity="0.6" vectorEffect="non-scaling-stroke" />
        </svg>
      </div>
      <div className="dash-rows">
        {rows.map((r, i) => (
          <div key={i} className="dash-row">
            <span className={`status ${r.s}`} />
            <span>{r.name}</span>
            <span style={{ textAlign: 'right', color: r.s === 'r' ? '#EF4444' : r.s === 'a' ? '#B45309' : '#16A34A', fontWeight: 600 }}>{r.v}</span>
          </div>
        ))}
      </div>
    </div>
  );
};

// ============================================
// HERO 3 — EDITORIAL (quote + navy canvas)
// ============================================
const HeroEditorial = () => (
  <div className="editorial-stage">
    <div className="editorial-glyph">T.</div>
    <div className="editorial-top">
      <span>Talos · manifiesto</span>
      <span>nº 01</span>
    </div>
    <div className="editorial-quote">
      “Lo que no <em style={{ fontFamily: 'var(--serif)', color: '#FF4E00' }}>gobiernas</em>,<br/>
      no lo puedes <em style={{ fontFamily: 'var(--serif)', color: '#FF4E00' }}>automatizar</em>.<br/>
      Primero el orden,<br/>
      después la <em style={{ fontFamily: 'var(--serif)' }}>inteligencia</em>.”
    </div>
    <div className="editorial-bottom">
      <div className="editorial-pill">Gobernanza → Digitalización → IA</div>
      <div>ES · 2026</div>
    </div>
  </div>
);

// ============================================
// HERO SECTION (switcher)
// ============================================
const HERO_SCROLL_MESSAGES = [
  {
    eyebrow: 'Talos Technology · Consultoría tecnológica para empresas e instituciones',
    title: 'Datos en orden. Procesos en marcha. IA donde aporta valor.',
    lead: 'Tres ámbitos operativos, un mismo orden de trabajo: ordenar antes de automatizar, automatizar antes de aplicar IA. Y formación inmersiva cuando el cambio requiere práctica antes que teoría.',
    strong: 'Una metodología contrastada y módulos que se entregan, no que se prometen.',
  },
  {
    eyebrow: 'Primero ordenar · después automatizar',
    title: 'Sin orden en los datos, la digitalización amplifica el desorden.',
    lead: 'Cuando la información tiene responsables, reglas y trazabilidad, los procesos dejan de depender de perseguir personas. Solo entonces tiene sentido aplicar IA.',
    strong: 'Gobernanza, digitalización e IA aplicada en el orden correcto.',
  },
  {
    eyebrow: 'Diagnóstico primero · módulos después',
    title: 'Sistemas que trabajan. Equipos que deciden mejor.',
    lead: 'La hoja de ruta convierte datos dispersos, tareas manuales y conocimiento atrapado en decisiones más claras. Y cuando el cambio requiere práctica antes que teoría, la inmersión aplicada entrena a tu equipo en entornos seguros.',
    strong: 'Diagnóstico honesto. Impacto priorizado. Cierre verificable en cada fase.',
  },
];

const makeSeededRandom = (seed = 183) => {
  let value = seed >>> 0;
  return () => {
    value += 0x6D2B79F5;
    let t = value;
    t = Math.imul(t ^ (t >>> 15), t | 1);
    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
};

const HeroThreeCanvas = () => {
  const hostRef = useRef(null);
  const canvasRef = useRef(null);

  useEffect(() => {
    let cancelled = false;
    let frameId = 0;
    let resizeObserver = null;
    let renderer = null;
    let geometry = null;
    let scene = null;
    let group = null;
    const materials = [];

    const start = (THREE) => {
      if (cancelled || !THREE || !hostRef.current || !canvasRef.current) return;

      const canvas = canvasRef.current;
      canvas.dataset.engine = 'three.js r183';

      scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 1000);
      camera.position.set(0, 0.5, 7.5);

      renderer = new THREE.WebGLRenderer({
        canvas,
        alpha: true,
        antialias: true,
        powerPreference: 'high-performance',
      });
      renderer.setClearColor(0x000000, 0);
      renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 1.5));

      scene.add(new THREE.AmbientLight(0xffffff, 0.74));
      const key = new THREE.DirectionalLight(0xffffff, 1.08);
      key.position.set(6, 10, 6);
      scene.add(key);
      const warm = new THREE.DirectionalLight(0xfff1e8, 0.22);
      warm.position.set(-5, 3, -3);
      scene.add(warm);
      const blue = new THREE.PointLight(0x003c70, 0.16);
      blue.position.set(0, -2, 3);
      scene.add(blue);

      group = new THREE.Group();
      scene.add(group);

      const palette = ['#003C70', '#003C70', '#0A4A80', '#1F5E8A', '#3F7899', '#7893A6', '#AEBECE', '#D9DEE5', '#E8EDF2', '#FFFFFF', '#FF4E00'];
      const random = makeSeededRandom(427183);
      const center = 1.38;
      const spacing = 0.46;
      geometry = new THREE.BoxGeometry(0.38, 0.38, 0.38);
      const blocks = [];

      for (let x = 0; x < 7; x += 1) {
        for (let y = 0; y < 7; y += 1) {
          for (let z = 0; z < 7; z += 1) {
            if (random() > 0.42) continue;
            const color = palette[Math.floor(random() * palette.length)];
            const isSoft = ['#FFFFFF', '#F7F9FB', '#E8EDF2', '#D9DEE5', '#B9CBD8'].includes(color);
            const isOrange = color === '#FF4E00';
            const material = new THREE.MeshStandardMaterial({
              color,
              roughness: 0.58,
              metalness: 0.02,
              transparent: true,
              opacity: isSoft ? 0.52 : isOrange ? 0.84 : 0.9,
            });
            materials.push(material);
            const mesh = new THREE.Mesh(geometry, material);
            const base = {
              x: spacing * x - center,
              y: spacing * y - center,
              z: spacing * z - center,
            };
            mesh.position.set(base.x, base.y, base.z);
            mesh.rotation.set(random() * Math.PI, random() * Math.PI, random() * Math.PI);
            group.add(mesh);
            blocks.push({
              mesh,
              base,
              floatSpeed: 0.3 + 0.5 * random(),
              floatAmplitude: 0.05 + 0.12 * random(),
              floatPhase: random() * Math.PI * 2,
              rotSpeed: [
                (random() - 0.5) * 0.15,
                (random() - 0.5) * 0.15,
                (random() - 0.5) * 0.08,
              ],
            });
          }
        }
      }

      const resize = () => {
        if (!hostRef.current || !renderer) return;
        const rect = hostRef.current.getBoundingClientRect();
        const width = Math.max(1, Math.round(rect.width));
        const height = Math.max(1, Math.round(rect.height));
        camera.aspect = width / height;
        camera.updateProjectionMatrix();
        renderer.setSize(width, height, false);
      };

      resizeObserver = new ResizeObserver(resize);
      resizeObserver.observe(hostRef.current);
      resize();

      let last = performance.now();
      const animate = (now) => {
        if (cancelled || !renderer) return;
        const delta = Math.min(0.05, (now - last) / 1000);
        last = now;
        const elapsed = now / 1000;

        group.rotation.y += 0.14 * delta;
        group.rotation.x = 0.1 * Math.sin(0.22 * elapsed);

        blocks.forEach((block) => {
          const { mesh, base, floatSpeed, floatAmplitude, floatPhase, rotSpeed } = block;
          mesh.position.x = base.x + Math.sin(elapsed * floatSpeed * 1.35 + floatPhase) * floatAmplitude * 1.25;
          mesh.position.y = base.y + Math.sin(elapsed * floatSpeed * 1.65 + floatPhase + 1) * floatAmplitude * 1.5;
          mesh.position.z = base.z + Math.cos(elapsed * floatSpeed * 1.05 + floatPhase + 2) * floatAmplitude;
          mesh.rotation.x += 0.03 * rotSpeed[0];
          mesh.rotation.y += 0.03 * rotSpeed[1];
          mesh.rotation.z += 0.024 * rotSpeed[2];
        });

        renderer.render(scene, camera);
        frameId = requestAnimationFrame(animate);
      };

      frameId = requestAnimationFrame(animate);
    };

    const ready = window.TALOS_THREE_READY || Promise.resolve(window.THREE);
    ready.then(start).catch(() => {});

    return () => {
      cancelled = true;
      cancelAnimationFrame(frameId);
      if (resizeObserver) resizeObserver.disconnect();
      materials.forEach((material) => material.dispose());
      if (geometry) geometry.dispose();
      if (renderer) renderer.dispose();
      scene = null;
      group = null;
    };
  }, []);

  return (
    <div ref={hostRef} className="hero-three-scene" aria-hidden="true">
      <canvas ref={canvasRef} />
    </div>
  );
};

const HeroSection = ({ variant }) => {
  const ref = useRef(null);
  const [progress, setProgress] = useState(0);
  const activeIndex = Math.min(HERO_SCROLL_MESSAGES.length - 1, Math.floor(progress * HERO_SCROLL_MESSAGES.length));
  const active = HERO_SCROLL_MESSAGES[activeIndex];

  useEffect(() => {
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduced) return;
    const onScroll = () => {
      const el = ref.current;
      if (!el) return;
      const rect = el.getBoundingClientRect();
      const span = Math.max(1, rect.height - window.innerHeight);
      const p = Math.max(0, Math.min(1, -rect.top / span));
      setProgress(p);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  return (
    <section className="hero" ref={ref}>
      <div className="container-wide hero-sticky" style={{ width: '100%' }}>
        <div className="hero-grid">
          <div className="hero-copy">
            <p className="eyebrow fade-up is-in">{active.eyebrow}</p>
            <h1 className="fade-up is-in">{active.title}</h1>
            <p className="hero-lead fade-up is-in">
              {active.lead}{' '}
              <strong>{active.strong}</strong>
            </p>
            <div className="cta-row fade-up is-in">
              <a className="btn btn-primary" href="/diagnostico">Solicita tu diagnóstico <ArrowRight /></a>
              <a className="btn btn-ghost" href="/metodologia">Ver cómo trabajamos</a>
            </div>
          </div>
          <div className="hero-visual">
            <HeroThreeCanvas />
          </div>
        </div>
      </div>
    </section>
  );
};

Object.assign(window, { HeroSection, HeroChaos, HeroDashboard, HeroEditorial, HeroThreeCanvas });
