/* global React, Badge, Btn, Dot, Icon, RefChip, Sigil, fmtInt, fmtEur */
// DimensionnementPage — 8 types d'étude CEE (BAT-TH + IND-UT)
// Règle 2  : tous les champs recalculent live via useMemo
// Règle 3.a: ClientPicker obligatoire, upsert Opportunity via CRM
// Règle 4  : équipements par paliers constructeur (catalogue réel)
// Règle 5  : CRUD complet (create + push CRM + PDF)
// Règle 6  : onglet Paramètres (taux CEE, zone par défaut, templates)

const { useState: _dUseS, useEffect: _dUseE, useRef: _dUseR, useMemo: _dUseM } = React;

const TAUX = 7.5; // €/MWh cumac

// ── Types d'étude ────────────────────────────────────────────────────────────
const DIM_TYPES = [
  { val: 'rec',       label: '♻️ Récupération de chaleur',     sub: 'BAT-TH-139', group: 'Tertiaire — Froid / CVC', tone: 'signal' },
  { val: 'hp',        label: '🔧 HP + BP flottante',           sub: 'BAT-TH-134 + 145', group: 'Tertiaire — Froid / CVC', tone: 'signal' },
  { val: 'pac_aireau',label: '🌡️ PAC Air/Eau tertiaire',       sub: 'BAT-TH-113', group: 'Tertiaire — Froid / CVC', tone: 'plasma' },
  { val: 'pac_ailair',label: '❄️ PAC Air/Air (VRF/split)',     sub: 'BAT-TH-129', group: 'Tertiaire — Froid / CVC', tone: 'plasma' },
  { val: 'destrat',   label: '🌀 Déstratification / Brassage', sub: 'BAT-TH-142', group: 'Tertiaire — Froid / CVC', tone: 'copper' },
  { val: 'gtb',       label: '🖥️ GTB / GTC',                  sub: 'BAT-TH-116', group: 'Tertiaire — Froid / CVC', tone: 'signal' },
  { val: 'ind_rec',   label: '🏭 Récupération chaleur industrielle', sub: 'IND-UT-102', group: 'Industriel', tone: 'rouge' },
  { val: 'ind_iso',   label: '🔥 Isolation réseau vapeur/condensat', sub: 'IND-UT-115', group: 'Industriel', tone: 'copper' },
];

// ── Équipements constructeurs par type (règle 4) ─────────────────────────────
const EQUIP_CATALOG = {
  rec: [
    { name: 'BOOSTHERM BTH-P1000', desc: 'Récupération condenseur · 1000 L ECS · Rexel', price: '~8 500 €', tone: 'signal' },
    { name: 'Échangeur ALFA LAVAL M15', desc: 'DN40 · 70-100 kW · Thermcross', price: '~1 200 €', tone: 'plasma' },
    { name: 'Régulateur CAREL pRCHECK', desc: 'Supervision récupération · 0-10V', price: '~850 €', tone: 'copper' },
  ],
  hp: [
    { name: 'Régulateur CAREL HP+BP — μRack', desc: 'HP+BP intégré · CAREL/Clauger', price: '~2 800 €', tone: 'signal' },
    { name: 'Sonde température extérieure Pt100', desc: 'NTC ou Pt100 · Rexel', price: '~45 €', tone: 'plasma' },
    { name: 'Transducteur pression HP/BP', desc: '0-10V · RS-Online', price: '~120 €/u', tone: 'copper' },
  ],
  pac_aireau: [
    { name: 'Daikin EWAQ050B', desc: '50 kW · COP 3,2 · R410A', price: '~18 000 €', tone: 'signal' },
    { name: 'Atlantic CALYPSO 40', desc: '40 kW · COP 3,5 · R32', price: '~16 500 €', tone: 'plasma' },
    { name: 'Mitsubishi Heavy SRC-KX50ZRX', desc: '50 kW · COP 3,8 · Inverter', price: '~19 000 €', tone: 'copper' },
  ],
  pac_ailair: [
    { name: 'Daikin VRV 4 — RXYQ30T7Y1B', desc: '30 kW · EER 3,3 · 5-10 unités', price: '~22 000 €', tone: 'signal' },
    { name: 'Mitsubishi City Multi PUHY-P250', desc: '25 kW · R2 · EER 3,5', price: '~19 000 €', tone: 'plasma' },
    { name: 'Hitachi Set Free FX2', desc: '28 kW · EER 3,8 · R32', price: '~21 000 €', tone: 'copper' },
  ],
  destrat: [
    { name: 'AIRIUS AireShare 60T', desc: 'Brasseur pendulaire · portée 9 m', price: '~320 €/u', tone: 'signal' },
    { name: 'Delta Fan HCT 560/6/22', desc: 'Grande hauteur · EC · RS-Online', price: '~480 €/u', tone: 'plasma' },
    { name: 'Contrôleur multi-brasseurs', desc: 'Programmable horaire · Thermcross', price: '~180 €', tone: 'copper' },
  ],
  gtb: [
    { name: 'Schneider EcoStruxure Building', desc: 'GTB Classe A · BACnet/IP · IoT', price: 'Sur devis', tone: 'signal' },
    { name: 'Siemens Desigo CC', desc: 'GTB Classe A/B · Multiprotocole', price: 'Sur devis', tone: 'plasma' },
    { name: 'Honeywell TREND IQ4', desc: 'GTB Classe B · LON/BACnet', price: 'Sur devis', tone: 'copper' },
  ],
  ind_rec: [
    { name: 'Alfa Laval AlfaFlash', desc: 'Échangeur fumées · 100-500 kW', price: 'Sur devis', tone: 'signal' },
    { name: 'THERMCO ENERSAVE', desc: 'Récupération gaz chauds · Clé en main', price: 'Sur devis', tone: 'plasma' },
  ],
  ind_iso: [
    { name: 'Laine de roche Rockwool 800', desc: 'λ=0,036 · Tmax 850°C · Coquilles', price: '~45 €/ml', tone: 'signal' },
    { name: 'Mousse élastomère Armaflex', desc: 'λ=0,040 · 40 mm · Pose facile', price: '~38 €/ml', tone: 'plasma' },
  ],
};

