/* global React */
// maprimerenov.jsx — M4 MaPrimeRénov' / Mon Accompagnateur Rénov' (MAR)
// CRUD dossiers bénéficiaires, calcul primes ANAH 2024 en live, Kanban statuts, barèmes

const { useState, useEffect, useMemo, useCallback } = React;
const BASE = (window.AE_API && window.AE_API.BASE) || '';

// ── Constantes locales (miroir routes/index.js) ────────────────────────────────
const CAT_LABELS = { tm: 'Très modeste (Bleu)', m: 'Modeste (Jaune)', i: 'Intermédiaire (Violet)', s: 'Supérieur (Rose)' };
const CAT_COLORS = { tm: '#3B82F6', m: '#F59E0B', i: '#8B5CF6', s: '#EC4899' };
const CAT_TONES  = { tm: 'plasma', m: 'amber', i: 'plasma', s: 'rouge' };

const STATUTS = [
  { key: 'eligibilite', label: 'Éligibilité',  color: '#94A3B8', bg: 'rgba(148,163,184,.12)' },
  { key: 'audit',       label: 'Audit',         color: '#3B82F6', bg: 'rgba(59,130,246,.12)' },
  { key: 'devis',       label: 'Devis',         color: '#F59E0B', bg: 'rgba(245,158,11,.12)' },
  { key: 'instruction', label: 'Instruction',   color: '#8B5CF6', bg: 'rgba(139,92,246,.12)' },
  { key: 'valide',      label: 'Validé ANAH',   color: '#22C55E', bg: 'rgba(34,197,94,.12)' },
  { key: 'verse',       label: 'Prime versée',  color: '#16A34A', bg: 'rgba(22,163,74,.12)' },
];

const ZONES = [
  { value: 'abis', label: 'Zone A bis — Paris + couronnes proches' },
  { value: 'a',    label: 'Zone A — Île-de-France, Côte d\'Azur, Genevois fr.' },
  { value: 'b1',   label: 'Zone B1 — Grandes agglos > 250 000 hab.' },
  { value: 'b2',   label: 'Zone B2 — Villes moyennes' },
  { value: 'c',    label: 'Zone C — Reste de la France' },
];

const DPE_LETTRES = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
const DPE_COLORS  = { A: '#009B77', B: '#2DB83D', C: '#7DC24B', D: '#F7CD1A', E: '#F4931E', F: '#E3610E', G: '#CC2529' };

// Barèmes locaux (affichage uniquement — autorité = backend)
const BAREMES_LOCAL = [
  { code:'ISO_COMBLES',       cat:'Isolation', label:'Combles perdus',           unite:'m²',     forfaits:{tm:25,m:20,i:15,s:7} },
  { code:'ISO_RAMPANTS',      cat:'Isolation', label:'Rampants de toiture',      unite:'m²',     forfaits:{tm:50,m:35,i:25,s:15} },
  { code:'ISO_ITE',           cat:'Isolation', label:'Murs extérieur (ITE)',     unite:'m²',     forfaits:{tm:75,m:55,i:40,s:25} },
  { code:'ISO_ITI',           cat:'Isolation', label:'Murs intérieur (ITI)',     unite:'m²',     forfaits:{tm:25,m:15,i:10,s:0} },
  { code:'ISO_PLANCHER',      cat:'Isolation', label:'Plancher bas',             unite:'m²',     forfaits:{tm:15,m:10,i:7,s:0} },
  { code:'ISO_FENETRE',       cat:'Isolation', label:'Fenêtres / portes-fen.',  unite:'unité',  forfaits:{tm:100,m:80,i:40,s:0} },
  { code:'PAC_AIREAU',        cat:'Chauffage', label:'PAC air/eau',              unite:'forfait',forfaits:{tm:4000,m:3000,i:2000,s:0} },
  { code:'PAC_GEO',           cat:'Chauffage', label:'PAC géothermique',         unite:'forfait',forfaits:{tm:10000,m:8000,i:5000,s:0} },
  { code:'POELE_GRANULES',    cat:'Chauffage', label:'Poêle / insert granulés', unite:'forfait',forfaits:{tm:2500,m:2000,i:1500,s:500} },
  { code:'CHAUDIERE_GRANULES',cat:'Chauffage', label:'Chaudière granulés',      unite:'forfait',forfaits:{tm:10000,m:8000,i:5000,s:0} },
  { code:'SOLAIRE_THERMIQUE', cat:'Chauffage', label:'CESI solaire thermique',  unite:'forfait',forfaits:{tm:4000,m:3000,i:2000,s:1000} },
  { code:'CET',               cat:'Chauffage', label:'Chauffe-eau thermodynamique',unite:'forfait',forfaits:{tm:1200,m:800,i:400,s:0} },
  { code:'RCU',               cat:'Chauffage', label:'Raccordement réseau chaleur',unite:'forfait',forfaits:{tm:1200,m:800,i:400,s:0} },
  { code:'VMC_DF',            cat:'Ventilation',label:'VMC double flux',        unite:'forfait',forfaits:{tm:2500,m:2000,i:1500,s:700} },
  { code:'AUDIT_ENE',         cat:'Accompagnement',label:'Audit énergétique',  unite:'forfait',forfaits:{tm:500,m:400,i:300,s:0} },
];

