// projects.jsx — Section 3: Bento with interactive widgets

const PROJECTS_FR = [
  {
    id: 'assurance',
    cat: 'Assurance professionnelle · Santé',
    role: 'CRM sur-mesure & applications métier',
    year: '2024 — 2026',
    desc: 'Refonte complète du CRM d’un acteur de référence en assurance professionnelle de santé : douze applications métier intégrées, prospection multi-canal automatisée, scoring commercial en temps réel.',
    tags: ['HubSpot', 'Airtable', 'CF Workers', 'TS'],
    size: 'lg',
    metrics: [
      { v: '12', k: 'apps métier' },
      { v: '4×', k: 'vélocité' },
      { v: '18 mo', k: 'engagement' },
    ],
    widget: 'pipeline',
  },
  {
    id: 'reno',
    cat: 'Rénovation énergétique',
    role: 'Plateforme d’éligibilité & cartographie',
    year: '2025',
    desc: 'Simulateur d’éligibilité MaPrimeRénov’ et cartographie clients déployés en edge.',
    tags: ['CF Workers', 'Leaflet'],
    size: 'sm',
    metrics: [{ v: '187', k: 'ms p95' }],
    widget: 'latency',
  },
  {
    id: 'tatoo',
    cat: 'Studio créatif',
    role: 'Réservation · RGPD',
    year: '2024',
    desc: 'Plateforme de prise de rendez-vous et workflow de gestion des consentements.',
    tags: ['Webflow', 'Fillout', 'CF'],
    size: 'sm',
    metrics: [{ v: '100 %', k: 'conformité' }],
    widget: 'flow',
  },
  {
    id: 'treso',
    cat: 'Pilotage financier',
    role: 'Tableau de bord de trésorerie',
    year: '2025',
    desc: 'Consolidation multi-comptes en temps réel, rapprochement bancaire automatisé, prévisionnel glissant à 90 jours.',
    tags: ['Airtable', 'Node.js', 'CF'],
    size: 'wd',
    metrics: [
      { v: '6', k: 'comptes' },
      { v: '90 j', k: 'horizon' },
      { v: '0', k: 'saisie manuelle' },
    ],
    widget: 'treasury',
  },
  {
    id: 'edu',
    cat: 'Édition · Pédagogie',
    role: 'Suivi pédagogique',
    year: '2025',
    desc: 'Application de pilotage déployée dans trois établissements : 800+ élèves.',
    tags: ['Airtable', 'CF Workers'],
    size: 'sm',
    metrics: [{ v: '824', k: 'élèves actifs' }],
    widget: 'cohort',
  },
  {
    id: 'lab',
    cat: 'Laboratoire R&D',
    role: 'Recherche & expérimentation',
    year: 'En continu',
    desc: 'Cellule interne d’exploration : agents IA, micro-outils, prototypes data.',
    tags: ['Claude API', 'Three.js'],
    size: 'sm',
    metrics: [{ v: '42', k: 'expérimentations' }],
    widget: 'lab',
  },
];

const PROJECTS_EN = [
  { ...PROJECTS_FR[0],
    cat: 'Professional insurance · Healthcare',
    role: 'Custom CRM & business apps',
    desc: 'Full CRM rebuild for a leading professional healthcare insurance provider: twelve embedded business apps, automated multi-channel prospecting, real-time commercial scoring.',
    metrics: [
      { v: '12', k: 'business apps' },
      { v: '4×', k: 'velocity' },
      { v: '18 mo', k: 'engagement' },
    ],
  },
  { ...PROJECTS_FR[1],
    cat: 'Energy retrofit',
    role: 'Eligibility & mapping platform',
    desc: 'Subsidy eligibility simulator and client mapping deployed at the edge.',
    metrics: [{ v: '187', k: 'ms p95' }],
  },
  { ...PROJECTS_FR[2],
    cat: 'Creative studio',
    role: 'Booking · GDPR',
    desc: 'Booking platform and GDPR consent workflow for a creative studio.',
    metrics: [{ v: '100 %', k: 'compliance' }],
  },
  { ...PROJECTS_FR[3],
    cat: 'Financial steering',
    role: 'Treasury dashboard',
    desc: 'Real-time multi-account consolidation, automated reconciliation, 90-day rolling forecast.',
    metrics: [
      { v: '6', k: 'accounts' },
      { v: '90 d', k: 'horizon' },
      { v: '0', k: 'manual entry' },
    ],
  },
  { ...PROJECTS_FR[4],
    cat: 'Education · Publishing',
    role: 'Student tracking',
    desc: 'Pedagogical platform across three schools: 800+ active students.',
    metrics: [{ v: '824', k: 'active students' }],
  },
  { ...PROJECTS_FR[5],
    cat: 'R&D Lab',
    role: 'Research & experimentation',
    desc: 'Internal exploration cell: AI agents, micro-tools, data prototypes.',
    metrics: [{ v: '42', k: 'experiments' }],
  },
];