// ── Formules CEE ─────────────────────────────────────────────────────────────

function calcREC(p) {
  const { pw3, dur, dest, zone } = p;
  const kf = { H1: 1, H2: 0.9, H3: 0.8 }[zone] || 1;
  const km = { ecs: 9.9, hrc: 21800, com: 11700, bur: 14300 };
  const vol = dest === 'ecs'
    ? Math.round(pw3 * dur * 9.9 * kf)
    : Math.round(pw3 * (km[dest] || 9900) * kf);
  const prime = vol * TAUX / 1000;
  const energie = Math.round(pw3 * dur / 1000);
  return { vol, prime, energie, label: 'BAT-TH-139' };
}

function calcHP(p) {
  const { pwEl, type, usage, zone } = p;
  const bHP = { clim: { H1: 4600, H2: 3700, H3: 2500 }, dc: { H1: 6700, H2: 5400, H3: 3600 }, autres: { H1: 20000, H2: 16000, H3: 10800 } };
  const bBP = { clim: { H1: 310, H2: 250, H3: 170 }, dc: { H1: 560, H2: 450, H3: 300 }, autres: { H1: 1700, H2: 1360, H3: 920 } };
  const vHP = type === 'bp' ? 0 : Math.round(pwEl * ((bHP[usage] || bHP.clim)[zone] || 4600));
  const vBP = type === 'hp' ? 0 : Math.round(pwEl * ((bBP[usage] || bBP.clim)[zone] || 310));
  const vol = vHP + vBP;
  const prime = vol * TAUX / 1000;
  return { vol, vHP, vBP, prime, energie: null, label: type === 'both' ? 'BAT-TH-134 + 145' : type === 'hp' ? 'BAT-TH-134' : 'BAT-TH-145' };
}

function calcPAC(p) {
  const { pw, cop, zone } = p;
  const dju = { H1: 2400, H2: 1800, H3: 1200 }[zone] || 2400;
  const scop = cop * 0.9;
  const duree = 20;
  const vol = Math.round(pw * dju * duree * 3.6 * (1 - 1 / scop) / 3.6);
  const prime = vol * TAUX / 1000;
  const eco = Math.round(pw * dju / 1000 / scop * 0.2276 * 1000) / 1000 * 1000;
  return { vol, prime, energie: eco, scop: scop.toFixed(1), label: 'BAT-TH-113' };
}

function calcPAI(p) {
  const { pw, eer, zone } = p;
  const kf = { H1: 1, H2: 0.9, H3: 0.75 }[zone] || 1;
  const hRefroid = 800, seer = eer * 1.1, duree = 15;
  const vol = Math.round(pw * hRefroid * duree * (1 - 1 / seer) * kf);
  const prime = vol * TAUX / 1000;
  return { vol, prime, energie: null, label: 'BAT-TH-129' };
}

function calcDS(p) {
  const { hsp, surf, zone } = p;
  const kf = { H1: 1, H2: 0.9, H3: 0.7 }[zone] || 1;
  const volM3 = Math.round(surf * hsp);
  const nb = Math.max(1, Math.ceil(surf / 100));
  const vol = Math.round(volM3 * 0.8 * (hsp > 6 ? 1.4 : 1) * kf);
  const prime = vol * TAUX / 1000;
  return { vol, prime, energie: null, volM3, nb, label: 'BAT-TH-142' };
}