// ── API helpers ────────────────────────────────────────────────────────────────
function apiMAR(path, opts) {
  return fetch(BASE + '/api/mar' + path, { headers: { 'Content-Type': 'application/json' }, ...opts }).then(r => r.json());
}
function fmt(n) { return (n ?? 0).toLocaleString('fr-FR', { maximumFractionDigits: 0 }); }
function fmtEur(n) {
  if (n >= 1e6) return (n / 1e6).toFixed(2) + ' M€';
  if (n >= 1000) return (n / 1000).toFixed(1) + ' k€';
  return fmt(n) + ' €';
}

// ── Local prime calc (live, sans backend) ─────────────────────────────────────
function calcPrimeLocal(poste, cat) {
  const b = BAREMES_LOCAL.find(x => x.code === poste.code);
  if (!b || !cat) return 0;
  const taux = b.forfaits[cat] || 0;
  if (!taux) return 0;
  if (b.unite === 'm²' && poste.quantite > 0) {
    const qte = Math.min(parseFloat(poste.quantite) || 0, 100);
    return qte * taux;
  }
  return taux;
}

// ── Shared UI ──────────────────────────────────────────────────────────────────
function Panel({ title, subtitle, children, actions, style }) {
  return (
    <div style={{ background: 'var(--paper)', border: '1px solid var(--line)', borderRadius: 8, overflow: 'hidden', ...style }}>
      {(title || actions) && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px 16px', borderBottom: '1px solid var(--line)' }}>
          <div>
            <div style={{ fontSize: 13, fontWeight: 600 }}>{title}</div>
            {subtitle && <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 1 }}>{subtitle}</div>}
          </div>
          {actions && <div style={{ display: 'flex', gap: 6 }}>{actions}</div>}
        </div>
      )}
      <div style={{ padding: 16 }}>{children}</div>
    </div>
  );
}
function Modal({ title, onClose, children, width = 680 }) {
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 3000, background: 'rgba(0,0,0,.45)', display: 'flex', alignItems: 'center', justifyContent: 'center' }} onClick={onClose}>
      <div style={{ background: 'var(--paper)', border: '1px solid var(--line)', borderRadius: 10, width, maxWidth: '96vw', maxHeight: '92vh', overflow: 'auto', boxShadow: '0 24px 48px rgba(0,0,0,.2)' }} onClick={e => e.stopPropagation()}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '14px 20px', borderBottom: '1px solid var(--line)' }}>
          <span style={{ fontWeight: 600, fontSize: 14 }}>{title}</span>
          <Btn variant="ghost" size="sm" onClick={onClose} icon={<Icon.cross />} />
        </div>
        <div style={{ padding: 20 }}>{children}</div>
      </div>
    </div>
  );
}
function Field({ label, children, required, hint }) {
  return (
    <div style={{ marginBottom: 14 }}>
      <label style={{ display: 'block', fontSize: 11, fontWeight: 600, color: 'var(--ink-3)', marginBottom: 4, textTransform: 'uppercase', letterSpacing: 0.4 }}>
        {label}{required && <span style={{ color: 'var(--rouge)', marginLeft: 3 }}>*</span>}
      </label>
      {children}
      {hint && <div style={{ fontSize: 10, color: 'var(--ink-4)', marginTop: 3 }}>{hint}</div>}
    </div>
  );
}
function Input({ value, onChange, type = 'text', placeholder, step, min, max, disabled, style }) {
  return <input type={type} value={value ?? ''} onChange={onChange} placeholder={placeholder} step={step} min={min} max={max} disabled={disabled}
    style={{ width: '100%', padding: '7px 10px', fontSize: 13, borderRadius: 6, border: '1px solid var(--line-2)', background: 'var(--paper-2)', color: 'var(--ink)', outline: 'none', boxSizing: 'border-box', ...style }} />;
}
function Select({ value, onChange, children, style }) {
  return <select value={value ?? ''} onChange={onChange}
    style={{ width: '100%', padding: '7px 10px', fontSize: 13, borderRadius: 6, border: '1px solid var(--line-2)', background: 'var(--paper-2)', color: 'var(--ink)', ...style }}>{children}</select>;
}

// ── DPE badge ──────────────────────────────────────────────────────────────────
function DpeBadge({ lettre }) {
  if (!lettre) return <span style={{ color: 'var(--ink-4)', fontSize: 12 }}>—</span>;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 22, height: 22, borderRadius: 4, background: DPE_COLORS[lettre] || 'var(--paper-3)', color: '#fff', fontSize: 11, fontWeight: 800 }}>{lettre}</span>
  );
}

// ── Statut badge ──────────────────────────────────────────────────────────────
function StatutBadge({ status }) {
  const s = STATUTS.find(x => x.key === status) || STATUTS[0];
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 8px', borderRadius: 999, fontSize: 11, fontWeight: 500, background: s.bg, color: s.color, border: `1px solid ${s.color}33` }}>
      <span style={{ width: 6, height: 6, borderRadius: '50%', background: s.color, flexShrink: 0 }} />
      {s.label}
    </span>
  );
}