/* ───────── Interactive widgets ───────── */

// Pipeline kanban — animated value ticking
function WidgetPipeline() {
  const [tick, setTick] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setTick((x) => x + 1), 2200);
    return () => clearInterval(id);
  }, []);
  const stages = [
    { k: 'Lead',         n: 142 + (tick % 6),     color: 'rgba(168,85,247,0.5)' },
    { k: 'Qualifié',     n: 87  + (tick % 4),     color: 'rgba(168,85,247,0.65)' },
    { k: 'Proposition',  n: 34  + ((tick + 1) % 3),color: 'rgba(168,85,247,0.8)' },
    { k: 'Signé',        n: 12  + ((tick + 2) % 2),color: 'rgba(168,85,247,1)' },
  ];
  const max = Math.max(...stages.map(s => s.n));
  return (
    <div className="wg wg-pipeline">
      <div className="wg-head">
        <span className="mono small dim">PIPELINE · LIVE</span>
        <span className="mono small accent"><span className="wg-dot"></span> sync 2 s</span>
      </div>
      <div className="wg-pipe">
        {stages.map((s, i) => (
          <div key={i} className="wg-pipe-col">
            <div className="wg-pipe-bar" style={{ height: `${(s.n / max) * 100}%`, background: s.color }}>
              <span className="wg-pipe-n">{s.n}</span>
            </div>
            <span className="wg-pipe-k mono">{s.k}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// Latency — live world map dots pulsing + p95 ticker
function WidgetLatency() {
  const [v, setV] = React.useState(187);
  React.useEffect(() => {
    const id = setInterval(() => setV(160 + Math.floor(Math.random() * 40)), 1500);
    return () => clearInterval(id);
  }, []);
  const dots = [
    { x: 28, y: 38 }, { x: 50, y: 32 }, { x: 72, y: 45 },
    { x: 38, y: 60 }, { x: 60, y: 55 }, { x: 80, y: 65 },
  ];
  return (
    <div className="wg wg-latency">
      <svg className="wg-map" viewBox="0 0 100 80" preserveAspectRatio="none">
        <g stroke="rgba(255,255,255,0.06)" strokeWidth="0.3" fill="none">
          {[...Array(8)].map((_, i) => <line key={`h${i}`} x1="0" y1={i * 10} x2="100" y2={i * 10} />)}
          {[...Array(11)].map((_, i) => <line key={`v${i}`} x1={i * 10} y1="0" x2={i * 10} y2="80" />)}
        </g>
        {dots.map((d, i) => (
          <g key={i}>
            <circle cx={d.x} cy={d.y} r="1.2" fill="#a855f7" />
            <circle cx={d.x} cy={d.y} r="1.2" fill="none" stroke="#a855f7" strokeWidth="0.4" opacity="0.6">
              <animate attributeName="r" from="1.2" to="6" dur="2s" begin={`${i * 0.3}s`} repeatCount="indefinite" />
              <animate attributeName="opacity" from="0.6" to="0" dur="2s" begin={`${i * 0.3}s`} repeatCount="indefinite" />
            </circle>
          </g>
        ))}
      </svg>
      <div className="wg-lat-bar">
        <span className="mono small dim">EDGE · p95</span>
        <span className="wg-lat-v">{v}<span className="mono small dim">ms</span></span>
      </div>
    </div>
  );
}

// Flow — animated DAG
function WidgetFlow() {
  return (
    <div className="wg wg-flow">
      <svg className="wg-flow-svg" viewBox="0 0 200 120" preserveAspectRatio="xMidYMid meet">
        <g fill="none" stroke="rgba(168,85,247,0.5)" strokeWidth="1">
          <rect x="10" y="20" width="44" height="20" rx="3" />
          <rect x="78" y="20" width="44" height="20" rx="3" />
          <rect x="146" y="20" width="44" height="20" rx="3" />
          <rect x="44" y="80" width="44" height="20" rx="3" />
          <rect x="112" y="80" width="44" height="20" rx="3" />
          <path d="M32,40 L66,80" />
          <path d="M100,40 L66,80" />
          <path d="M100,40 L134,80" />
          <path d="M168,40 L134,80" />
        </g>
        <g fill="rgba(255,255,255,0.85)" fontSize="6" fontFamily="Geist Mono">
          <text x="32" y="33" textAnchor="middle">Form</text>
          <text x="100" y="33" textAnchor="middle">RGPD</text>
          <text x="168" y="33" textAnchor="middle">Mail</text>
          <text x="66" y="93" textAnchor="middle">CRM</text>
          <text x="134" y="93" textAnchor="middle">Slot</text>
        </g>
        <circle r="1.8" fill="#a855f7">
          <animateMotion dur="3s" repeatCount="indefinite" path="M32,40 L66,80" />
        </circle>
        <circle r="1.8" fill="#a855f7">
          <animateMotion dur="3.6s" begin="0.5s" repeatCount="indefinite" path="M100,40 L134,80" />
        </circle>
        <circle r="1.8" fill="#a855f7">
          <animateMotion dur="4s" begin="1s" repeatCount="indefinite" path="M168,40 L134,80" />
        </circle>
      </svg>
    </div>
  );
}

// Treasury — sparkline + scrubbing labels (interactive on hover)
function WidgetTreasury() {
  const ref = React.useRef(null);
  const [hover, setHover] = React.useState(null);
  const pts = [40, 55, 42, 68, 50, 72, 60, 82, 72, 88, 70, 95, 84, 92, 88, 102, 96, 110];
  const months = ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D', 'J', 'F', 'M', 'A', 'M', 'J'];
  const max = Math.max(...pts), min = Math.min(...pts);
  const w = 600, h = 110;
  const path = pts.map((p, i) => {
    const x = (i / (pts.length - 1)) * w;
    const y = h - ((p - min) / (max - min)) * (h - 16) - 8;
    return `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(' ');
  const area = `${path} L${w},${h} L0,${h} Z`;

  const onMove = (e) => {
    const r = ref.current.getBoundingClientRect();
    const x = (e.clientX - r.left) / r.width;
    const idx = Math.max(0, Math.min(pts.length - 1, Math.round(x * (pts.length - 1))));
    setHover(idx);
  };

  const idx = hover ?? pts.length - 1;
  const px = (idx / (pts.length - 1)) * 100;

  return (
    <div className="wg wg-treasury" ref={ref}
         onMouseMove={onMove}
         onMouseLeave={() => setHover(null)}>
      <svg className="wg-tr-svg" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
        <defs>
          <linearGradient id="tr-g" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="rgba(168,85,247,0.4)" />
            <stop offset="100%" stopColor="rgba(168,85,247,0)" />
          </linearGradient>
        </defs>
        <path d={area} fill="url(#tr-g)" />
        <path d={path} fill="none" stroke="#a855f7" strokeWidth="1.6"
              strokeLinecap="round" strokeLinejoin="round" />
      </svg>
      <span className="wg-tr-cursor" style={{ left: `${px}%` }}></span>
      <div className="wg-tr-tooltip" style={{ left: `${px}%` }}>
        <span className="mono small dim">{months[idx]}</span>
        <span className="wg-tr-v">{(pts[idx] * 1.2).toFixed(0)} k€</span>
      </div>
    </div>
  );
}

// Cohort — live activity grid
function WidgetCohort() {
  const cols = 18, rows = 6;
  const [seed, setSeed] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setSeed((s) => s + 1), 2400);
    return () => clearInterval(id);
  }, []);
  return (
    <div className="wg wg-cohort">
      <svg className="wg-cohort-svg" viewBox="0 0 200 60" preserveAspectRatio="xMidYMid meet">
        {[...Array(rows)].map((_, r) =>
          [...Array(cols)].map((_, c) => {
            const i = r * cols + c;
            const live = ((i * 37 + seed * 13) % 100) < 32;
            return (
              <rect key={i}
                    x={4 + c * 10.5} y={4 + r * 9}
                    width="6" height="5" rx="1"
                    fill={live ? '#a855f7' : 'rgba(255,255,255,0.12)'}>
                <animate attributeName="opacity"
                         values="0.4;1;0.4" dur="3s"
                         begin={`${(i % 7) * 0.2}s`}
                         repeatCount="indefinite" />
              </rect>
            );
          })
        )}
      </svg>
    </div>
  );
}

// Lab — orbital experiments + counter
function WidgetLab() {
  return (
    <div className="wg wg-lab">
      <svg className="wg-lab-svg" viewBox="0 0 200 120" preserveAspectRatio="xMidYMid meet">
        <g fill="none" stroke="rgba(255,255,255,0.18)" strokeWidth="0.6">
          <ellipse cx="100" cy="60" rx="80" ry="20" />
          <ellipse cx="100" cy="60" rx="50" ry="40" />
          <ellipse cx="100" cy="60" rx="20" ry="50" />
        </g>
        <circle cx="100" cy="60" r="5" fill="#a855f7" />
        <circle cx="100" cy="60" r="9" fill="none" stroke="rgba(168,85,247,0.4)" strokeWidth="0.6">
          <animate attributeName="r" values="9;14;9" dur="3s" repeatCount="indefinite" />
        </circle>
        <circle r="2" fill="#a855f7">
          <animateMotion dur="6s" repeatCount="indefinite" path="M180,60 a80,20 0 1,1 -160,0 a80,20 0 1,1 160,0" />
        </circle>
        <circle r="1.5" fill="#fff" opacity="0.7">
          <animateMotion dur="9s" repeatCount="indefinite" path="M150,60 a50,40 0 1,0 -100,0 a50,40 0 1,0 100,0" />
        </circle>
      </svg>
    </div>
  );
}

const WIDGETS = {
  pipeline: WidgetPipeline,
  latency: WidgetLatency,
  flow: WidgetFlow,
  treasury: WidgetTreasury,
  cohort: WidgetCohort,
  lab: WidgetLab,
};

/* ───────── Card ───────── */

function MagicCard({ p, idx, ctaLabel }) {
  const ref = React.useRef(null);
  const [hovered, setHovered] = React.useState(false);
  const Widget = WIDGETS[p.widget];
  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    el.style.setProperty('--mx', `${e.clientX - r.left}px`);
    el.style.setProperty('--my', `${e.clientY - r.top}px`);
  };
  const num = String(idx + 1).padStart(2, '0');
  return (
    <article ref={ref}
             className={`pj pj-${p.size} ${hovered ? 'is-hover' : ''}`}
             data-magnet
             onMouseMove={onMove}
             onMouseEnter={() => setHovered(true)}
             onMouseLeave={() => setHovered(false)}
             style={{ animationDelay: `${0.1 + idx * 0.08}s` }}>
      <div className="pj-glow"></div>

      <header className="pj-h">
        <span className="mono small dim">{num} · SECTEUR</span>
        <span className="mono small dim">{p.year}</span>
      </header>

      <div className="pj-body">
        <span className="mono pj-cat">{p.cat}</span>
        <h3 className="pj-name">{p.role}</h3>
        <p className="pj-desc">{p.desc}</p>

        {Widget && (
          <div className="pj-widget">
            <Widget />
          </div>
        )}

        {p.metrics && (
          <div className="pj-metrics">
            {p.metrics.map((m, i) => (
              <div key={i} className="pj-metric">
                <span className="pj-metric-v">{m.v}</span>
                <span className="pj-metric-k mono">{m.k}</span>
              </div>
            ))}
          </div>
        )}
      </div>

      <footer className="pj-f">
        <div className="pj-tags">
          {p.tags.map((t) => (
            <span key={t} className="pj-tag mono">{t}</span>
          ))}
        </div>
        <span className="pj-cta mono" aria-hidden="true">
          {ctaLabel}
          <svg width="11" height="11" viewBox="0 0 11 11">
            <path d="M2 9 L9 2 M9 2 H4 M9 2 V7" fill="none" stroke="currentColor" strokeWidth="1.2" />
          </svg>
        </span>
      </footer>
    </article>
  );
}

function Projects() {
  const { t: T, lang } = useT();
  const data = lang === 'en' ? PROJECTS_EN : PROJECTS_FR;
  return (
    <section id="travaux" className="projects" data-screen-label="03 Travaux" data-reveal="up">
      <div className="pj-head">
        <span className="mono small dim">{T('pj.label')}</span>
        <h2 className="pj-eyebrow">
          {T('pj.title.a')}<em className="serif">{T('pj.title.b')}</em>
        </h2>
        <p className="pj-intro">{T('pj.intro')}</p>
      </div>

      <div className="pj-bento">
        {data.map((p, i) => <MagicCard key={p.id} p={p} idx={i} ctaLabel={T('pj.cta')} />)}
      </div>
    </section>
  );
}

window.Projects = Projects;