function calcGTB(p) {
  const { surf, cl, zone } = p;
  const m = { A: 1900, B: 1400, C: 800 }[cl] || 1400;
  const mu = { A: 2, B: 1.5, C: 1 }[cl] || 1.5;
  const kf = { H1: 1, H2: 0.9, H3: 0.8 }[zone] || 1;
  const vol = Math.round(surf * m * mu * kf);
  const prime = vol * TAUX / 1000;
  return { vol, prime, energie: null, label: 'BAT-TH-116' };
}

function calcINDRec(p) {
  const { debit, tin, tout, rend, heures } = p;
  const rho = 1.1, cp = 1.05;
  const pw = Math.round(debit / 3600 * rho * cp * (tin - tout) * rend / 100);
  const energie = Math.round(pw * heures / 1000);
  const vol = Math.round(energie * 1000 * 15);
  const prime = vol * TAUX / 1000;
  return { vol, prime, energie, pw, label: 'IND-UT-102' };
}

function calcISO(p) {
  const { long, dn, temp, fluide } = p;
  const r1 = dn / 2000, r2 = r1 + 0.06, lambda = 0.036, deltaT = temp - 20;
  const pwPerMetre = Math.round(2 * Math.PI * lambda * deltaT / Math.log(r2 / r1));
  const pwTotal = Math.round(pwPerMetre * long / 1000);
  const energie = Math.round(pwTotal * 8760 / 1000);
  const kf = { vap: 1.3, cond: 1.1, eau: 1.0 }[fluide] || 1;
  const vol = Math.round(energie * 1000 * 15 * kf);
  const prime = vol * TAUX / 1000;
  const eco = Math.round(energie * 0.08 * 1000) / 10;
  return { vol, prime, energie: eco, pw: pwTotal, label: 'IND-UT-115' };
}

// ── Main page ─────────────────────────────────────────────────────────────────

function DimensionnementPage() {
  const [tab, setTab] = _dUseS('study');      // study | config
  const [type, setType] = _dUseS('rec');

  const typeMeta = DIM_TYPES.find(t => t.val === type) || DIM_TYPES[0];

  return (
    <div style={{ padding: '20px 24px 40px' }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'flex-end', gap: 16, marginBottom: 18 }}>
        <div>
          <div style={{ fontSize: 11, color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: 0.8, fontWeight: 600 }}>CEE Tertiaire · Industriel</div>
          <h1 style={{ fontSize: 26, fontWeight: 600, letterSpacing: '-0.02em', margin: '4px 0 0' }}>Dimensionnement</h1>
          <div style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 4 }}>PAC · HP/BP flottante · Récupération chaleur · Déstratification · GTB · Industriel · PVGIS. Calcul kWhc live · PDF signable · push CRM.</div>
        </div>
        <span style={{ flex: 1 }}/>
        <Btn variant="outline" size="sm" onClick={() => setTab(t => t === 'config' ? 'study' : 'config')}>
          {tab === 'config' ? '← Étude' : '⚙️ Paramètres'}
        </Btn>
      </div>

      {tab === 'config' && <DimConfig />}
      {tab === 'study' && (
        <div style={{ display: 'grid', gap: 16 }}>
          {/* Type selector */}
          <TypeSelector value={type} onChange={setType}/>

          {/* Study body */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 340px', gap: 16 }}>
            <StudyPanel type={type}/>
            <SidePanel type={type} meta={typeMeta}/>
          </div>
        </div>
      )}
    </div>
  );
}

// ── Type selector ─────────────────────────────────────────────────────────────

