/* ============================================================
   Business model — flux bidirectionnels animés
   Hub central Neolia, 4 acteurs autour. Pour chaque axe :
   - Ligne verte : Neolia → acteur (valeur livrée)
   - Ligne orange : acteur → Neolia (contrepartie / paiement)
   Pulses circulants animés. Inspiré de illustration-flux.jsx.
   ============================================================ */

const { useEffect: useEffectBM, useState: useStateBM } = React;

const BM_I18N = {
  fr: {
    overlay: 'Modèle d’affaires · Flux bidirectionnels',
    actors: {
      // role kept short (1 verb) to mirror the format of DirCFlux subs ("SIP · Vidéo", "M-Bus · PV"…)
      promoteur:    { title: 'Promoteur',    role: 'Conçoit',   give: '−38 % de CAPEX',     sub_give: 'courant-faible allégé',     pay: 'CAPEX au permis', sub_pay: 'une seule fois' },
      construction: { title: 'Constructeur', role: 'Construit', give: '1 lot, 1 fournisseur', sub_give: 'mise en service < 2 sem.', pay: 'Pose & câblage',  sub_pay: 'temps installateur' },
      regie:        { title: 'Régie',        role: 'Exploite',  give: 'OPEX simplifié',   sub_give: 'décomptes & SAV unifiés',   pay: 'OPEX mensuel',     sub_pay: 'par logement' },
      resident:     { title: 'Résident',     role: 'Habite',    give: 'App incluse',        sub_give: 'porte · énergie · domotique', pay: 'Usage quotidien',  sub_pay: 'add-ons en option' },
    },
  },
  de: {
    overlay: 'Geschäftsmodell · Bidirektionale Flüsse',
    actors: {
      promoteur:    { title: 'Bauträger',    role: 'Entwirft',  give: '−38 % CAPEX',          sub_give: 'weniger Schwachstrom',     pay: 'CAPEX bei Baugenehmigung', sub_pay: 'einmalig' },
      construction: { title: 'Bauunternehmen', role: 'Installiert', give: '1 Los, 1 Lieferant', sub_give: 'Inbetriebnahme < 2 Wochen', pay: 'Installation & Verkabelung', sub_pay: 'Installateurszeit' },
      regie:        { title: 'Verwaltung',   role: 'Betreibt',  give: 'OPEX vereinfacht',     sub_give: 'Abrechnungen & Service zentral', pay: 'OPEX monatlich',  sub_pay: 'pro Wohnung' },
      resident:     { title: 'Bewohner',     role: 'Wohnt',     give: 'App inklusive',        sub_give: 'Tür · Energie · Smart Home', pay: 'Tägliche Nutzung', sub_pay: 'Add-ons optional' },
    },
  },
  it: {
    overlay: 'Modello di business · Flussi bidirezionali',
    actors: {
      promoteur:    { title: 'Promotore',    role: 'Progetta',  give: '−38 % di CAPEX',       sub_give: 'cavi ridotti',              pay: 'CAPEX alla licenza', sub_pay: 'una sola volta' },
      construction: { title: 'Costruttore',  role: 'Installa',  give: '1 lotto, 1 fornitore', sub_give: 'messa in servizio < 2 sett.', pay: 'Posa e cavi',     sub_pay: 'tempo installatore' },
      regie:        { title: 'Amministrazione', role: 'Gestisce', give: 'OPEX semplificato', sub_give: 'conteggi e assistenza unificati', pay: 'OPEX mensile',  sub_pay: 'per alloggio' },
      resident:     { title: 'Residente',    role: 'Abita',     give: 'App inclusa',          sub_give: 'porta · energia · domotica', pay: 'Uso quotidiano',  sub_pay: 'add-on opzionali' },
    },
  },
  en: {
    overlay: 'Business model · Bidirectional flows',
    actors: {
      promoteur:    { title: 'Developer',    role: 'Designs',   give: '−38 % CAPEX',          sub_give: 'lighter low-voltage',       pay: 'CAPEX at permit',  sub_pay: 'one-time' },
      construction: { title: 'Builder',      role: 'Installs',  give: '1 lot, 1 supplier',    sub_give: 'commissioning < 2 weeks',   pay: 'Install & wiring', sub_pay: 'installer time' },
      regie:        { title: 'Manager',      role: 'Operates',  give: 'OPEX simplified',      sub_give: 'statements & service unified', pay: 'Monthly OPEX',  sub_pay: 'per dwelling' },
      resident:     { title: 'Resident',     role: 'Lives',     give: 'App included',         sub_give: 'door · energy · smart home', pay: 'Daily use',      sub_pay: 'optional add-ons' },
    },
  },
};