// ── Formulaire dossier complet ─────────────────────────────────────────────────
function DossierForm({ initial, onSave, onClose }) {
  const isNew = !initial?.id;
  const [form, setForm] = useState(initial || {
    nom: '', prenom: '', email: '', telephone: '',
    adresse: '', codePostal: '', ville: '', zone: 'c',
    typeBatiment: 'maison', anneeConstruction: '', surfaceHabitable: '',
    dpeBefore: '', dpeAfter: '',
    categorie: '', nombrePersonnes: 1, revenuFiscal: '',
    status: 'eligibilite',
    postes: [],
    notes: '',
  });
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');
  const [showBaremes, setShowBaremes] = useState(false);

  const f = k => e => setForm(p => ({ ...p, [k]: e.target.value }));
  const fi = k => e => setForm(p => ({ ...p, [k]: parseInt(e.target.value) || '' }));
  const ff = k => e => setForm(p => ({ ...p, [k]: parseFloat(e.target.value) || '' }));

  // Calcul catégorie live
  const catAuto = useMemo(() => {
    const rev = parseFloat(form.revenuFiscal);
    const nb = parseInt(form.nombrePersonnes) || 1;
    if (!rev || !form.zone) return null;
    // Simplified local calc (backend has authority)
    const PLAF = {
      abis: { tm:[23541,34551,41493,48447,55427], m:[28657,42058,50513,58981,67462], i:[40018,58827,70382,82839,94440] },
      a:    { tm:[23541,34551,41493,48447,55427], m:[28657,42058,50513,58981,67462], i:[40018,58827,70382,82839,94440] },
      default: { tm:[17009,24875,29917,34948,39992], m:[21805,31889,38349,44802,51281], i:[30549,44907,54071,63235,72400] },
    };
    const p = PLAF[form.zone] || PLAF.default;
    const idx = Math.min(Math.max(1, nb), 5) - 1;
    if (rev <= p.tm[idx]) return 'tm';
    if (rev <= p.m[idx])  return 'm';
    if (rev <= p.i[idx])  return 'i';
    return 's';
  }, [form.revenuFiscal, form.zone, form.nombrePersonnes]);

  const cat = form.categorie || catAuto;

  // Primes live
  const primesCalc = useMemo(() => {
    if (!cat) return { postes: form.postes || [], total: 0 };
    const postes = (form.postes || []).map(p => ({ ...p, prime: calcPrimeLocal(p, cat) }));
    const total = postes.reduce((s, p) => s + (p.prime || 0), 0);
    return { postes, total };
  }, [form.postes, cat]);

  const addPoste = (b) => {
    const exists = form.postes?.find(p => p.code === b.code);
    if (exists) return;
    setForm(p => ({ ...p, postes: [...(p.postes || []), { code: b.code, label: b.label, unite: b.unite, quantite: b.unite === 'm²' ? 20 : 1, montantTTC: '', prime: 0 }] }));
  };
  const updatePoste = (idx, key, val) => {
    setForm(p => {
      const arr = [...(p.postes || [])];
      arr[idx] = { ...arr[idx], [key]: val };
      return { ...p, postes: arr };
    });
  };
  const removePoste = (idx) => setForm(p => ({ ...p, postes: (p.postes || []).filter((_, i) => i !== idx) }));

  const save = async () => {
    if (!form.nom) { setError('Le nom du bénéficiaire est requis'); return; }
    setSaving(true); setError('');
    try {
      const body = { ...form, categorie: cat || form.categorie, postes: primesCalc.postes, primeTotal: primesCalc.total };
      const method = isNew ? 'POST' : 'PATCH';
      const url = isNew ? '/projects' : `/projects/${form.id}`;
      await apiMAR(url, { method, body: JSON.stringify(body) });
      onSave && onSave();
      onClose();
    } catch (e) { setError(e.message || 'Erreur'); }
    setSaving(false);
  };

  return (
    <div>
      {/* Section bénéficiaire */}
      <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 10 }}>👤 Bénéficiaire</div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: '0 14px' }}>
        <Field label="Nom" required><Input value={form.nom} onChange={f('nom')} placeholder="Dupont" /></Field>
        <Field label="Prénom"><Input value={form.prenom} onChange={f('prenom')} placeholder="Jean" /></Field>
        <Field label="Email"><Input type="email" value={form.email} onChange={f('email')} placeholder="jean@email.fr" /></Field>
        <Field label="Téléphone"><Input value={form.telephone} onChange={f('telephone')} placeholder="06 12 34 56 78" /></Field>
      </div>

      {/* Section logement */}
      <div style={{ borderTop: '1px solid var(--line)', paddingTop: 14, marginTop: 4 }}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 10 }}>🏠 Logement</div>
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr', gap: '0 14px' }}>
          <Field label="Adresse"><Input value={form.adresse} onChange={f('adresse')} placeholder="12 rue des Acacias" /></Field>
          <Field label="Code postal"><Input value={form.codePostal} onChange={f('codePostal')} placeholder="69001" /></Field>
          <Field label="Ville"><Input value={form.ville} onChange={f('ville')} placeholder="Lyon" /></Field>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr 1fr', gap: '0 14px' }}>
          <Field label="Zone ANAH">
            <Select value={form.zone} onChange={f('zone')}>
              {ZONES.map(z => <option key={z.value} value={z.value}>{z.value.toUpperCase()}</option>)}
            </Select>
          </Field>
          <Field label="Type">
            <Select value={form.typeBatiment} onChange={f('typeBatiment')}>
              <option value="maison">Maison individuelle</option>
              <option value="appartement">Appartement</option>
            </Select>
          </Field>
          <Field label="Année construction"><Input type="number" value={form.anneeConstruction} onChange={fi('anneeConstruction')} placeholder="1975" min="1800" max={new Date().getFullYear()} /></Field>
          <Field label="Surface (m²)"><Input type="number" value={form.surfaceHabitable} onChange={ff('surfaceHabitable')} placeholder="120" min="9" /></Field>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0 8px' }}>
            <Field label="DPE avant">
              <Select value={form.dpeBefore} onChange={f('dpeBefore')}>
                <option value="">—</option>
                {DPE_LETTRES.map(l => <option key={l} value={l}>{l}</option>)}
              </Select>
            </Field>
            <Field label="DPE après">
              <Select value={form.dpeAfter} onChange={f('dpeAfter')}>
                <option value="">—</option>
                {DPE_LETTRES.map(l => <option key={l} value={l}>{l}</option>)}
              </Select>
            </Field>
          </div>
        </div>
      </div>

      {/* Section fiscalité */}
      <div style={{ borderTop: '1px solid var(--line)', paddingTop: 14, marginTop: 4 }}>
        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 10 }}>💰 Éligibilité & Fiscalité</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: '0 14px', alignItems: 'end' }}>
          <Field label="Revenu fiscal de référence (€)" hint="Revenu N-2 (avis d'imposition)">
            <Input type="number" value={form.revenuFiscal} onChange={ff('revenuFiscal')} placeholder="28 000" min="0" />
          </Field>
          <Field label="Nb personnes au foyer">
            <Select value={form.nombrePersonnes} onChange={fi('nombrePersonnes')}>
              {[1,2,3,4,5,6].map(n => <option key={n} value={n}>{n} personne{n > 1 ? 's' : ''}</option>)}
            </Select>
          </Field>
          <Field label="Catégorie ANAH détectée">
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, height: 34 }}>
              {cat
                ? <span style={{ display: 'inline-block', padding: '4px 12px', borderRadius: 6, background: `${CAT_COLORS[cat]}22`, color: CAT_COLORS[cat], fontWeight: 700, fontSize: 12, border: `1px solid ${CAT_COLORS[cat]}44` }}>{CAT_LABELS[cat]}</span>
                : <span style={{ fontSize: 12, color: 'var(--ink-4)' }}>Saisir revenu + zone</span>
              }
            </div>
          </Field>
          <Field label="Statut dossier">
            <Select value={form.status} onChange={f('status')}>
              {STATUTS.map(s => <option key={s.key} value={s.key}>{s.label}</option>)}
            </Select>
          </Field>
        </div>
      </div>

      {/* Section travaux */}
      <div style={{ borderTop: '1px solid var(--line)', paddingTop: 14, marginTop: 4 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
          <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5 }}>🔧 Postes de travaux</div>
          <Btn variant="outline" size="sm" icon={<Icon.plus />} onClick={() => setShowBaremes(v => !v)}>
            {showBaremes ? 'Masquer barèmes' : 'Ajouter poste'}
          </Btn>
        </div>

        {showBaremes && (
          <div style={{ background: 'var(--paper-2)', border: '1px solid var(--line)', borderRadius: 6, padding: 12, marginBottom: 12 }}>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 8 }}>Cliquer pour ajouter au dossier :</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {BAREMES_LOCAL.map(b => (
                <button key={b.code} onClick={() => addPoste(b)}
                  style={{ padding: '4px 10px', fontSize: 11, borderRadius: 5, border: '1px solid var(--line-2)', background: form.postes?.find(p => p.code === b.code) ? 'var(--signal-tint)' : 'var(--paper)', color: 'var(--ink-2)', cursor: 'pointer' }}>
                  {b.label}
                </button>
              ))}
            </div>
          </div>
        )}

        {primesCalc.postes.length === 0
          ? <div style={{ textAlign: 'center', padding: '14px 0', color: 'var(--ink-4)', fontSize: 12 }}>Aucun poste de travaux ajouté.</div>
          : (
            <div>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
                <thead>
                  <tr style={{ borderBottom: '1px solid var(--line)' }}>
                    {['Poste', 'Quantité', 'Montant devis TTC (€)', 'Prime calculée', ''].map(h => (
                      <th key={h} style={{ padding: '5px 6px', textAlign: 'left', color: 'var(--ink-3)', fontWeight: 600, fontSize: 11 }}>{h}</th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {primesCalc.postes.map((p, idx) => (
                    <tr key={idx} style={{ borderBottom: '1px solid var(--line-2)' }}>
                      <td style={{ padding: '6px 6px', fontWeight: 500 }}>{p.label}</td>
                      <td style={{ padding: '6px 6px', width: 100 }}>
                        {p.unite === 'm²' || p.unite === 'unité'
                          ? <Input type="number" value={p.quantite} onChange={e => updatePoste(idx, 'quantite', parseFloat(e.target.value) || 1)} style={{ width: 70 }} min="1" />
                          : <span style={{ color: 'var(--ink-3)' }}>forfait</span>
                        }
                        <span style={{ marginLeft: 4, fontSize: 11, color: 'var(--ink-4)' }}>{p.unite}</span>
                      </td>
                      <td style={{ padding: '6px 6px', width: 160 }}>
                        <Input type="number" value={p.montantTTC} onChange={e => updatePoste(idx, 'montantTTC', parseFloat(e.target.value) || '')} placeholder="ex: 3 500" style={{ width: 130 }} min="0" step="10" />
                      </td>
                      <td style={{ padding: '6px 6px' }}>
                        {cat
                          ? <strong style={{ color: 'var(--signal)', fontSize: 13 }}>{fmt(p.prime)} €</strong>
                          : <span style={{ color: 'var(--ink-4)', fontSize: 12 }}>Saisir revenu + zone</span>
                        }
                      </td>
                      <td style={{ padding: '6px 6px' }}>
                        <Btn variant="ghost" size="sm" onClick={() => removePoste(idx)} icon={<Icon.cross />} style={{ color: 'var(--rouge)' }} />
                      </td>
                    </tr>
                  ))}
                </tbody>
                <tfoot>
                  <tr style={{ borderTop: '2px solid var(--line)' }}>
                    <td colSpan={2} style={{ padding: '8px 6px', fontWeight: 700 }}>Total</td>
                    <td style={{ padding: '8px 6px', fontWeight: 700, color: 'var(--copper)' }}>
                      {fmt(primesCalc.postes.reduce((s, p) => s + (parseFloat(p.montantTTC) || 0), 0))} €
                    </td>
                    <td style={{ padding: '8px 6px' }}>
                      <strong style={{ fontSize: 15, color: 'var(--signal)' }}>{fmt(primesCalc.total)} €</strong>
                      {primesCalc.postes.reduce((s, p) => s + (parseFloat(p.montantTTC) || 0), 0) > 0 && (
                        <span style={{ fontSize: 11, color: 'var(--ink-3)', marginLeft: 6 }}>
                          ({Math.round(primesCalc.total / primesCalc.postes.reduce((s, p) => s + (parseFloat(p.montantTTC) || 0), 0) * 100)} % d'aide)
                        </span>
                      )}
                    </td>
                    <td />
                  </tr>
                </tfoot>
              </table>
            </div>
          )
        }
      </div>

      <Field label="Notes"><Input value={form.notes} onChange={f('notes')} placeholder="Informations complémentaires, historique contacts…" /></Field>

      {error && <div style={{ color: 'var(--rouge)', fontSize: 12, marginBottom: 10 }}>{error}</div>}
      <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 8 }}>
        <Btn variant="ghost" onClick={onClose}>Annuler</Btn>
        <Btn variant="primary" onClick={save} disabled={saving || !form.nom}>{saving ? 'Sauvegarde…' : isNew ? 'Créer le dossier' : 'Enregistrer'}</Btn>
      </div>
    </div>
  );
}