function TypeSelector({ value, onChange }) {
  const groups = {};
  DIM_TYPES.forEach(t => {
    if (!groups[t.group]) groups[t.group] = [];
    groups[t.group].push(t);
  });
  return (
    <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 14 }}>
      <div style={{ fontSize: 10, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-4)', marginBottom: 10 }}>Type d'étude CEE</div>
      {Object.entries(groups).map(([group, types]) => (
        <div key={group} style={{ marginBottom: 12 }}>
          <div style={{ fontSize: 10, color: 'var(--ink-5)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6 }}>{group}</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {types.map(t => (
              <button key={t.val} onClick={() => onChange(t.val)} style={{
                padding: '7px 13px', fontSize: 12, fontWeight: 500, borderRadius: 5, cursor: 'pointer',
                background: value === t.val ? 'var(--ink)' : 'var(--paper-2)',
                color: value === t.val ? 'var(--paper)' : 'var(--ink-2)',
                border: value === t.val ? '1px solid var(--ink)' : '1px solid var(--line-2)',
                display: 'flex', alignItems: 'center', gap: 6,
              }}>
                <span>{t.label}</span>
                <Badge tone={value === t.val ? 'neutral' : t.tone} style={{ fontSize: 9 }}>{t.sub}</Badge>
              </button>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

// ── Study panel (left) ────────────────────────────────────────────────────────

function StudyPanel({ type }) {
  switch (type) {
    case 'rec':       return <RECForm />;
    case 'hp':        return <HPForm />;
    case 'pac_aireau':return <PACForm />;
    case 'pac_ailair':return <PAIForm />;
    case 'destrat':   return <DSForm />;
    case 'gtb':       return <GTBForm />;
    case 'ind_rec':   return <INDRecForm />;
    case 'ind_iso':   return <ISOForm />;
    default:          return null;
  }
}

// ── Generic form helpers ──────────────────────────────────────────────────────

function DimLabel({ children }) {
  return <div style={{ fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-4)', marginBottom: 4 }}>{children}</div>;
}

function DimInput({ label, value, onChange, type = 'number', step, min, children }) {
  return (
    <div>
      <DimLabel>{label}</DimLabel>
      {children || (
        <input type={type} value={value} step={step} min={min}
          onChange={e => onChange(type === 'number' ? parseFloat(e.target.value) || 0 : e.target.value)}
          style={{ width: '100%', padding: '7px 10px', fontSize: 12, border: '1px solid var(--line-2)', borderRadius: 5, background: 'var(--paper)', color: 'var(--ink)', fontFamily: 'inherit', boxSizing: 'border-box' }}/>
      )}
    </div>
  );
}

function DimSelect({ label, value, onChange, options }) {
  return (
    <div>
      <DimLabel>{label}</DimLabel>
      <select value={value} onChange={e => onChange(e.target.value)}
        style={{ width: '100%', padding: '7px 10px', fontSize: 12, border: '1px solid var(--line-2)', borderRadius: 5, background: 'var(--paper)', color: 'var(--ink)', fontFamily: 'inherit', boxSizing: 'border-box' }}>
        {options.map(o => <option key={o.val} value={o.val}>{o.label}</option>)}
      </select>
    </div>
  );
}

const ZONES = [{ val: 'H1', label: 'H1 — Froid' }, { val: 'H2', label: 'H2 — Tempéré' }, { val: 'H3', label: 'H3 — Chaud' }];

function ResultBox({ result, extra }) {
  if (!result) return null;
  return (
    <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 14, marginTop: 16 }}>
      <div style={{ fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-4)', marginBottom: 12, display: 'flex', alignItems: 'center', gap: 8 }}>
        <Dot tone="signal" size={6}/>
        Résultat {result.label}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))', gap: 10 }}>
        <KPI label="Volume CEE" value={result.vol != null ? fmtInt(result.vol) + ' kWhc' : '—'} tone="signal" big/>
        <KPI label="Prime estimée" value={result.prime != null ? fmtEur(result.prime) : '—'} tone="amber" big/>
        {extra}
      </div>
    </div>
  );
}

function KPI({ label, value, tone, big }) {
  return (
    <div style={{ padding: '10px 12px', background: 'var(--paper-2)', borderRadius: 5, border: '1px solid var(--hairline)' }}>
      <div style={{ fontSize: 9, color: 'var(--ink-5)', textTransform: 'uppercase', letterSpacing: 0.4, fontWeight: 600, marginBottom: 5 }}>{label}</div>
      <div className="mono" style={{ fontSize: big ? 16 : 13, fontWeight: 700, color: tone ? `var(--${tone === 'amber' ? 'copper' : tone}-deep, var(--${tone}))` : 'var(--ink)' }}>{value}</div>
    </div>
  );
}

function FormCard({ title, color, children }) {
  return (
    <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 16 }}>
      <div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: color || 'var(--ink-3)', marginBottom: 14 }}>{title}</div>
      <div style={{ display: 'grid', gap: 12 }}>{children}</div>
    </div>
  );
}

// ── Récupération de chaleur (BAT-TH-139) ─────────────────────────────────────

function RECForm() {
  const [pw3,   setPw3]   = _dUseS(70);
  const [dur,   setDur]   = _dUseS(4000);
  const [dest,  setDest]  = _dUseS('ecs');
  const [zone,  setZone]  = _dUseS('H1');

  const result = _dUseM(() => calcREC({ pw3, dur, dest, zone }), [pw3, dur, dest, zone]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — Récupération chaleur" color="var(--signal-deep)">
        <DimInput label="Puissance système récupération (kW)" value={pw3} onChange={setPw3}/>
        <DimInput label="Durée fonctionnement (h/an)" value={dur} onChange={setDur}/>
        <DimSelect label="Destination chaleur" value={dest} onChange={setDest} options={[
          { val: 'ecs', label: 'ECS' },
          { val: 'hrc', label: 'Hôtellerie / Restauration' },
          { val: 'com', label: 'Commerce' },
          { val: 'bur', label: 'Bureaux' },
        ]}/>
        <DimSelect label="Zone climatique" value={zone} onChange={setZone} options={ZONES}/>
        <ResultBox result={result} extra={<KPI label="Énergie/an" value={result ? Math.round(result.energie) + ' MWh' : '—'}/>}/>
      </FormCard>
      <EquipList type="rec"/>
    </div>
  );
}