function getBMLang() {
  if (typeof document === 'undefined') return BM_I18N.fr;
  const lang = (document.documentElement.lang || 'fr').toLowerCase().slice(0, 2);
  return BM_I18N[lang] || BM_I18N.fr;
}

function DirBusinessModel({ bare = false } = {}) {
  const [t, setT] = useStateBM(0);
  const [isMobile, setIsMobile] = useStateBM(
    typeof window !== 'undefined' && window.innerWidth <= 720
  );
  const i18n = getBMLang();

  useEffectBM(() => {
    let raf;
    const start = performance.now();
    const tick = (now) => {
      setT((now - start) / 1000);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  useEffectBM(() => {
    const onResize = () => setIsMobile(window.innerWidth <= 720);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  // Geometry
  const cx = 600, cy = 400;
  const hubRadius = 70;       // outer hub edge (where lines start)
  const nodeRadius = 22;      // actor inner ring (where lines end)
  const offset = isMobile ? 14 : 10;  // perpendicular offset between the 2 parallel lines

  // Text scaling — strictly mirrors DirCFlux so a toggle between the two
  // diagrams keeps every shared element pixel-stable.
  const fsCore  = isMobile ? 26 : 11;        // hub label "NEOLIA · CORE"
  const fsLabel = isMobile ? 36 : 16;        // actor title (Inter, big)
  const fsSub   = isMobile ? 22 : 10;        // actor role (mono, small)
  const labelOffset  = isMobile ? 70 : 52;   // distance from node center to label group
  const subOffset    = isMobile ? 52 : 26;   // sub-label position when node is below hub
  const subOffsetTop = isMobile ? -42 : -16; // sub-label position when node is above hub
  // Flow labels are unique to the business-model view (no equivalent in DirCFlux)
  const fsFlow       = isMobile ? 18 : 11;
  const fsFlowSub    = isMobile ? 16 : 10;
  const flowGap      = isMobile ? 26 : 22;

  const A = i18n.actors;
  // Coords aligned 1:1 with illustration-flux.jsx so toggling between the two
  // diagrams keeps the corner nodes pixel-stable.
  const actors = [
    { id: 'promoteur',    x: 220, y: 200, ...A.promoteur },
    { id: 'construction', x: 980, y: 200, ...A.construction },
    { id: 'regie',        x: 220, y: 600, ...A.regie },
    { id: 'resident',     x: 980, y: 600, ...A.resident },
  ];

  // Compute geometry for one actor's twin lines
  function computeFlow(node) {
    const dx = node.x - cx;
    const dy = node.y - cy;
    const len = Math.sqrt(dx * dx + dy * dy);
    const ux = dx / len, uy = dy / len;
    // Perpendicular (rot 90° ccw)
    const px = -uy, py = ux;

    // Line A: hub → actor (offset on +perp side, color: energy/green)
    const aStart = { x: cx + ux * hubRadius + px * offset, y: cy + uy * hubRadius + py * offset };
    const aEnd   = { x: node.x - ux * nodeRadius + px * offset, y: node.y - uy * nodeRadius + py * offset };
    // Line B: actor → hub (offset on -perp side, color: signal/orange)
    const bStart = { x: node.x - ux * nodeRadius - px * offset, y: node.y - uy * nodeRadius - py * offset };
    const bEnd   = { x: cx + ux * hubRadius - px * offset, y: cy + uy * hubRadius - py * offset };

    // Midpoints for labels
    const midA = { x: (aStart.x + aEnd.x) / 2 + px * flowGap, y: (aStart.y + aEnd.y) / 2 + py * flowGap };
    const midB = { x: (bStart.x + bEnd.x) / 2 - px * flowGap, y: (bStart.y + bEnd.y) / 2 - py * flowGap };

    // Label rotation (in degrees), flipped to stay readable
    let angle = Math.atan2(dy, dx) * 180 / Math.PI;
    if (angle > 90 || angle < -90) angle += 180;

    return { aStart, aEnd, bStart, bEnd, midA, midB, angle, len, ux, uy, px, py };
  }

  return (
    <div style={{
      position: 'relative',
      width: '100%',
      height: '100%',
      background: bare
        ? 'transparent'
        : 'radial-gradient(ellipse at 50% 50%, #1B2347 0%, #0B1129 55%, #050817 100%)',
      overflow: 'hidden',
      fontFamily: '"Inter", system-ui, sans-serif',
      color: '#F5F2EB',
    }}>
      {/* Ambient halo */}
      <div style={{
        position: 'absolute', left: '50%', top: '50%',
        width: 900, height: 900, marginLeft: -450, marginTop: -450,
        background: 'radial-gradient(circle, rgba(34,211,164,0.18) 0%, transparent 65%)',
        filter: 'blur(40px)',
        pointerEvents: 'none',
      }} />

      <svg viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid meet"
        style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
        <defs>
          <radialGradient id="hubGradBM" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor="#22D3A4" stopOpacity="0.9" />
            <stop offset="60%" stopColor="#22D3A4" stopOpacity="0.3" />
            <stop offset="100%" stopColor="#22D3A4" stopOpacity="0" />
          </radialGradient>
          <linearGradient id="lineGradGive" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%"  stopColor="#22D3A4" stopOpacity="0.15" />
            <stop offset="50%" stopColor="#22D3A4" stopOpacity="0.7" />
            <stop offset="100%" stopColor="#22D3A4" stopOpacity="0.15" />
          </linearGradient>
          <linearGradient id="lineGradPay" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%"  stopColor="#FF6B47" stopOpacity="0.15" />
            <stop offset="50%" stopColor="#FF6B47" stopOpacity="0.7" />
            <stop offset="100%" stopColor="#FF6B47" stopOpacity="0.15" />
          </linearGradient>
          <filter id="glowBM">
            <feGaussianBlur stdDeviation="4" result="coloredBlur" />
            <feMerge>
              <feMergeNode in="coloredBlur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>
        </defs>

        {/* Concentric rings around hub (rotating, identical to flux animation) */}
        {[120, 220, 320, 420].map((r, i) => (
          <circle key={r} cx={cx} cy={cy} r={r}
            fill="none"
            stroke="rgba(34,211,164,0.10)"
            strokeWidth="1"
            strokeDasharray={i % 2 ? '4,6' : 'none'}
            style={{
              transformOrigin: `${cx}px ${cy}px`,
              animation: `spinBM ${20 + i * 8}s linear ${i % 2 ? 'reverse' : 'normal'} infinite`,
            }}
          />
        ))}

        {/* Twin flows for each actor */}
        {actors.map((node, i) => {
          const f = computeFlow(node);
          // Pulse phases (offset between actors so they don't all blink together)
          const phaseGive = ((t * 0.4) + i * 0.2) % 1;
          const pxGive = f.aStart.x + (f.aEnd.x - f.aStart.x) * phaseGive;
          const pyGive = f.aStart.y + (f.aEnd.y - f.aStart.y) * phaseGive;

          const phasePay  = ((t * 0.4) + i * 0.2 + 0.45) % 1;
          const pxPay = f.bStart.x + (f.bEnd.x - f.bStart.x) * phasePay;
          const pyPay = f.bStart.y + (f.bEnd.y - f.bStart.y) * phasePay;

          return (
            <g key={'flow-' + node.id}>
              {/* Line A — give (green, hub → actor) */}
              <line x1={f.aStart.x} y1={f.aStart.y} x2={f.aEnd.x} y2={f.aEnd.y}
                stroke="url(#lineGradGive)" strokeWidth="1.5" />
              <circle cx={pxGive} cy={pyGive} r="4"
                fill="#22D3A4" filter="url(#glowBM)"
                opacity={0.35 + 0.65 * Math.sin(phaseGive * Math.PI)} />

              {/* Line B — pay (orange, actor → hub) */}
              <line x1={f.bStart.x} y1={f.bStart.y} x2={f.bEnd.x} y2={f.bEnd.y}
                stroke="url(#lineGradPay)" strokeWidth="1.5" />
              <circle cx={pxPay} cy={pyPay} r="4"
                fill="#FF6B47" filter="url(#glowBM)"
                opacity={0.35 + 0.65 * Math.sin(phasePay * Math.PI)} />

              {/* Flow labels (give / pay) — at midpoints, rotated to follow line */}
              <g transform={`translate(${f.midA.x}, ${f.midA.y}) rotate(${f.angle})`}>
                <text textAnchor="middle"
                  fill="#22D3A4" fontSize={fsFlow} fontWeight="600"
                  fontFamily='"JetBrains Mono", monospace' letterSpacing="1"
                  y="0">
                  {node.give}
                </text>
                <text textAnchor="middle"
                  fill="rgba(34,211,164,0.6)" fontSize={fsFlowSub}
                  fontFamily='"Inter", system-ui, sans-serif'
                  y={isMobile ? 22 : 14}>
                  {node.sub_give}
                </text>
              </g>
              <g transform={`translate(${f.midB.x}, ${f.midB.y}) rotate(${f.angle})`}>
                <text textAnchor="middle"
                  fill="#FF6B47" fontSize={fsFlow} fontWeight="600"
                  fontFamily='"JetBrains Mono", monospace' letterSpacing="1"
                  y="0">
                  {node.pay}
                </text>
                <text textAnchor="middle"
                  fill="rgba(255,107,71,0.6)" fontSize={fsFlowSub}
                  fontFamily='"Inter", system-ui, sans-serif'
                  y={isMobile ? 22 : 14}>
                  {node.sub_pay}
                </text>
              </g>
            </g>
          );
        })}

        {/* Hub (Neolia) */}
        <circle cx={cx} cy={cy} r={hubRadius} fill="url(#hubGradBM)" />
        <circle cx={cx} cy={cy} r="38"
          fill="#0B1129" stroke="#22D3A4" strokeWidth="1.5"
          filter="url(#glowBM)" />
        <circle cx={cx} cy={cy} r="14"
          fill="#22D3A4" filter="url(#glowBM)">
          <animate attributeName="r" values="14;18;14" dur="2s" repeatCount="indefinite" />
        </circle>
        <text x={cx} y={cy + (isMobile ? 84 : 60)} textAnchor="middle"
          fill="rgba(34,211,164,0.9)" fontSize={fsCore}
          fontFamily='"JetBrains Mono", monospace' letterSpacing="2">
          NEOLIA · CORE
        </text>

        {/* Actor nodes */}
        {actors.map((node, i) => {
          const pulse = 0.7 + 0.3 * Math.sin(t * 1.5 + i);
          const isAbove = node.y < cy;
          return (
            <g key={'node-' + node.id}>
              {/* Halo */}
              <circle cx={node.x} cy={node.y} r="42"
                fill="rgba(34,211,164,0.06)"
                style={{ opacity: pulse }} />
              {/* Outer ring */}
              <circle cx={node.x} cy={node.y} r="32"
                fill="none" stroke="rgba(34,211,164,0.4)" strokeWidth="1" />
              {/* Inner */}
              <circle cx={node.x} cy={node.y} r={nodeRadius}
                fill="#0B1129" stroke="#22D3A4" strokeWidth="1.5"
                filter="url(#glowBM)" />
              <circle cx={node.x} cy={node.y} r="6"
                fill="#22D3A4" filter="url(#glowBM)" />

              {/* Label block — strictly mirrors DirCFlux: title (Inter big) + sub (mono small).
                  Sub goes ABOVE the title for nodes above the hub, BELOW for nodes below. */}
              <g transform={`translate(${node.x}, ${node.y + (isAbove ? -labelOffset : labelOffset)})`}>
                <text textAnchor="middle"
                  fill="#F5F2EB" fontSize={fsLabel} fontWeight="600"
                  letterSpacing="-0.3"
                  y={isAbove ? 0 : 12}>
                  {node.title}
                </text>
                <text textAnchor="middle"
                  fill="rgba(34,211,164,0.7)" fontSize={fsSub}
                  fontFamily='"JetBrains Mono", monospace' letterSpacing="2"
                  y={isAbove ? subOffsetTop : subOffset}>
                  {node.role}
                </text>
              </g>
            </g>
          );
        })}
      </svg>

      {/* Header overlay */}
      {!bare && <div style={{
        position: 'absolute', left: 40, top: 40,
        fontFamily: '"JetBrains Mono", monospace', fontSize: 11,
        letterSpacing: '0.18em', textTransform: 'uppercase',
        color: 'rgba(34,211,164,0.9)',
        display: 'flex', alignItems: 'center', gap: 10,
      }}>
        <span style={{ width: 6, height: 6, background: '#22D3A4', borderRadius: '50%', boxShadow: '0 0 8px #22D3A4' }} />
        {i18n.overlay}
      </div>}

      {!bare && <div style={{
        position: 'absolute', right: 40, bottom: 40,
        fontFamily: '"JetBrains Mono", monospace', fontSize: 10,
        letterSpacing: '0.15em', textTransform: 'uppercase',
        color: 'rgba(245,242,235,0.4)',
      }}>
        {i18n.meta}
      </div>}

      <style>{`
        @keyframes spinBM {
          from { transform: rotate(0deg); }
          to { transform: rotate(360deg); }
        }
      `}</style>
    </div>
  );
}

window.DirBusinessModel = DirBusinessModel;