// ── Tab 1: Kanban dossiers ──────────────────────────────────────────────────────
function KanbanTab({ projects, onEdit, onDelete, onRefresh, loading }) {
  const byStatus = useMemo(() => {
    const map = {};
    STATUTS.forEach(s => { map[s.key] = []; });
    (projects || []).forEach(p => { if (map[p.status]) map[p.status].push(p); else map['eligibilite'].push(p); });
    return map;
  }, [projects]);

  const totalPrimes = (projects || []).reduce((s, p) => s + (p.primeTotal || 0), 0);
  const totalTravaux = (projects || []).reduce((s, p) => s + (p.montantTravaux || 0), 0);
  const nbValide = (projects || []).filter(p => p.status === 'valide' || p.status === 'verse').length;

  if (loading) return <div style={{ textAlign: 'center', padding: 40, color: 'var(--ink-3)' }}>Chargement…</div>;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* KPIs */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0, border: '1px solid var(--line)', borderRadius: 8, background: 'var(--paper-2)', overflow: 'hidden' }}>
        {[
          { label: 'Dossiers en cours', value: fmt(projects?.length || 0), sub: 'total actif', color: 'var(--ink)' },
          { label: 'Primes calculées', value: fmtEur(totalPrimes), sub: `${projects?.length || 0} dossiers`, color: 'var(--signal)', div: true },
          { label: 'Montant travaux', value: fmtEur(totalTravaux), sub: 'TTC total devis', color: 'var(--copper)', div: true },
          { label: 'Validés ANAH', value: fmt(nbValide), sub: 'prime accordée', color: 'var(--signal-deep)', div: true },
        ].map((kpi, i) => (
          <div key={i} style={{ padding: '16px 20px', borderLeft: kpi.div ? '1px solid var(--line)' : 'none' }}>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 500, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 6 }}>{kpi.label}</div>
            <div style={{ fontSize: 22, fontWeight: 700, color: kpi.color, letterSpacing: '-0.02em' }}>{kpi.value}</div>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 2 }}>{kpi.sub}</div>
          </div>
        ))}
      </div>

      {/* Kanban */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 10, overflowX: 'auto', minWidth: 0 }}>
        {STATUTS.map(s => (
          <div key={s.key} style={{ minWidth: 160 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 8 }}>
              <span style={{ width: 8, height: 8, borderRadius: '50%', background: s.color, flexShrink: 0 }} />
              <span style={{ fontSize: 11, fontWeight: 600, color: s.color }}>{s.label}</span>
              <span style={{ fontSize: 10, fontWeight: 700, background: s.bg, color: s.color, padding: '1px 6px', borderRadius: 99, marginLeft: 'auto' }}>{byStatus[s.key]?.length || 0}</span>
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {(byStatus[s.key] || []).map(p => (
                <div key={p.id} style={{ background: 'var(--paper)', border: '1px solid var(--line)', borderLeft: `3px solid ${s.color}`, borderRadius: 6, padding: '10px 12px' }}>
                  <div style={{ fontWeight: 600, fontSize: 12, marginBottom: 3 }}>{p.prenom ? `${p.prenom} ${p.nom}` : p.nom}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 6 }}>{p.ville || '—'}</div>
                  {p.primeTotal > 0 && (
                    <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--signal)', marginBottom: 4 }}>{fmt(p.primeTotal)} €</div>
                  )}
                  <div style={{ display: 'flex', alignItems: 'center', gap: 4, marginBottom: 6 }}>
                    <DpeBadge lettre={p.dpeBefore} />
                    {p.dpeAfter && <><span style={{ fontSize: 10, color: 'var(--ink-4)' }}>→</span><DpeBadge lettre={p.dpeAfter} /></>}
                  </div>
                  {p.categorie && <Badge tone={CAT_TONES[p.categorie] || 'neutral'}>{CAT_LABELS[p.categorie]}</Badge>}
                  <div style={{ display: 'flex', gap: 4, marginTop: 8 }}>
                    <Btn variant="ghost" size="sm" onClick={() => onEdit(p)} icon={<Icon.doc />} style={{ flex: 1 }}>Voir</Btn>
                    <Btn variant="ghost" size="sm" onClick={() => onDelete(p.id)} icon={<Icon.cross />} style={{ color: 'var(--rouge)' }} />
                  </div>
                </div>
              ))}
              {byStatus[s.key]?.length === 0 && (
                <div style={{ textAlign: 'center', padding: '14px 0', color: 'var(--ink-4)', fontSize: 11, borderRadius: 6, border: '1px dashed var(--line)' }}>Vide</div>
              )}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Tab 2: Liste détaillée ──────────────────────────────────────────────────────