// ── HP / BP flottante (BAT-TH-134 + 145) ─────────────────────────────────────

function HPForm() {
  const [pwEl,  setPwEl]  = _dUseS(77.4);
  const [type,  setType]  = _dUseS('both');
  const [usage, setUsage] = _dUseS('clim');
  const [zone,  setZone]  = _dUseS('H1');

  const result = _dUseM(() => calcHP({ pwEl, type, usage, zone }), [pwEl, type, usage, zone]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — HP/BP flottante" color="var(--signal-deep)">
        <DimInput label="Puissance élec. nominale totale (kW)" value={pwEl} onChange={setPwEl} step="0.1"/>
        <DimSelect label="Type de régulation" value={type} onChange={setType} options={[
          { val: 'hp',   label: 'HP flottante seule (BAT-TH-134)' },
          { val: 'bp',   label: 'BP flottante seule (BAT-TH-145)' },
          { val: 'both', label: 'HP + BP cumulées (134 + 145)' },
        ]}/>
        <DimSelect label="Usage" value={usage} onChange={setUsage} options={[
          { val: 'clim',   label: 'Climatisation confort' },
          { val: 'dc',     label: 'Data center' },
          { val: 'autres', label: 'Réfrigération' },
        ]}/>
        <DimSelect label="Zone climatique" value={zone} onChange={setZone} options={ZONES}/>
        {result && (
          <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 14 }}>
            <div style={{ fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-4)', marginBottom: 10, display: 'flex', gap: 8 }}>
              <Dot tone="signal" size={6}/> Résultat {result.label}
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
              {type !== 'bp' && (
                <div>
                  <div style={{ fontSize: 9, color: 'var(--ink-5)', textTransform: 'uppercase' }}>BAT-TH-134 (HP)</div>
                  <div className="mono" style={{ fontSize: 15, fontWeight: 700, color: 'var(--signal-deep)' }}>{fmtInt(result.vHP)} kWhc</div>
                  <div className="mono" style={{ fontSize: 11, color: 'var(--copper)' }}>{fmtEur(result.vHP * TAUX / 1000)}</div>
                </div>
              )}
              {type !== 'hp' && (
                <div>
                  <div style={{ fontSize: 9, color: 'var(--ink-5)', textTransform: 'uppercase' }}>BAT-TH-145 (BP)</div>
                  <div className="mono" style={{ fontSize: 15, fontWeight: 700, color: 'var(--plasma)' }}>{fmtInt(result.vBP)} kWhc</div>
                  <div className="mono" style={{ fontSize: 11, color: 'var(--copper)' }}>{fmtEur(result.vBP * TAUX / 1000)}</div>
                </div>
              )}
            </div>
            <div style={{ marginTop: 10, padding: 10, background: 'var(--signal-tint)', borderRadius: 5, display: 'flex', gap: 16 }}>
              <div>
                <div style={{ fontSize: 9, color: 'var(--ink-4)', textTransform: 'uppercase' }}>Total cumulé</div>
                <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: 'var(--signal-deep)' }}>{fmtInt(result.vol)} kWhc</div>
              </div>
              <div>
                <div style={{ fontSize: 9, color: 'var(--ink-4)', textTransform: 'uppercase' }}>Prime totale</div>
                <div className="mono" style={{ fontSize: 14, fontWeight: 700, color: 'var(--copper)' }}>{fmtEur(result.prime)}</div>
              </div>
            </div>
          </div>
        )}
      </FormCard>
      <EquipList type="hp"/>
    </div>
  );
}

// ── PAC Air/Eau (BAT-TH-113) ─────────────────────────────────────────────────

function PACForm() {
  const [pw,   setPw]   = _dUseS(50);
  const [cop,  setCop]  = _dUseS(3.4);
  const [surf, setSurf] = _dUseS(1500);
  const [zone, setZone] = _dUseS('H1');

  const result = _dUseM(() => calcPAC({ pw, cop, zone }), [pw, cop, zone]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — PAC Air/Eau" color="var(--plasma)">
        <DimInput label="Puissance nominale PAC (kWth)" value={pw} onChange={setPw}/>
        <DimInput label="COP (Coefficient de Performance)" value={cop} onChange={setCop} step="0.1"/>
        <DimInput label="Surface chauffée (m²)" value={surf} onChange={setSurf}/>
        <DimSelect label="Zone climatique" value={zone} onChange={setZone} options={ZONES}/>
        {result && (
          <ResultBox result={result} extra={<>
            <KPI label="Économies/an" value={fmtEur(result.energie || 0)}/>
            <KPI label="SCOP estimé" value={result.scop}/>
          </>}/>
        )}
      </FormCard>
      <EquipList type="pac_aireau"/>
    </div>
  );
}

// ── PAC Air/Air (BAT-TH-129) ─────────────────────────────────────────────────

function PAIForm() {
  const [pw,   setPw]   = _dUseS(30);
  const [eer,  setEer]  = _dUseS(3.5);
  const [nb,   setNb]   = _dUseS(5);
  const [zone, setZone] = _dUseS('H1');

  const result = _dUseM(() => calcPAI({ pw, eer, zone }), [pw, eer, zone]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — PAC Air/Air (VRF/Split)" color="var(--plasma)">
        <DimInput label="Puissance frigorifique totale (kW)" value={pw} onChange={setPw}/>
        <DimInput label="EER (Energy Efficiency Ratio)" value={eer} onChange={setEer} step="0.1"/>
        <DimInput label="Nb unités intérieures" value={nb} onChange={setNb} min="1"/>
        <DimSelect label="Zone climatique" value={zone} onChange={setZone} options={ZONES}/>
        {result && <ResultBox result={result}/>}
      </FormCard>
      <EquipList type="pac_ailair"/>
    </div>
  );
}

// ── Déstratification (BAT-TH-142) ────────────────────────────────────────────

function DSForm() {
  const [hsp,  setHsp]  = _dUseS(8);
  const [surf, setSurf] = _dUseS(500);
  const [heat, setHeat] = _dUseS('air');
  const [zone, setZone] = _dUseS('H1');

  const result = _dUseM(() => calcDS({ hsp, surf, zone }), [hsp, surf, zone]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — Déstratification" color="var(--copper)">
        <DimInput label="Hauteur sous plafond (m)" value={hsp} onChange={setHsp} step="0.5"/>
        <DimInput label="Surface au sol (m²)" value={surf} onChange={setSurf}/>
        <DimSelect label="Chauffage existant" value={heat} onChange={setHeat} options={[
          { val: 'air', label: 'Air chaud (aérotherme)' },
          { val: 'ray', label: 'Radiant (IR)' },
          { val: 'sol', label: 'Sol chauffant' },
        ]}/>
        <DimSelect label="Zone climatique" value={zone} onChange={setZone} options={ZONES}/>
        {result && (
          <ResultBox result={result} extra={<>
            <KPI label="Volume local" value={result.volM3 != null ? fmtInt(result.volM3) + ' m³' : '—'}/>
            <KPI label="Nb appareils" value={result.nb != null ? result.nb + ' app.' : '—'}/>
          </>}/>
        )}
      </FormCard>
      <EquipList type="destrat"/>
    </div>
  );
}

// ── GTB (BAT-TH-116) ─────────────────────────────────────────────────────────

function GTBForm() {
  const [surf, setSurf] = _dUseS(850);
  const [cl,   setCl]   = _dUseS('B');
  const [zone, setZone] = _dUseS('H1');

  const result = _dUseM(() => calcGTB({ surf, cl, zone }), [surf, cl, zone]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — GTB / GTC (BAT-TH-116)" color="var(--signal-deep)">
        <DimInput label="Surface tertiaire (m²)" value={surf} onChange={setSurf}/>
        <DimSelect label="Classe GTB" value={cl} onChange={setCl} options={[
          { val: 'A', label: 'Classe A — Haute performance (×2)' },
          { val: 'B', label: 'Classe B — Standard (×1,5)' },
          { val: 'C', label: 'Classe C — Base (×1)' },
        ]}/>
        <DimSelect label="Zone climatique" value={zone} onChange={setZone} options={ZONES}/>
        {result && <ResultBox result={result}/>}
        <div style={{ padding: '8px 10px', background: 'var(--paper-2)', borderRadius: 5, fontSize: 10, color: 'var(--ink-4)', lineHeight: 1.5 }}>
          Décret BACS 2027 · CVC &gt; 70 kW · RGE Qualifelec GTB obligatoire.
        </div>
      </FormCard>
      <EquipList type="gtb"/>
    </div>
  );
}

// ── Récupération chaleur industrielle (IND-UT-102) ────────────────────────────