function ListeTab({ projects, onEdit, onDelete, loading }) {
  const [search, setSearch] = useState('');
  const [filterStatus, setFilterStatus] = useState('');

  const filtered = useMemo(() => (projects || []).filter(p => {
    const q = search.toLowerCase();
    const matchQ = !q || `${p.nom} ${p.prenom} ${p.ville} ${p.email}`.toLowerCase().includes(q);
    const matchS = !filterStatus || p.status === filterStatus;
    return matchQ && matchS;
  }), [projects, search, filterStatus]);

  if (loading) return <div style={{ textAlign: 'center', padding: 40, color: 'var(--ink-3)' }}>Chargement…</div>;

  return (
    <Panel
      title={`Dossiers (${filtered.length}/${(projects || []).length})`}
      subtitle="Liste complète — cliquer pour ouvrir"
      actions={
        <div style={{ display: 'flex', gap: 8 }}>
          <Input value={search} onChange={e => setSearch(e.target.value)} placeholder="Rechercher…" style={{ width: 160 }} />
          <Select value={filterStatus} onChange={e => setFilterStatus(e.target.value)} style={{ width: 130 }}>
            <option value="">Tous statuts</option>
            {STATUTS.map(s => <option key={s.key} value={s.key}>{s.label}</option>)}
          </Select>
          <Btn variant="ghost" size="sm" icon={<Icon.download />} onClick={() => window.open(`${BASE}/api/mar/export-csv`, '_blank')}>CSV</Btn>
        </div>
      }
    >
      {filtered.length === 0
        ? <div style={{ textAlign: 'center', padding: '20px 0', color: 'var(--ink-3)' }}>Aucun dossier.</div>
        : (
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--line)' }}>
                {['Bénéficiaire', 'Ville / Zone', 'Type', 'Catégorie', 'DPE', 'Travaux', 'Prime', 'Statut', ''].map(h => (
                  <th key={h} style={{ padding: '6px 8px', textAlign: 'left', color: 'var(--ink-3)', fontWeight: 600, fontSize: 11 }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {filtered.map(p => (
                <tr key={p.id} style={{ borderBottom: '1px solid var(--line-2)', cursor: 'pointer' }} onClick={() => onEdit(p)}>
                  <td style={{ padding: '8px 8px', fontWeight: 500 }}>{p.prenom ? `${p.prenom} ${p.nom}` : p.nom}</td>
                  <td style={{ padding: '8px 8px', color: 'var(--ink-3)' }}>{p.ville || '—'} · {(p.zone || '').toUpperCase()}</td>
                  <td style={{ padding: '8px 8px', color: 'var(--ink-3)' }}>{p.typeBatiment === 'maison' ? '🏠' : '🏢'}</td>
                  <td style={{ padding: '8px 8px' }}>{p.categorie ? <span style={{ fontSize: 11, fontWeight: 600, color: CAT_COLORS[p.categorie] }}>{CAT_LABELS[p.categorie]}</span> : '—'}</td>
                  <td style={{ padding: '8px 8px' }}><div style={{ display: 'flex', gap: 4, alignItems: 'center' }}><DpeBadge lettre={p.dpeBefore} />{p.dpeAfter && <><span style={{ fontSize: 10, color: 'var(--ink-4)' }}>→</span><DpeBadge lettre={p.dpeAfter} /></>}</div></td>
                  <td style={{ padding: '8px 8px', color: 'var(--copper)' }}>{p.montantTravaux ? fmtEur(p.montantTravaux) : '—'}</td>
                  <td style={{ padding: '8px 8px', fontWeight: 600, color: 'var(--signal)' }}>{p.primeTotal ? fmtEur(p.primeTotal) : '—'}</td>
                  <td style={{ padding: '8px 8px' }}><StatutBadge status={p.status} /></td>
                  <td style={{ padding: '8px 8px' }}>
                    <Btn variant="ghost" size="sm" onClick={e => { e.stopPropagation(); onDelete(p.id); }} icon={<Icon.cross />} style={{ color: 'var(--rouge)' }} />
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )
      }
    </Panel>
  );
}

// ── Tab 3: Barèmes ANAH 2024 ───────────────────────────────────────────────────
function BaremesTab() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <Panel title="Barèmes MaPrimeRénov' 2024" subtitle="Source : Arrêté du 29 déc. 2023 — montants en € par poste et par catégorie de revenus">
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8, marginBottom: 16 }}>
          {Object.entries(CAT_LABELS).map(([cat, label]) => (
            <div key={cat} style={{ padding: '8px 12px', borderRadius: 6, background: `${CAT_COLORS[cat]}15`, border: `1px solid ${CAT_COLORS[cat]}33`, textAlign: 'center' }}>
              <div style={{ fontSize: 11, fontWeight: 700, color: CAT_COLORS[cat] }}>{label}</div>
            </div>
          ))}
        </div>
        {['Isolation', 'Chauffage', 'Ventilation', 'Accompagnement'].map(catLabel => {
          const postes = BAREMES_LOCAL.filter(b => b.cat === catLabel);
          if (!postes.length) return null;
          return (
            <div key={catLabel} style={{ marginBottom: 20 }}>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 8 }}>{catLabel}</div>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
                <thead>
                  <tr style={{ borderBottom: '1px solid var(--line)' }}>
                    <th style={{ padding: '5px 8px', textAlign: 'left', color: 'var(--ink-3)', fontSize: 11, fontWeight: 600, width: '40%' }}>Poste</th>
                    {['Très modeste', 'Modeste', 'Intermédiaire', 'Supérieur'].map(c => (
                      <th key={c} style={{ padding: '5px 8px', textAlign: 'right', color: 'var(--ink-3)', fontSize: 11, fontWeight: 600 }}>{c}</th>
                    ))}
                    <th style={{ padding: '5px 8px', textAlign: 'left', color: 'var(--ink-3)', fontSize: 11, fontWeight: 600, width: '8%' }}>Unité</th>
                  </tr>
                </thead>
                <tbody>
                  {postes.map(b => (
                    <tr key={b.code} style={{ borderBottom: '1px solid var(--line-2)' }}>
                      <td style={{ padding: '7px 8px', fontWeight: 500 }}>{b.label}</td>
                      {['tm', 'm', 'i', 's'].map(cat => (
                        <td key={cat} style={{ padding: '7px 8px', textAlign: 'right', fontWeight: b.forfaits[cat] > 0 ? 600 : 400, color: b.forfaits[cat] > 0 ? CAT_COLORS[cat] : 'var(--ink-4)' }}>
                          {b.forfaits[cat] > 0 ? `${fmt(b.forfaits[cat])} €` : '—'}
                        </td>
                      ))}
                      <td style={{ padding: '7px 8px', color: 'var(--ink-3)', fontSize: 11 }}>{b.unite}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          );
        })}
      </Panel>

      {/* Plafonds revenus */}
      <Panel title="Plafonds de revenus ANAH 2024" subtitle="Revenu fiscal de référence N-2 — Zone B2/C (reste de la France)">
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
          <thead>
            <tr style={{ borderBottom: '1px solid var(--line)' }}>
              <th style={{ padding: '6px 8px', textAlign: 'left', color: 'var(--ink-3)', fontSize: 11, fontWeight: 600 }}>Composition</th>
              {Object.entries(CAT_LABELS).filter(([k]) => k !== 's').map(([cat, label]) => (
                <th key={cat} style={{ padding: '6px 8px', textAlign: 'right', color: CAT_COLORS[cat], fontSize: 11, fontWeight: 700 }}>{label}</th>
              ))}
            </tr>
          </thead>
          <tbody>
            {[
              ['1 personne', [17009, 21805, 30549]],
              ['2 personnes', [24875, 31889, 44907]],
              ['3 personnes', [29917, 38349, 54071]],
              ['4 personnes', [34948, 44802, 63235]],
              ['5 personnes et +', [39992, 51281, 72400]],
            ].map(([label, vals]) => (
              <tr key={label} style={{ borderBottom: '1px solid var(--line-2)' }}>
                <td style={{ padding: '7px 8px', fontWeight: 500 }}>{label}</td>
                {vals.map((v, i) => (
                  <td key={i} style={{ padding: '7px 8px', textAlign: 'right', color: 'var(--ink-2)' }}>≤ {fmt(v)} €</td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
        <div style={{ fontSize: 11, color: 'var(--ink-4)', marginTop: 10 }}>
          ⚠ Zones A bis / A (Île-de-France + grandes métropoles) : plafonds plus élevés (+30%). Consulter le backend pour les valeurs exactes.
        </div>
      </Panel>
    </div>
  );
}

// ── Tab 4: Paramètres ──────────────────────────────────────────────────────────
function ParamsTab() {
  const [prefs, setPrefs] = useState(() => { try { return JSON.parse(localStorage.getItem('mar_prefs') || '{}'); } catch { return {}; } });
  const save = patch => { const next = { ...prefs, ...patch }; setPrefs(next); localStorage.setItem('mar_prefs', JSON.stringify(next)); };
  const p = k => e => save({ [k]: e.target.value });

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 680 }}>
      <Panel title="Workflow MAR" subtitle="Étapes et délais de traitement">
        <Field label="Délai alerte sans mise à jour (jours)">
          <Select value={prefs.alertDays ?? '30'} onChange={p('alertDays')} style={{ maxWidth: 200 }}>
            {['7','14','30','60','90'].map(v => <option key={v} value={v}>{v} jours</option>)}
          </Select>
        </Field>
        <Field label="Zone ANAH par défaut">
          <Select value={prefs.defaultZone ?? 'b2'} onChange={p('defaultZone')} style={{ maxWidth: 300 }}>
            {ZONES.map(z => <option key={z.value} value={z.value}>{z.value.toUpperCase()} — {z.label.split(' — ')[1]}</option>)}
          </Select>
        </Field>
      </Panel>
      <Panel title="Agrément MAR ANAH" subtitle="Statut de la demande d'agrément — délai ~3 mois">
        <div style={{ padding: '12px 14px', background: 'var(--paper-2)', border: '1px solid var(--line)', borderRadius: 6, fontSize: 12 }}>
          <div style={{ fontWeight: 600, marginBottom: 6 }}>⚠ Rappel : l'agrément MAR est obligatoire pour facturer l'accompagnement MaPrimeRénov'</div>
          <ul style={{ margin: 0, paddingLeft: 18, color: 'var(--ink-2)', lineHeight: 2 }}>
            <li>Déposer la demande sur <strong>france-renov.gouv.fr</strong></li>
            <li>Délai d'instruction : 3 mois incompressible</li>
            <li>Coût : ~500 € / an</li>
            <li>Requis : assurance RC Pro + références de chantier + formation DPE</li>
          </ul>
        </div>
        <div style={{ marginTop: 10 }}>
          <Field label="Statut de la demande MAR">
            <Select value={prefs.marStatus ?? 'non_depose'} onChange={p('marStatus')} style={{ maxWidth: 260 }}>
              <option value="non_depose">Non déposée</option>
              <option value="en_cours">Demande déposée — en instruction</option>
              <option value="obtenu">Agrément obtenu ✓</option>
              <option value="refuse">Refusé — recours en cours</option>
            </Select>
          </Field>
          {prefs.marStatus === 'obtenu' && <div style={{ marginTop: 4 }}><Field label="Date d'obtention"><Input type="date" value={prefs.marDate || ''} onChange={p('marDate')} style={{ maxWidth: 180 }} /></Field></div>}
        </div>
      </Panel>
      <Panel title="Informations légales" subtitle="À afficher dans les documents générés">
        <Field label="Nom de la structure MAR"><Input value={prefs.structureNom || ''} onChange={p('structureNom')} placeholder="Audits Énergies SAS" /></Field>
        <Field label="N° SIRET"><Input value={prefs.siret || ''} onChange={p('siret')} placeholder="123 456 789 00012" /></Field>
        <Field label="N° agrément MAR ANAH (une fois obtenu)"><Input value={prefs.agrementNum || ''} onChange={p('agrementNum')} placeholder="FR-MAR-XXXX-XXXX" /></Field>
      </Panel>
    </div>
  );
}

// ── Main ────────────────────────────────────────────────────────────────────────
function MaPrimeRenovPage() {
  const TABS = [
    { key: 'kanban', label: 'Tableau de bord', icon: Icon.kanban },
    { key: 'liste',  label: 'Liste dossiers',  icon: Icon.layers },
    { key: 'baremes',label: 'Barèmes ANAH',    icon: Icon.doc },
    { key: 'params', label: '⚙ Paramètres',   icon: null },
  ];
  const [tab, setTab] = useState('kanban');
  const [projects, setProjects] = useState([]);
  const [loading, setLoading] = useState(false);
  const [modalProject, setModalProject] = useState(null); // null | 'new' | project object

  const load = useCallback(async () => {
    setLoading(true);
    const d = await apiMAR('/projects').catch(() => ({ projects: [] }));
    setProjects(d.projects || []);
    setLoading(false);
  }, []);

  useEffect(() => { load(); }, [load]);

  const del = async (id) => {
    if (!confirm('Supprimer ce dossier ?')) return;
    await apiMAR(`/projects/${id}`, { method: 'DELETE' });
    load();
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
      {/* Header */}
      <div style={{ padding: '16px 24px 0', flexShrink: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
          <div>
            <h1 style={{ fontSize: 16, fontWeight: 700, margin: 0 }}>
              🏠 MaPrimeRénov' / MAR
            </h1>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 2 }}>Mon Accompagnateur Rénov' · Barèmes ANAH 2024 · Calcul primes automatique</div>
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <Badge tone="copper">M4 MaPrimeRénov'</Badge>
            <Btn variant="ghost" size="sm" icon={<Icon.refresh />} onClick={load}>Actualiser</Btn>
            <Btn variant="primary" size="sm" icon={<Icon.plus />} onClick={() => setModalProject('new')}>Nouveau dossier</Btn>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 0, borderBottom: '1px solid var(--line)' }}>
          {TABS.map(t => (
            <button key={t.key} onClick={() => setTab(t.key)}
              style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '8px 16px', fontSize: 13, fontWeight: tab === t.key ? 600 : 400, color: tab === t.key ? 'var(--ink)' : 'var(--ink-3)', borderBottom: tab === t.key ? '2px solid var(--signal)' : '2px solid transparent', background: 'none', border: 'none', borderBottom: tab === t.key ? '2px solid var(--signal)' : '2px solid transparent', cursor: 'pointer' }}>
              {t.icon && <t.icon />} {t.label}
            </button>
          ))}
        </div>
      </div>

      {/* Content */}
      <div style={{ flex: 1, overflow: 'auto', padding: '20px 24px 60px' }}>
        {tab === 'kanban'  && <KanbanTab projects={projects} onEdit={p => setModalProject(p)} onDelete={del} onRefresh={load} loading={loading} />}
        {tab === 'liste'   && <ListeTab  projects={projects} onEdit={p => setModalProject(p)} onDelete={del} loading={loading} />}
        {tab === 'baremes' && <BaremesTab />}
        {tab === 'params'  && <ParamsTab />}
      </div>

      {/* Modal dossier */}
      {modalProject && (
        <Modal title={modalProject === 'new' ? 'Nouveau dossier MaPrimeRénov\'' : `Dossier — ${modalProject.prenom || ''} ${modalProject.nom}`} onClose={() => setModalProject(null)} width={900}>
          <DossierForm
            initial={modalProject === 'new' ? null : modalProject}
            onSave={load}
            onClose={() => setModalProject(null)}
          />
        </Modal>
      )}
    </div>
  );
}

Object.assign(window, { MaPrimeRenovPage });