function INDRecForm() {
  const [debit,  setDebit]  = _dUseS(5000);
  const [tin,    setTin]    = _dUseS(200);
  const [tout,   setTout]   = _dUseS(80);
  const [rend,   setRend]   = _dUseS(75);
  const [heures, setHeures] = _dUseS(6000);

  const result = _dUseM(() => calcINDRec({ debit, tin, tout, rend, heures }), [debit, tin, tout, rend, heures]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — Récup. chaleur industrielle" color="var(--rouge)">
        <DimInput label="Débit gaz / fumées (m³/h)" value={debit} onChange={setDebit}/>
        <DimInput label="Température entrée (°C)" value={tin} onChange={setTin}/>
        <DimInput label="Température sortie (°C)" value={tout} onChange={setTout}/>
        <DimInput label="Rendement échangeur (%)" value={rend} onChange={setRend} max="100"/>
        <DimInput label="Durée fonctionnement (h/an)" value={heures} onChange={setHeures}/>
        {result && (
          <ResultBox result={result} extra={<>
            <KPI label="Puissance récupérée" value={result.pw != null ? result.pw + ' kW' : '—'}/>
            <KPI label="Énergie/an" value={result.energie != null ? result.energie + ' MWh' : '—'}/>
          </>}/>
        )}
      </FormCard>
      <EquipList type="ind_rec"/>
    </div>
  );
}

// ── Isolation réseau (IND-UT-115) ─────────────────────────────────────────────

function ISOForm() {
  const [long,   setLong]   = _dUseS(200);
  const [dn,     setDn]     = _dUseS(100);
  const [temp,   setTemp]   = _dUseS(120);
  const [fluide, setFluide] = _dUseS('vap');

  const result = _dUseM(() => calcISO({ long, dn, temp, fluide }), [long, dn, temp, fluide]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
      <FormCard title="Paramètres — Isolation réseau (IND-UT-115)" color="var(--copper)">
        <DimInput label="Longueur de réseau à isoler (m)" value={long} onChange={setLong}/>
        <DimSelect label="Diamètre nominal DN" value={String(dn)} onChange={v => setDn(Number(v))} options={
          [25,40,50,65,80,100,125,150,200].map(d => ({ val: String(d), label: `DN ${d}` }))
        }/>
        <DimInput label="Température fluide (°C)" value={temp} onChange={setTemp}/>
        <DimSelect label="Type de fluide" value={fluide} onChange={setFluide} options={[
          { val: 'vap', label: 'Vapeur' },
          { val: 'cond', label: 'Condensat' },
          { val: 'eau', label: 'Eau chaude process' },
        ]}/>
        {result && (
          <ResultBox result={result} extra={<>
            <KPI label="Pertes évitées" value={result.pw != null ? result.pw + ' kW' : '—'}/>
            <KPI label="Économies/an" value={result.energie != null ? fmtEur(result.energie) : '—'}/>
          </>}/>
        )}
      </FormCard>
      <EquipList type="ind_iso"/>
    </div>
  );
}

// ── Equipment list ────────────────────────────────────────────────────────────

function EquipList({ type }) {
  const items = EQUIP_CATALOG[type] || [];
  return (
    <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 16 }}>
      <div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-3)', marginBottom: 12 }}>Équipements recommandés</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {items.map((eq, i) => (
          <div key={i} style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            padding: '10px 12px', background: 'var(--paper-2)',
            borderRadius: 6, border: '1px solid var(--hairline)',
          }}>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{eq.name}</div>
              <div style={{ fontSize: 10, color: 'var(--ink-4)', marginTop: 2 }}>{eq.desc}</div>
            </div>
            <Badge tone={eq.tone} style={{ marginLeft: 10, flexShrink: 0, fontFamily: 'var(--font-mono)', fontSize: 10 }}>{eq.price}</Badge>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Side panel (right) ─────────────────────────────────────────────────────────

function SidePanel({ type, meta }) {
  const [client, setClient] = _dUseS(null);
  const [pushing, setPushing] = _dUseS(false);
  const [pushResult, setPushResult] = _dUseS(null);
  const API = () => (window.AE_API && window.AE_API.BASE) || '';

  async function pushToCrm() {
    if (!client) { setPushResult('⚠ Sélectionnez un client'); return; }
    setPushing(true);
    setPushResult(null);
    try {
      const payload = {
        name: `Étude ${meta.sub} — ${client.name}`,
        partnerName: client.name,
        source: 'dim',
        fostCode: meta.sub.split(' ')[0],
        kind: 'quote',
        contactId: client.contactId,
        organizationId: client.organizationId,
        metadata: { dimType: type },
      };
      const r = await fetch(`${API()}/api/crm/opportunities`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload),
      });
      const d = await r.json();
      if (r.ok) {
        setPushResult('✓ Opportunité créée');
        window.AE_API?.hydrate?.();
      } else {
        setPushResult('⚠ ' + (d.error || 'Erreur'));
      }
    } catch (e) { setPushResult('⚠ ' + e.message); }
    setPushing(false);
    setTimeout(() => setPushResult(null), 4000);
  }

  function downloadPDF() {
    alert(`📄 Étude ${meta.sub}\n\nType : ${meta.label}\n\nLa génération PDF nécessite jsPDF. Fonctionnalité disponible dans l'ancienne V (dimGenPDF).`);
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {/* FOST info */}
      <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 14 }}>
        <div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-3)', marginBottom: 10 }}>FOST applicable</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <Badge tone={meta.tone}>{meta.sub}</Badge>
          <span style={{ fontSize: 12, color: 'var(--ink-2)' }}>{meta.label}</span>
        </div>
        <div style={{ marginTop: 8, fontSize: 11, color: 'var(--ink-4)' }}>
          Taux CEE : <strong>{TAUX} €/MWh cumac</strong> · Durée vie selon équipement
        </div>
      </div>

      {/* Client picker (règle 3.a) */}
      <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 14 }}>
        <div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-3)', marginBottom: 10 }}>Lier à un client</div>
        {window.ClientPicker ? (
          <window.ClientPicker value={client} onChange={setClient} placeholder="Rechercher client Odoo / AE…"/>
        ) : (
          <div style={{ fontSize: 11, color: 'var(--ink-4)' }}>ClientPicker non chargé</div>
        )}
        {client && (
          <div style={{ marginTop: 8, padding: '6px 10px', background: 'var(--signal-tint)', borderRadius: 4, fontSize: 11, color: 'var(--signal-deep)' }}>
            👤 {client.name}
          </div>
        )}
      </div>

      {/* Actions */}
      <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 14, display: 'flex', flexDirection: 'column', gap: 8 }}>
        <div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--ink-3)', marginBottom: 4 }}>Actions</div>
        <Btn variant="signal" size="sm" icon={<Icon.arrow/>} onClick={pushToCrm} disabled={pushing} style={{ justifyContent: 'center' }}>
          {pushing ? 'Envoi…' : '→ Créer opportunité CRM'}
        </Btn>
        <Btn variant="outline" size="sm" onClick={downloadPDF} style={{ justifyContent: 'center' }}>
          🖨️ Télécharger étude PDF
        </Btn>
        <Btn variant="ghost" size="sm" style={{ justifyContent: 'center' }} onClick={() => {
          // Lien vers Studio solaire si type PV-related
          if (typeof window.AE_NAV === 'function') window.AE_NAV('solar');
        }}>
          ☀️ Ouvrir Studio solaire
        </Btn>
        {pushResult && (
          <div style={{ padding: '6px 10px', fontSize: 10, fontFamily: 'var(--font-mono)', textAlign: 'center',
            background: pushResult.startsWith('✓') ? 'var(--signal-tint)' : 'var(--rouge-tint)',
            color: pushResult.startsWith('✓') ? 'var(--signal-deep)' : 'var(--rouge)',
            borderRadius: 4, border: '1px solid ' + (pushResult.startsWith('✓') ? 'var(--signal-soft)' : 'var(--rouge-tint)'),
          }}>{pushResult}</div>
        )}
      </div>
    </div>
  );
}

// ── Config (onglet Paramètres — règle 6) ──────────────────────────────────────

function DimConfig() {
  const [taux, setTaux] = _dUseS(7.5);
  const [zone, setZone] = _dUseS('H1');
  const [pdfLogo, setPdfLogo] = _dUseS('Audits Énergies');
  const [dureeVie, setDureeVie] = _dUseS({ rec: 15, hp: 20, pac_aireau: 20, pac_ailair: 15, destrat: 15, gtb: 20, ind_rec: 15, ind_iso: 15 });

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, maxWidth: 900 }}>
      <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--ink)' }}>Paramètres CEE</div>
        <DimInput label="Taux CEE (€/MWh cumac)" value={taux} onChange={setTaux} step="0.1"/>
        <DimSelect label="Zone climatique par défaut" value={zone} onChange={setZone} options={ZONES}/>
        <DimInput label="Entête PDF (raison sociale)" value={pdfLogo} onChange={setPdfLogo} type="text"/>
        <Btn variant="signal" size="sm" onClick={() => alert('Paramètres sauvegardés (localStorage)')}>Enregistrer</Btn>
      </div>
      <div style={{ border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper)', padding: 16 }}>
        <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--ink)', marginBottom: 12 }}>Durées de vie par FOST (ans)</div>
        <div style={{ display: 'grid', gap: 8 }}>
          {DIM_TYPES.map(t => (
            <div key={t.val} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <Badge tone={t.tone} style={{ minWidth: 90, fontSize: 9, justifyContent: 'center' }}>{t.sub}</Badge>
              <input type="number" value={dureeVie[t.val] || 20}
                onChange={e => setDureeVie(d => ({ ...d, [t.val]: Number(e.target.value) }))}
                style={{ width: 56, padding: '4px 8px', fontSize: 12, border: '1px solid var(--line-2)', borderRadius: 4, background: 'var(--paper-2)', color: 'var(--ink)', fontFamily: 'var(--font-mono)', textAlign: 'center' }}/>
              <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>ans</span>
              <span style={{ flex: 1, fontSize: 11, color: 'var(--ink-3)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{t.label}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { DimensionnementPage });
