/* global React */
// cpe-monitoring.jsx — M1 Décret Tertiaire + M2 Monitoring des consommations
// Portage du module CPE backend (Portfolio→Building→Meter→EnergyReading)
// Règles : 0 (UI immutable), 2 (live recalc), 3 (interconnexion), 5 (CRUD complet), 6 (paramètres)

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

const BASE = (window.AE_API && window.AE_API.BASE) || '';

// ── Constantes OPERAT (miroir tertiaire.js) ────────────────────────────────────
const OPERAT_OBJECTIVES = {
  bureaux:      { ref: 210, label: 'Bureaux' },
  enseignement: { ref: 230, label: 'Enseignement' },
  sante:        { ref: 280, label: 'Santé' },
  hotellerie:   { ref: 290, label: 'Hôtellerie' },
  commerce:     { ref: 220, label: 'Commerce' },
  logistique:   { ref: 90,  label: 'Logistique / Entrepôt' },
  restauration: { ref: 410, label: 'Restauration' },
  sport:        { ref: 250, label: 'Sport / Loisirs' },
  industrie:    { ref: 180, label: 'Industrie (tertiaire)' },
  default:      { ref: 220, label: 'Tertiaire (standard)' },
};
const USAGE_TYPES = Object.entries(OPERAT_OBJECTIVES).map(([k, v]) => ({ value: k, label: v.label }));
const METER_TYPES = ['elec', 'gaz', 'chaleur', 'fioul', 'froid', 'eau', 'autre'];
const METER_TYPE_LABELS = { elec: 'Électricité', gaz: 'Gaz naturel', chaleur: 'Réseau chaleur', fioul: 'Fioul', froid: 'Réseau froid', eau: 'Eau', autre: 'Autre' };
const METER_TYPE_COLORS = { elec: 'var(--signal)', gaz: 'var(--copper)', chaleur: 'var(--rouge)', fioul: '#8B6914', froid: 'var(--plasma)', eau: '#38BDF8', autre: 'var(--ink-3)' };
const ZONES_CLIMATIQUES = ['H1a', 'H1b', 'H1c', 'H2a', 'H2b', 'H2c', 'H2d', 'H3'];

// ── Helpers ────────────────────────────────────────────────────────────────────
function api(path, opts) {
  return fetch(BASE + path, { headers: { 'Content-Type': 'application/json' }, ...opts })
    .then(r => r.json());
}
function fmt(n, dec = 0) { return (n ?? 0).toLocaleString('fr-FR', { maximumFractionDigits: dec }); }
function fmtKwh(n) {
  if (n >= 1e6) return (n / 1e6).toFixed(2) + ' GWh';
  if (n >= 1e3) return (n / 1e3).toFixed(1) + ' MWh';
  return fmt(n) + ' kWh';
}
function fmtEur(n) {
  if (n >= 1e6) return (n / 1e6).toFixed(2) + ' M€';
  if (n >= 1e3) return (n / 1e3).toFixed(1) + ' k€';
  return fmt(n) + ' €';
}

// Conformity badge for OPERAT
function ConformBadge({ pct, gap, conforme }) {
  if (conforme) return <Badge tone="signal">✓ Conforme</Badge>;
  if (gap > 0)  return <Badge tone="rouge">✗ +{fmt(gap, 1)} kWhep/m²</Badge>;
  return <Badge tone="neutral">—</Badge>;
}

// Gauge bar for trajectory
function TrajectoryBar({ value, target, max, color }) {
  const pct = Math.min(100, (value / (max || 1)) * 100);
  const tPct = Math.min(100, (target / (max || 1)) * 100);
  return (
    <div style={{ position: 'relative', height: 10, background: 'var(--paper-3)', borderRadius: 99, overflow: 'visible' }}>
      <div style={{ position: 'absolute', left: 0, top: 0, height: '100%', width: pct + '%', background: color, borderRadius: 99, transition: 'width 600ms ease' }} />
      {/* Target marker */}
      <div style={{ position: 'absolute', top: -3, left: tPct + '%', width: 2, height: 16, background: 'var(--ink-2)', borderRadius: 1 }} title={`Objectif : ${fmt(target, 1)} kWhep/m²`} />
    </div>
  );
}

// Section panel used across tabs
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, color: 'var(--ink)' }}>{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>
  );
}

// Modal wrapper
function Modal({ title, onClose, children, width = 560 }) {
  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: '95vw', maxHeight: '90vh', overflow: 'auto', boxShadow: '0 24px 48px rgba(0,0,0,.18)' }} 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>
  );
}

// Field row for forms
function Field({ label, children, required }) {
  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}
    </div>
  );
}
function Input({ value, onChange, type = 'text', placeholder, step, min, max, disabled, style }) {
  const base = { 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 };
  return <input type={type} value={value} onChange={onChange} placeholder={placeholder} step={step} min={min} max={max} disabled={disabled} style={base} />;
}
function Select({ value, onChange, children, style }) {
  const base = { width: '100%', padding: '7px 10px', fontSize: 13, borderRadius: 6, border: '1px solid var(--line-2)', background: 'var(--paper-2)', color: 'var(--ink)', ...style };
  return <select value={value} onChange={onChange} style={base}>{children}</select>;
}

// ── Tab 1: Monitoring Dashboard ────────────────────────────────────────────────
function MonitoringDashboard({ summary, timeseries, loading }) {
  if (loading) return <div style={{ padding: 40, textAlign: 'center', color: 'var(--ink-3)', fontSize: 13 }}>Chargement des données…</div>;
  if (!summary) return <div style={{ padding: 40, textAlign: 'center', color: 'var(--ink-3)', fontSize: 13 }}>Aucune donnée disponible. Créez un portefeuille et des relevés d'énergie.</div>;

  const { portfolioCount = 0, buildingCount = 0, meterCount = 0, totalKwhLast12m = 0, totalCostLast12m = 0, anomalies = 0, buildings = [] } = summary;
  const sparkData = timeseries?.series?.map(s => s.totalKwh) || [];

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Hero 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: 'Conso totale 12 mois', value: fmtKwh(totalKwhLast12m), sub: `${buildingCount} bâtiment${buildingCount > 1 ? 's' : ''}`, spark: sparkData, color: 'var(--signal)' },
          { label: 'Coût énergie 12 mois', value: fmtEur(totalCostLast12m), sub: `${meterCount} compteur${meterCount > 1 ? 's' : ''}`, spark: sparkData.map(v => v * 0.15), color: 'var(--copper)', divider: true },
          { label: 'Portefeuilles', value: fmt(portfolioCount), sub: 'actifs', spark: [portfolioCount], color: 'var(--plasma)', divider: true },
          { label: 'Anomalies détectées', value: fmt(anomalies), sub: anomalies > 0 ? 'relevés manquants' : 'tout normal', spark: [], color: anomalies > 0 ? 'var(--rouge)' : 'var(--signal)', divider: true },
        ].map((kpi, i) => (
          <div key={i} style={{ padding: '20px 24px', borderLeft: kpi.divider ? '1px solid var(--line)' : 'none' }}>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', fontWeight: 500, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 8 }}>{kpi.label}</div>
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: 12, justifyContent: 'space-between' }}>
              <div>
                <div style={{ fontSize: 26, fontWeight: 700, color: 'var(--ink)', letterSpacing: '-0.02em', lineHeight: 1 }}>{kpi.value}</div>
                <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 4 }}>{kpi.sub}</div>
              </div>
              {kpi.spark.length > 1 && <Sparkline data={kpi.spark} width={80} height={24} stroke={kpi.color} fill={kpi.color.replace(')', ',0.12)').replace('var(', 'rgba(').replace('--signal', '63,224,124').replace('--copper', '230,138,0').replace('--rouge', '239,68,68')} strokeWidth={1.5} />}
            </div>
          </div>
        ))}
      </div>

      {/* Time series chart */}
      {timeseries?.series?.length > 0 && (
        <Panel title="Évolution mensuelle des consommations" subtitle={`${timeseries.months} derniers mois · tous compteurs`}>
          <div style={{ display: 'flex', alignItems: 'flex-end', gap: 2, height: 80 }}>
            {timeseries.series.map((s, i) => {
              const max = Math.max(...timeseries.series.map(x => x.totalKwh)) || 1;
              const h = Math.max(4, (s.totalKwh / max) * 76);
              return (
                <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3 }}>
                  <div style={{ width: '100%', height: h, background: 'var(--signal)', borderRadius: '3px 3px 0 0', opacity: 0.85, minWidth: 8 }} title={`${s.month} : ${fmtKwh(s.totalKwh)}`} />
                  <span style={{ fontSize: 9, color: 'var(--ink-4)', transform: 'rotate(-45deg)', whiteSpace: 'nowrap' }}>{s.month?.slice(5)}</span>
                </div>
              );
            })}
          </div>
        </Panel>
      )}

      {/* Buildings table */}
      {buildings.length > 0 && (
        <Panel title="Bâtiments — Consommations 12 mois" subtitle="classé par consommation décroissante">
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--line)' }}>
                {['Bâtiment', 'Portefeuille', 'Surface', 'Type', 'Conso 12m', 'Coût 12m', 'kWh/m²'].map(h => (
                  <th key={h} style={{ padding: '6px 8px', textAlign: 'left', color: 'var(--ink-3)', fontWeight: 600, fontSize: 11 }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {[...buildings].sort((a, b) => b.kwhLast12m - a.kwhLast12m).map(b => (
                <tr key={b.id} style={{ borderBottom: '1px solid var(--line-2)' }}>
                  <td style={{ padding: '7px 8px', fontWeight: 500, color: 'var(--ink)' }}>{b.name}</td>
                  <td style={{ padding: '7px 8px', color: 'var(--ink-3)' }}>{b.portfolioName}</td>
                  <td style={{ padding: '7px 8px', color: 'var(--ink-3)' }}>{b.surface ? fmt(b.surface) + ' m²' : '—'}</td>
                  <td style={{ padding: '7px 8px' }}><Badge tone="neutral">{OPERAT_OBJECTIVES[b.usageType]?.label || '—'}</Badge></td>
                  <td style={{ padding: '7px 8px', fontWeight: 600 }}>{fmtKwh(b.kwhLast12m)}</td>
                  <td style={{ padding: '7px 8px', color: 'var(--copper)' }}>{fmtEur(b.costLast12m)}</td>
                  <td style={{ padding: '7px 8px', color: 'var(--ink-2)' }}>{b.surface > 0 ? fmt(b.kwhLast12m / b.surface, 1) : '—'}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Panel>
      )}
    </div>
  );
}

// ── Tab 2: Bâtiments CRUD ──────────────────────────────────────────────────────
function BatimentsTab({ onRefresh }) {
  const [portfolios, setPortfolios] = useState([]);
  const [buildings, setBuildings] = useState([]);
  const [search, setSearch] = useState('');
  const [filterPf, setFilterPf] = useState('');
  const [modal, setModal] = useState(null); // null | 'portfolio' | 'building'
  const [editTarget, setEditTarget] = useState(null); // entity being edited
  const [form, setForm] = useState({});
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');

  const load = useCallback(async () => {
    const [pf, bld] = await Promise.all([
      api('/api/cpe/portfolios').catch(() => []),
      api('/api/cpe/buildings').catch(() => []),
    ]);
    setPortfolios(Array.isArray(pf) ? pf : (pf.portfolios || []));
    setBuildings(Array.isArray(bld) ? bld : (bld.buildings || []));
  }, []);

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

  const filteredBuildings = useMemo(() => buildings.filter(b => {
    const q = search.toLowerCase();
    const matchQ = !q || b.name?.toLowerCase().includes(q) || b.city?.toLowerCase().includes(q) || b.address?.toLowerCase().includes(q);
    const matchPf = !filterPf || String(b.portfolioId) === String(filterPf);
    return matchQ && matchPf;
  }), [buildings, search, filterPf]);

  const openNew = (type) => { setEditTarget(null); setForm(type === 'portfolio' ? { name: '', description: '' } : { name: '', portfolioId: portfolios[0]?.id || '', usageType: 'bureaux', surface: '', address: '', postalCode: '', city: '', anneeReference: new Date().getFullYear() - 1, consumptionRefEp: '', zoneClimatique: 'H2b' }); setModal(type); setError(''); };
  const openEdit = (type, entity) => { setEditTarget(entity); setForm({ ...entity }); setModal(type); setError(''); };

  const save = async () => {
    setSaving(true); setError('');
    try {
      if (modal === 'portfolio') {
        const method = editTarget ? 'PATCH' : 'POST';
        const url = editTarget ? `/api/cpe/portfolios/${editTarget.id}` : '/api/cpe/portfolios';
        await api(url, { method, body: JSON.stringify(form) });
      } else {
        // building — OPERAT fields via tertiaire PATCH or standard building endpoint
        const method = editTarget ? 'PATCH' : 'POST';
        const url = editTarget ? `/api/cpe/buildings/${editTarget.id}` : '/api/cpe/buildings';
        await api(url, { method, body: JSON.stringify(form) });
        // Also sync OPERAT fields via dedicated endpoint when editing
        if (editTarget) {
          await api(`/api/cpe/tertiaire/building/${editTarget.id}`, {
            method: 'PATCH',
            body: JSON.stringify({ anneeReference: form.anneeReference, consumptionRefEp: form.consumptionRefEp, usageType: form.usageType, surface: form.surface, zoneClimatique: form.zoneClimatique }),
          });
        }
      }
      setModal(null);
      await load();
      onRefresh && onRefresh();
    } catch (e) {
      setError(e.message || 'Erreur lors de la sauvegarde');
    }
    setSaving(false);
  };

  const del = async (type, id) => {
    if (!confirm('Supprimer cet élément ? Cette action est irréversible.')) return;
    await api(`/api/cpe/${type === 'portfolio' ? 'portfolios' : 'buildings'}/${id}`, { method: 'DELETE' });
    load();
  };

  const f = (k) => (e) => setForm(prev => ({ ...prev, [k]: e.target.value }));

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Portefeuilles */}
      <Panel
        title={`Portefeuilles (${portfolios.length})`}
        subtitle="Groupes de bâtiments — entité de reporting OPERAT"
        actions={<Btn variant="outline" size="sm" icon={<Icon.plus />} onClick={() => openNew('portfolio')}>Nouveau portefeuille</Btn>}
      >
        {portfolios.length === 0
          ? <div style={{ textAlign: 'center', padding: '20px 0', color: 'var(--ink-3)', fontSize: 13 }}>Aucun portefeuille. Créez-en un pour commencer.</div>
          : <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 10 }}>
              {portfolios.map(pf => {
                const bldCount = buildings.filter(b => b.portfolioId === pf.id).length;
                return (
                  <div key={pf.id} style={{ border: '1px solid var(--line)', borderRadius: 6, padding: '12px 14px', background: 'var(--paper-2)', display: 'flex', flexDirection: 'column', gap: 6 }}>
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                      <span style={{ fontWeight: 600, fontSize: 13 }}>{pf.name}</span>
                      <div style={{ display: 'flex', gap: 4 }}>
                        <Btn variant="ghost" size="sm" onClick={() => openEdit('portfolio', pf)} icon={<Icon.doc />} />
                        <Btn variant="ghost" size="sm" onClick={() => del('portfolio', pf.id)} icon={<Icon.cross />} style={{ color: 'var(--rouge)' }} />
                      </div>
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{bldCount} bâtiment{bldCount !== 1 ? 's' : ''}</div>
                    {pf.description && <div style={{ fontSize: 11, color: 'var(--ink-4)', marginTop: 2 }}>{pf.description}</div>}
                  </div>
                );
              })}
            </div>
        }
      </Panel>

      {/* Bâtiments */}
      <Panel
        title={`Bâtiments (${filteredBuildings.length}/${buildings.length})`}
        subtitle="Chaque bâtiment est lié à un portefeuille et peut avoir N compteurs"
        actions={
          <div style={{ display: 'flex', gap: 8 }}>
            <Input value={search} onChange={e => setSearch(e.target.value)} placeholder="Rechercher…" style={{ width: 160 }} />
            <Select value={filterPf} onChange={e => setFilterPf(e.target.value)} style={{ width: 140 }}>
              <option value="">Tous les PF</option>
              {portfolios.map(pf => <option key={pf.id} value={pf.id}>{pf.name}</option>)}
            </Select>
            <Btn variant="primary" size="sm" icon={<Icon.plus />} onClick={() => openNew('building')} disabled={portfolios.length === 0}>Nouveau bâtiment</Btn>
          </div>
        }
      >
        {filteredBuildings.length === 0
          ? <div style={{ textAlign: 'center', padding: '20px 0', color: 'var(--ink-3)', fontSize: 13 }}>
              {buildings.length === 0 ? 'Aucun bâtiment. Commencez par créer un portefeuille puis ajoutez des bâtiments.' : 'Aucun résultat.'}
            </div>
          : <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--line)' }}>
                  {['Bâtiment', 'Adresse', 'Type usage', 'Surface', 'Portefeuille', 'Zone', 'Réf. OPERAT', ''].map(h => (
                    <th key={h} style={{ padding: '6px 8px', textAlign: 'left', color: 'var(--ink-3)', fontWeight: 600, fontSize: 11 }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {filteredBuildings.map(b => {
                  const pf = portfolios.find(p => p.id === b.portfolioId);
                  return (
                    <tr key={b.id} style={{ borderBottom: '1px solid var(--line-2)' }}>
                      <td style={{ padding: '8px 8px', fontWeight: 500 }}>{b.name}</td>
                      <td style={{ padding: '8px 8px', color: 'var(--ink-3)', maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{[b.address, b.city].filter(Boolean).join(', ') || '—'}</td>
                      <td style={{ padding: '8px 8px' }}><Badge tone="neutral" variant="solid">{OPERAT_OBJECTIVES[b.usageType]?.label || 'Non défini'}</Badge></td>
                      <td style={{ padding: '8px 8px', color: 'var(--ink-2)' }}>{b.surface ? fmt(b.surface) + ' m²' : '—'}</td>
                      <td style={{ padding: '8px 8px', color: 'var(--ink-3)' }}>{pf?.name || '—'}</td>
                      <td style={{ padding: '8px 8px', color: 'var(--ink-3)' }}>{b.zoneClimatique || '—'}</td>
                      <td style={{ padding: '8px 8px', color: 'var(--ink-2)' }}>{b.anneeReference || '—'}</td>
                      <td style={{ padding: '8px 8px', display: 'flex', gap: 4 }}>
                        <Btn variant="ghost" size="sm" onClick={() => openEdit('building', b)} icon={<Icon.doc />} />
                        <Btn variant="ghost" size="sm" onClick={() => del('building', b.id)} icon={<Icon.cross />} style={{ color: 'var(--rouge)' }} />
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
        }
      </Panel>

      {/* Portfolio modal */}
      {modal === 'portfolio' && (
        <Modal title={editTarget ? 'Modifier le portefeuille' : 'Nouveau portefeuille'} onClose={() => setModal(null)}>
          <Field label="Nom" required><Input value={form.name || ''} onChange={f('name')} placeholder="Portefeuille tertiaire Seine-et-Marne" /></Field>
          <Field label="Description"><Input value={form.description || ''} onChange={f('description')} placeholder="Description libre" /></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={() => setModal(null)}>Annuler</Btn>
            <Btn variant="primary" onClick={save} disabled={saving || !form.name}>{saving ? 'Sauvegarde…' : editTarget ? 'Modifier' : 'Créer'}</Btn>
          </div>
        </Modal>
      )}

      {/* Building modal */}
      {modal === 'building' && (
        <Modal title={editTarget ? 'Modifier le bâtiment' : 'Nouveau bâtiment'} onClose={() => setModal(null)} width={640}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0 16px' }}>
            <Field label="Nom du bâtiment" required><Input value={form.name || ''} onChange={f('name')} placeholder="Siège social — Tour A" /></Field>
            <Field label="Portefeuille" required>
              <Select value={form.portfolioId || ''} onChange={f('portfolioId')}>
                <option value="">— Choisir —</option>
                {portfolios.map(pf => <option key={pf.id} value={pf.id}>{pf.name}</option>)}
              </Select>
            </Field>
            <Field label="Adresse"><Input value={form.address || ''} onChange={f('address')} placeholder="12 rue de la Paix" /></Field>
            <Field label="Code postal"><Input value={form.postalCode || ''} onChange={f('postalCode')} placeholder="75001" /></Field>
            <Field label="Ville"><Input value={form.city || ''} onChange={f('city')} placeholder="Paris" /></Field>
            <Field label="Zone climatique">
              <Select value={form.zoneClimatique || ''} onChange={f('zoneClimatique')}>
                <option value="">— Choisir —</option>
                {ZONES_CLIMATIQUES.map(z => <option key={z} value={z}>{z}</option>)}
              </Select>
            </Field>
            <Field label="Type d'usage (OPERAT)" required>
              <Select value={form.usageType || 'bureaux'} onChange={f('usageType')}>
                {USAGE_TYPES.map(u => <option key={u.value} value={u.value}>{u.label}</option>)}
              </Select>
            </Field>
            <Field label="Surface de référence thermique (m²)">
              <Input type="number" value={form.surface || ''} onChange={f('surface')} placeholder="1 500" min="0" />
            </Field>
          </div>
          <div style={{ borderTop: '1px solid var(--line)', paddingTop: 14, marginTop: 4 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 12 }}>⚡ Référence OPERAT (Décret Tertiaire)</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '0 16px' }}>
              <Field label="Année de référence">
                <Input type="number" value={form.anneeReference || ''} onChange={f('anneeReference')} placeholder="2010" min="1990" max={new Date().getFullYear()} />
              </Field>
              <Field label="Conso ref. EP (kWhep/m²/an)" >
                <Input type="number" value={form.consumptionRefEp || ''} onChange={f('consumptionRefEp')} placeholder={`ex: ${OPERAT_OBJECTIVES[form.usageType || 'bureaux']?.ref}`} min="0" step="0.1" />
              </Field>
              <Field label="Conso ref. EF (kWhef/m²/an)">
                <Input type="number" value={form.consumptionRefEf || ''} onChange={f('consumptionRefEf')} placeholder="Optionnel" min="0" step="0.1" />
              </Field>
            </div>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: -6 }}>
              Si non renseignée, la référence nationale ADEME ({OPERAT_OBJECTIVES[form.usageType || 'bureaux']?.ref} kWhep/m²/an pour {OPERAT_OBJECTIVES[form.usageType || 'bureaux']?.label}) sera utilisée.
            </div>
          </div>
          <Field label="Notes"><Input value={form.notes || ''} onChange={f('notes')} placeholder="Informations complémentaires…" /></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={() => setModal(null)}>Annuler</Btn>
            <Btn variant="primary" onClick={save} disabled={saving || !form.name || !form.portfolioId}>{saving ? 'Sauvegarde…' : editTarget ? 'Modifier' : 'Créer'}</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── Tab 3: Compteurs ────────────────────────────────────────────────────────────
function CompteursTab() {
  const [buildings, setBuildings] = useState([]);
  const [meters, setMeters] = useState([]);
  const [filterBld, setFilterBld] = useState('');
  const [filterType, setFilterType] = useState('');
  const [modal, setModal] = useState(false);
  const [editTarget, setEditTarget] = useState(null);
  const [form, setForm] = useState({});
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');

  const load = useCallback(async () => {
    const [bld, mtrs] = await Promise.all([
      api('/api/cpe/buildings').catch(() => []),
      api('/api/cpe/meters').catch(() => []),
    ]);
    setBuildings(Array.isArray(bld) ? bld : (bld.buildings || []));
    setMeters(Array.isArray(mtrs) ? mtrs : (mtrs.meters || []));
  }, []);

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

  const filtered = useMemo(() => meters.filter(m => {
    const mBld = !filterBld || String(m.buildingId) === String(filterBld);
    const mType = !filterType || m.type === filterType;
    return mBld && mType;
  }), [meters, filterBld, filterType]);

  const openNew = () => { setEditTarget(null); setForm({ buildingId: buildings[0]?.id || '', type: 'elec', reference: '', label: '', unit: 'kWh', source: 'manual', active: true }); setModal(true); setError(''); };
  const openEdit = (m) => { setEditTarget(m); setForm({ ...m }); setModal(true); setError(''); };
  const f = (k) => (e) => setForm(prev => ({ ...prev, [k]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }));

  const save = async () => {
    setSaving(true); setError('');
    try {
      const method = editTarget ? 'PATCH' : 'POST';
      const url = editTarget ? `/api/cpe/meters/${editTarget.id}` : '/api/cpe/meters';
      await api(url, { method, body: JSON.stringify(form) });
      setModal(false);
      load();
    } catch (e) { setError(e.message); }
    setSaving(false);
  };

  const del = async (id) => {
    if (!confirm('Supprimer ce compteur ? Tous ses relevés seront supprimés.')) return;
    await api(`/api/cpe/meters/${id}`, { method: 'DELETE' });
    load();
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <Panel
        title={`Compteurs (${filtered.length}/${meters.length})`}
        subtitle="Électricité, gaz, chaleur, eau… chaque compteur alimente les relevés"
        actions={
          <div style={{ display: 'flex', gap: 8 }}>
            <Select value={filterBld} onChange={e => setFilterBld(e.target.value)} style={{ width: 140 }}>
              <option value="">Tous bâtiments</option>
              {buildings.map(b => <option key={b.id} value={b.id}>{b.name}</option>)}
            </Select>
            <Select value={filterType} onChange={e => setFilterType(e.target.value)} style={{ width: 110 }}>
              <option value="">Tous types</option>
              {METER_TYPES.map(t => <option key={t} value={t}>{METER_TYPE_LABELS[t]}</option>)}
            </Select>
            <Btn variant="primary" size="sm" icon={<Icon.plus />} onClick={openNew} disabled={buildings.length === 0}>Nouveau compteur</Btn>
          </div>
        }
      >
        {filtered.length === 0
          ? <div style={{ textAlign: 'center', padding: '20px 0', color: 'var(--ink-3)', fontSize: 13 }}>Aucun compteur.</div>
          : <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--line)' }}>
                  {['Type', 'Référence', 'Label', 'Bâtiment', 'Source', 'Unité', '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(m => {
                  const bld = buildings.find(b => b.id === m.buildingId);
                  return (
                    <tr key={m.id} style={{ borderBottom: '1px solid var(--line-2)' }}>
                      <td style={{ padding: '7px 8px' }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                          <div style={{ width: 8, height: 8, borderRadius: '50%', background: METER_TYPE_COLORS[m.type] || 'var(--ink-4)', flexShrink: 0 }} />
                          <span style={{ fontWeight: 500 }}>{METER_TYPE_LABELS[m.type] || m.type}</span>
                        </div>
                      </td>
                      <td style={{ padding: '7px 8px' }}><RefChip r={m.reference || `CPT-${m.id}`} /></td>
                      <td style={{ padding: '7px 8px', color: 'var(--ink-2)' }}>{m.label || '—'}</td>
                      <td style={{ padding: '7px 8px', color: 'var(--ink-3)' }}>{bld?.name || '—'}</td>
                      <td style={{ padding: '7px 8px', color: 'var(--ink-3)' }}>{m.source || 'manual'}</td>
                      <td style={{ padding: '7px 8px', color: 'var(--ink-3)' }}>{m.unit || 'kWh'}</td>
                      <td style={{ padding: '7px 8px' }}><Dot tone={m.active !== false ? 'signal' : 'muted'} pulse={m.active !== false} /></td>
                      <td style={{ padding: '7px 8px', display: 'flex', gap: 4 }}>
                        <Btn variant="ghost" size="sm" onClick={() => openEdit(m)} icon={<Icon.doc />} />
                        <Btn variant="ghost" size="sm" onClick={() => del(m.id)} icon={<Icon.cross />} style={{ color: 'var(--rouge)' }} />
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
        }
      </Panel>

      {modal && (
        <Modal title={editTarget ? 'Modifier le compteur' : 'Nouveau compteur'} onClose={() => setModal(false)}>
          <Field label="Bâtiment" required>
            <Select value={form.buildingId || ''} onChange={f('buildingId')}>
              <option value="">— Choisir —</option>
              {buildings.map(b => <option key={b.id} value={b.id}>{b.name}</option>)}
            </Select>
          </Field>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0 16px' }}>
            <Field label="Type d'énergie" required>
              <Select value={form.type || 'elec'} onChange={f('type')}>
                {METER_TYPES.map(t => <option key={t} value={t}>{METER_TYPE_LABELS[t]}</option>)}
              </Select>
            </Field>
            <Field label="Unité">
              <Select value={form.unit || 'kWh'} onChange={f('unit')}>
                {['kWh', 'MWh', 'm³', 'L', 'kVA', 'autre'].map(u => <option key={u} value={u}>{u}</option>)}
              </Select>
            </Field>
            <Field label="Référence compteur"><Input value={form.reference || ''} onChange={f('reference')} placeholder="PDL-12345678" /></Field>
            <Field label="Label"><Input value={form.label || ''} onChange={f('label')} placeholder="Tableau général basse tension" /></Field>
            <Field label="Source des relevés">
              <Select value={form.source || 'manual'} onChange={f('source')}>
                {[['manual', 'Saisie manuelle'], ['csv', 'Import CSV'], ['imap', 'Email/IMAP'], ['api', 'API externe'], ['iot', 'Capteur IoT']].map(([v, l]) => <option key={v} value={v}>{l}</option>)}
              </Select>
            </Field>
            <Field label="Actif">
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, height: 34 }}>
                <input type="checkbox" checked={form.active !== false} onChange={f('active')} id="meter-active" />
                <label htmlFor="meter-active" style={{ fontSize: 12, color: 'var(--ink-2)' }}>Compteur actif (inclus dans les calculs)</label>
              </div>
            </Field>
          </div>
          {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={() => setModal(false)}>Annuler</Btn>
            <Btn variant="primary" onClick={save} disabled={saving || !form.buildingId}>{saving ? 'Sauvegarde…' : editTarget ? 'Modifier' : 'Créer'}</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── Tab 4: Relevés (import CSV + historique + qualité) ──────────────────────────
function RelevedsTab() {
  const [meters, setMeters] = useState([]);
  const [buildings, setBuildings] = useState([]);
  const [filterMeter, setFilterMeter] = useState('');
  const [readings, setReadings] = useState([]);
  const [quality, setQuality] = useState(null);
  const [importing, setImporting] = useState(false);
  const [importResult, setImportResult] = useState(null);
  const [modal, setModal] = useState(false);
  const [form, setForm] = useState({ meterId: '', periodStart: '', periodEnd: '', value: '', costHT: '' });
  const [saving, setSaving] = useState(false);
  const fileRef = useRef(null);

  const load = useCallback(async () => {
    const [mtrs, bld] = await Promise.all([
      api('/api/cpe/meters').catch(() => []),
      api('/api/cpe/buildings').catch(() => []),
    ]);
    const mArr = Array.isArray(mtrs) ? mtrs : (mtrs.meters || []);
    setMeters(mArr);
    setBuildings(Array.isArray(bld) ? bld : (bld.buildings || []));
    if (filterMeter || mArr.length > 0) {
      const mId = filterMeter || mArr[0]?.id;
      if (mId) loadReadings(mId);
    }
  }, [filterMeter]);

  const loadReadings = async (meterId) => {
    const [rds, qual] = await Promise.all([
      api(`/api/cpe/readings?meterId=${meterId}&limit=50`).catch(() => []),
      api(`/api/cpe/readings/quality/${meterId}`).catch(() => null),
    ]);
    setReadings(Array.isArray(rds) ? rds : (rds.readings || []));
    setQuality(qual);
  };

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

  const handleMeterChange = (mId) => {
    setFilterMeter(mId);
    setReadings([]);
    setQuality(null);
    if (mId) loadReadings(mId);
  };

  const importCSV = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setImporting(true); setImportResult(null);
    const fd = new FormData();
    fd.append('file', file);
    if (filterMeter) fd.append('meterId', filterMeter);
    try {
      const r = await fetch(`${BASE}/api/cpe/readings/import`, { method: 'POST', body: fd });
      const d = await r.json();
      setImportResult(d);
      if (filterMeter) loadReadings(filterMeter);
    } catch (err) {
      setImportResult({ error: err.message });
    }
    setImporting(false);
    e.target.value = '';
  };

  const exportCSV = () => {
    if (!filterMeter) return;
    window.open(`${BASE}/api/cpe/readings/export?meterId=${filterMeter}`, '_blank');
  };

  const saveReading = async () => {
    setSaving(true);
    try {
      await api('/api/cpe/readings', { method: 'POST', body: JSON.stringify({ ...form, value: parseFloat(form.value), costHT: form.costHT ? parseFloat(form.costHT) : undefined }) });
      setModal(false);
      if (filterMeter) loadReadings(filterMeter);
    } catch {}
    setSaving(false);
  };

  const openNew = () => {
    const today = new Date().toISOString().slice(0, 10);
    const lastMonth = new Date(new Date().setMonth(new Date().getMonth() - 1)).toISOString().slice(0, 10);
    setForm({ meterId: filterMeter || meters[0]?.id || '', periodStart: lastMonth, periodEnd: today, value: '', costHT: '' });
    setModal(true);
  };

  const f = (k) => (e) => setForm(prev => ({ ...prev, [k]: e.target.value }));

  const meterLabel = (m) => {
    const b = buildings.find(bld => bld.id === m.buildingId);
    return `${METER_TYPE_LABELS[m.type] || m.type} — ${b?.name || 'Inconnu'} (${m.reference || m.id})`;
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Sélecteur compteur + actions */}
      <Panel title="Relevés de consommation" subtitle="Historique mensuel et import en lot par CSV">
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center', marginBottom: 16 }}>
          <Select value={filterMeter} onChange={e => handleMeterChange(e.target.value)} style={{ width: 280 }}>
            <option value="">— Sélectionner un compteur —</option>
            {meters.map(m => <option key={m.id} value={m.id}>{meterLabel(m)}</option>)}
          </Select>
          <Btn variant="outline" size="sm" icon={<Icon.plus />} onClick={openNew} disabled={meters.length === 0}>Relevé manuel</Btn>
          <Btn variant="outline" size="sm" icon={<Icon.download />} onClick={() => fileRef.current?.click()} disabled={importing}>
            {importing ? 'Import en cours…' : 'Importer CSV'}
          </Btn>
          <input ref={fileRef} type="file" accept=".csv" style={{ display: 'none' }} onChange={importCSV} />
          {filterMeter && <Btn variant="ghost" size="sm" icon={<Icon.download />} onClick={exportCSV}>Exporter CSV</Btn>}
        </div>

        {/* Import result */}
        {importResult && (
          <div style={{ padding: '10px 14px', background: importResult.error ? 'var(--rouge-tint)' : 'var(--signal-tint)', border: `1px solid ${importResult.error ? 'var(--rouge)' : 'var(--signal-soft)'}`, borderRadius: 6, marginBottom: 14, fontSize: 12 }}>
            {importResult.error ? `❌ Erreur : ${importResult.error}` : `✓ Import réussi — ${importResult.imported || 0} relevés créés, ${importResult.skipped || 0} ignorés (doublons)`}
          </div>
        )}

        {/* Quality score */}
        {quality && (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10, marginBottom: 14, padding: '12px 0', borderBottom: '1px solid var(--line)' }}>
            {[
              { label: 'Couverture', value: `${quality.coverageScore ?? '—'} %`, tone: (quality.coverageScore || 0) >= 80 ? 'signal' : (quality.coverageScore || 0) >= 50 ? 'amber' : 'rouge' },
              { label: 'Relevés manquants', value: quality.missingMonths ?? '—', tone: (quality.missingMonths || 0) === 0 ? 'signal' : 'amber' },
              { label: 'Doublons', value: quality.duplicates ?? 0, tone: (quality.duplicates || 0) === 0 ? 'signal' : 'rouge' },
              { label: 'Dernière entrée', value: quality.lastEntry ? quality.lastEntry.slice(0, 10) : '—', tone: 'neutral' },
            ].map((kpi, i) => (
              <div key={i} style={{ textAlign: 'center' }}>
                <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 4 }}>{kpi.label}</div>
                <Badge tone={kpi.tone}>{kpi.value}</Badge>
              </div>
            ))}
          </div>
        )}

        {/* Table */}
        {readings.length === 0
          ? <div style={{ textAlign: 'center', padding: '20px 0', color: 'var(--ink-3)', fontSize: 13 }}>
              {!filterMeter ? 'Sélectionnez un compteur pour voir ses relevés.' : 'Aucun relevé. Importez un CSV ou saisissez manuellement.'}
            </div>
          : (
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--line)' }}>
                  {['Période début', 'Période fin', 'Consommation', 'Coût HT', 'Source', 'Qualité', ''].map(h => (
                    <th key={h} style={{ padding: '6px 8px', textAlign: 'left', color: 'var(--ink-3)', fontWeight: 600, fontSize: 11 }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {readings.map(r => (
                  <tr key={r.id} style={{ borderBottom: '1px solid var(--line-2)' }}>
                    <td style={{ padding: '7px 8px' }}>{r.periodStart}</td>
                    <td style={{ padding: '7px 8px', color: 'var(--ink-3)' }}>{r.periodEnd || '—'}</td>
                    <td style={{ padding: '7px 8px', fontWeight: 600 }}>{fmtKwh(r.value)}</td>
                    <td style={{ padding: '7px 8px', color: 'var(--copper)' }}>{r.costHT ? fmtEur(r.costHT) : '—'}</td>
                    <td style={{ padding: '7px 8px', color: 'var(--ink-3)' }}>{r.source || 'manual'}</td>
                    <td style={{ padding: '7px 8px' }}><Dot tone={r.qualityScore >= 80 ? 'signal' : r.qualityScore >= 50 ? 'amber' : 'rouge'} /></td>
                    <td style={{ padding: '7px 8px' }}>
                      <Btn variant="ghost" size="sm" onClick={() => api(`/api/cpe/readings/${r.id}`, { method: 'DELETE' }).then(() => loadReadings(filterMeter))} icon={<Icon.cross />} style={{ color: 'var(--rouge)' }} />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )
        }
      </Panel>

      {/* Relevé manuel modal */}
      {modal && (
        <Modal title="Nouveau relevé manuel" onClose={() => setModal(false)}>
          <Field label="Compteur" required>
            <Select value={form.meterId || ''} onChange={f('meterId')}>
              <option value="">— Choisir —</option>
              {meters.map(m => <option key={m.id} value={m.id}>{meterLabel(m)}</option>)}
            </Select>
          </Field>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0 16px' }}>
            <Field label="Date début de période" required><Input type="date" value={form.periodStart} onChange={f('periodStart')} /></Field>
            <Field label="Date fin de période"><Input type="date" value={form.periodEnd} onChange={f('periodEnd')} /></Field>
            <Field label="Consommation (kWh)" required><Input type="number" value={form.value} onChange={f('value')} placeholder="1 250" min="0" step="0.01" /></Field>
            <Field label="Coût HT (€)"><Input type="number" value={form.costHT} onChange={f('costHT')} placeholder="185.00" min="0" step="0.01" /></Field>
          </div>
          <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 8 }}>
            <Btn variant="ghost" onClick={() => setModal(false)}>Annuler</Btn>
            <Btn variant="primary" onClick={saveReading} disabled={saving || !form.meterId || !form.periodStart || !form.value}>{saving ? 'Sauvegarde…' : 'Enregistrer'}</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── Tab 5: Décret Tertiaire / OPERAT ───────────────────────────────────────────
function DecretTertiaireTab() {
  const [buildings, setBuildings] = useState([]);
  const [selectedBld, setSelectedBld] = useState('');
  const [year, setYear] = useState(new Date().getFullYear());
  const [trajectory, setTrajectory] = useState(null);
  const [loading, setLoading] = useState(false);
  const [exportYear, setExportYear] = useState(new Date().getFullYear());
  const [portfolios, setPortfolios] = useState([]);
  const [exportPf, setExportPf] = useState('');

  useEffect(() => {
    Promise.all([
      api('/api/cpe/buildings').catch(() => []),
      api('/api/cpe/portfolios').catch(() => []),
    ]).then(([bld, pf]) => {
      const bArr = Array.isArray(bld) ? bld : (bld.buildings || []);
      setBuildings(bArr);
      setPortfolios(Array.isArray(pf) ? pf : (pf.portfolios || []));
      if (bArr.length > 0) setSelectedBld(bArr[0].id);
    });
  }, []);

  useEffect(() => {
    if (!selectedBld) return;
    setLoading(true);
    api(`/api/cpe/tertiaire/trajectory/${selectedBld}?year=${year}`)
      .then(d => { setTrajectory(d.buildingId ? d : null); })
      .catch(() => setTrajectory(null))
      .finally(() => setLoading(false));
  }, [selectedBld, year]);

  const exportOPERAT = () => {
    const q = exportPf ? `portfolioId=${exportPf}&year=${exportYear}` : `year=${exportYear}`;
    window.open(`${BASE}/api/cpe/tertiaire/export-operat?${q}`, '_blank');
  };

  const maxRef = trajectory ? trajectory.consumptionRefEp * 1.1 : 300;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Controls */}
      <Panel title="Trajectoire OPERAT — Décret Tertiaire" subtitle="Loi ELAN 2018 · Objectifs -40% 2030 / -50% 2040 / -60% 2050 vs. référence">
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center', marginBottom: 20 }}>
          <Select value={selectedBld} onChange={e => setSelectedBld(e.target.value)} style={{ width: 240 }}>
            <option value="">— Sélectionner un bâtiment —</option>
            {buildings.map(b => <option key={b.id} value={b.id}>{b.name}</option>)}
          </Select>
          <Select value={year} onChange={e => setYear(Number(e.target.value))} style={{ width: 90 }}>
            {Array.from({ length: 10 }, (_, i) => new Date().getFullYear() - i).map(y => <option key={y} value={y}>{y}</option>)}
          </Select>
        </div>

        {loading && <div style={{ textAlign: 'center', padding: 20, color: 'var(--ink-3)', fontSize: 13 }}>Calcul en cours…</div>}

        {!loading && trajectory && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
            {/* Header badges */}
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
              <Badge tone="neutral">{trajectory.usageLabel}</Badge>
              <Badge tone="neutral">{trajectory.surface} m²</Badge>
              {trajectory.anneeReference && <Badge tone="neutral">Réf. {trajectory.anneeReference}</Badge>}
              <ConformBadge conforme={trajectory.conforme2030} gap={trajectory.gap2030} />
            </div>

            {/* 3-column KPIs */}
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
              {[
                { label: 'Conso actuelle', value: `${fmt(trajectory.consoEpM2, 1)} kWhep/m²/an`, sub: `${fmtKwh(trajectory.consoEpTotalKwh)} total EP`, color: 'var(--ink)' },
                { label: 'Réf. OPERAT', value: `${fmt(trajectory.consumptionRefEp, 1)} kWhep/m²/an`, sub: `Année de référence : ${trajectory.anneeReference || '—'}`, color: 'var(--ink-3)' },
                { label: 'Réduction réalisée', value: `${fmt(trajectory.reductionPct, 1)} %`, sub: trajectory.reductionPct >= 40 ? '✓ Objectif 2030 atteint' : `${fmt(40 - trajectory.reductionPct, 1)} % manquants pour 2030`, color: trajectory.reductionPct >= 40 ? 'var(--signal)' : trajectory.reductionPct >= 20 ? 'var(--amber)' : 'var(--rouge)' },
              ].map((kpi, i) => (
                <div key={i} style={{ border: '1px solid var(--line)', borderRadius: 6, padding: '14px 16px', background: 'var(--paper-2)' }}>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 6 }}>{kpi.label}</div>
                  <div style={{ fontSize: 20, fontWeight: 700, color: kpi.color, letterSpacing: '-0.02em' }}>{kpi.value}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-4)', marginTop: 3 }}>{kpi.sub}</div>
                </div>
              ))}
            </div>

            {/* Objectifs par horizon */}
            <div>
              <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 10 }}>Trajectoire par horizon</div>
              {[
                { year: 2030, target: trajectory.obj2030, gap: trajectory.gap2030, pct: 40, conforme: trajectory.conforme2030 },
                { year: 2040, target: trajectory.obj2040, gap: trajectory.gap2040, pct: 50, conforme: trajectory.conforme2040 },
                { year: 2050, target: trajectory.obj2050, gap: trajectory.gap2050, pct: 60, conforme: trajectory.conforme2050 },
              ].map(o => (
                <div key={o.year} style={{ display: 'grid', gridTemplateColumns: '60px 1fr 120px 100px', gap: 12, alignItems: 'center', marginBottom: 12 }}>
                  <div style={{ fontWeight: 700, fontSize: 13, color: o.conforme ? 'var(--signal)' : 'var(--rouge)' }}>{o.year}</div>
                  <div>
                    <TrajectoryBar
                      value={trajectory.consoEpM2}
                      target={o.target}
                      max={maxRef}
                      color={o.conforme ? 'var(--signal)' : trajectory.consoEpM2 - o.target < o.target * 0.3 ? 'var(--amber)' : 'var(--rouge)'}
                    />
                    <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 3, fontSize: 10, color: 'var(--ink-4)' }}>
                      <span>0</span>
                      <span>Objectif : {fmt(o.target, 1)} kWhep/m²</span>
                      <span>{fmt(maxRef, 0)}</span>
                    </div>
                  </div>
                  <div style={{ fontSize: 12, fontWeight: 500, color: 'var(--ink-2)' }}>–{o.pct}% de réf.</div>
                  <ConformBadge conforme={o.conforme} gap={o.gap} />
                </div>
              ))}
            </div>

            {/* By type breakdown */}
            {Object.keys(trajectory.byType).length > 0 && (
              <div>
                <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 10 }}>Détail par énergie ({year})</div>
                <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
                  {Object.entries(trajectory.byType).map(([type, kwh]) => (
                    <div key={type} style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '6px 12px', border: '1px solid var(--line)', borderRadius: 6, background: 'var(--paper-2)' }}>
                      <div style={{ width: 8, height: 8, borderRadius: '50%', background: METER_TYPE_COLORS[type] || 'var(--ink-4)' }} />
                      <span style={{ fontSize: 12, fontWeight: 500 }}>{METER_TYPE_LABELS[type] || type}</span>
                      <span style={{ fontSize: 12, color: 'var(--ink-3)' }}>{fmtKwh(kwh)}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}

        {!loading && !trajectory && selectedBld && (
          <div style={{ textAlign: 'center', padding: '20px 0', color: 'var(--ink-3)', fontSize: 13 }}>
            Aucune donnée pour {year}. Importez des relevés pour ce bâtiment.
          </div>
        )}
      </Panel>

      {/* Export OPERAT */}
      <Panel title="Export OPERAT (CSV officiel)" subtitle="Format compatible avec la plateforme OPERAT de l'ADEME">
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
          <div style={{ fontSize: 12, color: 'var(--ink-3)', marginRight: 8 }}>Exporter l'année :</div>
          <Select value={exportYear} onChange={e => setExportYear(Number(e.target.value))} style={{ width: 90 }}>
            {Array.from({ length: 10 }, (_, i) => new Date().getFullYear() - i).map(y => <option key={y} value={y}>{y}</option>)}
          </Select>
          <Select value={exportPf} onChange={e => setExportPf(e.target.value)} style={{ width: 180 }}>
            <option value="">Tous les portefeuilles</option>
            {portfolios.map(pf => <option key={pf.id} value={pf.id}>{pf.name}</option>)}
          </Select>
          <Btn variant="primary" size="sm" icon={<Icon.download />} onClick={exportOPERAT} disabled={buildings.length === 0}>
            Télécharger CSV OPERAT
          </Btn>
        </div>
        <div style={{ marginTop: 12, padding: '10px 14px', background: 'var(--paper-2)', borderRadius: 6, border: '1px solid var(--line)', fontSize: 12, color: 'var(--ink-3)' }}>
          Le CSV généré contient tous les champs requis par la plateforme OPERAT (ADEME) : identifiant bâtiment, SRT, catégorie d'activité, consommations par énergie en kWhef, consommation totale en kWhep, objectifs 2030/2040/2050 et statut de conformité.
        </div>
      </Panel>
    </div>
  );
}

// ── Tab 6: Paramètres (Règle n°6) ──────────────────────────────────────────────
function ParametresTab() {
  const [prefs, setPrefs] = useState(() => {
    try { return JSON.parse(localStorage.getItem('cpe_prefs') || '{}'); } catch { return {}; }
  });
  const save = (patch) => {
    const next = { ...prefs, ...patch };
    setPrefs(next);
    localStorage.setItem('cpe_prefs', JSON.stringify(next));
  };
  const p = (k) => (e) => save({ [k]: e.target.value });
  const pb = (k) => (e) => save({ [k]: e.target.checked });

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 720 }}>
      <Panel title="Alertes & Anomalies" subtitle="Déclencheurs d'alertes dans le monitoring">
        <Field label="Seuil d'alerte absence de relevé (mois)">
          <Select value={prefs.alertMissingMonths ?? '3'} onChange={p('alertMissingMonths')} style={{ maxWidth: 200 }}>
            {['1', '2', '3', '6', '12'].map(v => <option key={v} value={v}>{v} mois</option>)}
          </Select>
        </Field>
        <Field label="Variation anormale (%)" >
          <Select value={prefs.alertVariationPct ?? '50'} onChange={p('alertVariationPct')} style={{ maxWidth: 200 }}>
            {['20', '30', '50', '75', '100'].map(v => <option key={v} value={v}>{v} %</option>)}
          </Select>
        </Field>
        <Field label="">
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <input type="checkbox" id="alert-email" checked={prefs.alertEmail !== false} onChange={pb('alertEmail')} />
            <label htmlFor="alert-email" style={{ fontSize: 12, color: 'var(--ink-2)' }}>Recevoir les alertes par email (bus événements)</label>
          </div>
        </Field>
      </Panel>

      <Panel title="Référence OPERAT par défaut" subtitle="Valeurs préremplies lors de la création d'un nouveau bâtiment">
        <Field label="Année de référence par défaut">
          <Select value={prefs.defaultRefYear ?? '2010'} onChange={p('defaultRefYear')} style={{ maxWidth: 200 }}>
            {['2005', '2010', '2015', '2019', '2020'].map(v => <option key={v} value={v}>{v}</option>)}
          </Select>
        </Field>
        <Field label="Facteur coût électricité (€/kWh)">
          <Input type="number" value={prefs.elecTariff ?? '0.18'} onChange={p('elecTariff')} style={{ maxWidth: 180 }} step="0.001" min="0" />
        </Field>
        <Field label="Facteur coût gaz (€/kWh)">
          <Input type="number" value={prefs.gazTariff ?? '0.08'} onChange={p('gazTariff')} style={{ maxWidth: 180 }} step="0.001" min="0" />
        </Field>
      </Panel>

      <Panel title="Affichage & Rapports" subtitle="Préférences de présentation">
        <Field label="Nombre de mois dans les graphiques">
          <Select value={prefs.chartMonths ?? '12'} onChange={p('chartMonths')} style={{ maxWidth: 200 }}>
            {['6', '12', '24', '36'].map(v => <option key={v} value={v}>{v} mois</option>)}
          </Select>
        </Field>
        <Field label="Unité d'affichage par défaut">
          <Select value={prefs.displayUnit ?? 'kwh'} onChange={p('displayUnit')} style={{ maxWidth: 200 }}>
            <option value="kwh">kWh</option>
            <option value="mwh">MWh</option>
            <option value="kwh_m2">kWh/m²</option>
            <option value="ep">kWhep</option>
          </Select>
        </Field>
        <Field label="">
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <input type="checkbox" id="show-operat" checked={prefs.showOperatBanner !== false} onChange={pb('showOperatBanner')} />
            <label htmlFor="show-operat" style={{ fontSize: 12, color: 'var(--ink-2)' }}>Afficher le bandeau de conformité OPERAT sur le monitoring</label>
          </div>
        </Field>
      </Panel>

      <Panel title="Facteurs de conversion kWhef → kWhep" subtitle="Source : ADEME / Arrêté du 15 septembre 2006 — modifiables si nouvelle publication">
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '0 24px' }}>
          {[['elec', 'Électricité', 2.3], ['gaz', 'Gaz naturel', 1.0], ['fioul', 'Fioul domestique', 1.0], ['chaleur', 'Réseau de chaleur', 0.77], ['froid', 'Réseau de froid', 0.77]].map(([k, label, def]) => (
            <Field key={k} label={`${label} (×)`}>
              <Input type="number" value={prefs[`factor_${k}`] ?? String(def)} onChange={p(`factor_${k}`)} style={{ maxWidth: 120 }} step="0.01" min="0.1" max="5" />
            </Field>
          ))}
        </div>
        <div style={{ fontSize: 11, color: 'var(--ink-4)', marginTop: 4 }}>
          Note : Ces facteurs sont enregistrés localement. Pour une mise à jour globale (multi-utilisateurs), modifiez directement le fichier <code>modules/cpe/routes/tertiaire.js</code>.
        </div>
      </Panel>
    </div>
  );
}

// ── Main component ─────────────────────────────────────────────────────────────
function CPEMonitoringPage() {
  const TABS = [
    { key: 'monitoring',  label: 'Monitoring',       icon: Icon.chart },
    { key: 'batiments',   label: 'Bâtiments',        icon: Icon.home },
    { key: 'compteurs',   label: 'Compteurs',        icon: Icon.bolt },
    { key: 'releves',     label: 'Relevés',          icon: Icon.layers },
    { key: 'tertiaire',   label: 'Décret Tertiaire', icon: Icon.shield },
    { key: 'params',      label: '⚙ Paramètres',    icon: null },
  ];
  const [tab, setTab] = useState('monitoring');
  const [summary, setSummary] = useState(null);
  const [timeseries, setTimeseries] = useState(null);
  const [loadingDash, setLoadingDash] = useState(false);
  const [rev, setRev] = useState(0); // refresh trigger

  const prefs = (() => { try { return JSON.parse(localStorage.getItem('cpe_prefs') || '{}'); } catch { return {}; } })();
  const months = prefs.chartMonths || 12;

  useEffect(() => {
    setLoadingDash(true);
    Promise.all([
      api('/api/cpe/tertiaire/summary').catch(() => null),
      api(`/api/cpe/tertiaire/timeseries?months=${months}`).catch(() => null),
    ]).then(([s, t]) => {
      setSummary(s);
      setTimeseries(t);
      setLoadingDash(false);
    });
  }, [rev, months]);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
      {/* Page 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, color: 'var(--ink)', margin: 0 }}>
              <Icon.bolt style={{ display: 'inline', marginRight: 8, color: 'var(--signal)' }} />
              Énergie & CPE
            </h1>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 2 }}>Contrat de Performance Énergétique · Décret Tertiaire (OPERAT) · Monitoring des consommations</div>
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <Badge tone="copper">M1 Décret Tertiaire</Badge>
            <Badge tone="plasma">M2 Monitoring</Badge>
            <Btn variant="ghost" size="sm" icon={<Icon.refresh />} onClick={() => setRev(v => v + 1)}>Actualiser</Btn>
          </div>
        </div>

        {/* OPERAT conformity banner */}
        {prefs.showOperatBanner !== false && summary && summary.buildingCount > 0 && (
          <div style={{ padding: '8px 14px', background: 'var(--paper-2)', border: '1px solid var(--line)', borderRadius: 6, marginBottom: 14, fontSize: 12, display: 'flex', alignItems: 'center', gap: 12 }}>
            <Icon.shield style={{ color: 'var(--copper)', flexShrink: 0 }} />
            <span style={{ color: 'var(--ink-2)' }}>
              <strong>{summary.buildingCount} bâtiment{summary.buildingCount > 1 ? 's' : ''}</strong> surveillé{summary.buildingCount > 1 ? 's' : ''} · Décret Tertiaire : objectifs {'-'}40% en 2030, {'-'}50% en 2040, {'-'}60% en 2050 vs. année de référence
            </span>
            {summary.anomalies > 0 && <Badge tone="amber">{summary.anomalies} anomalie{summary.anomalies > 1 ? 's' : ''}</Badge>}
          </div>
        )}

        {/* Tabs */}
        <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(--ink)' : '2px solid transparent',
                background: 'none', border: 'none', borderBottom: tab === t.key ? '2px solid var(--signal)' : '2px solid transparent',
                cursor: 'pointer', transition: 'all 120ms', letterSpacing: 0,
              }}
            >
              {t.icon && <t.icon />} {t.label}
            </button>
          ))}
        </div>
      </div>

      {/* Content */}
      <div style={{ flex: 1, overflow: 'auto', padding: '20px 24px 60px' }}>
        {tab === 'monitoring'  && <MonitoringDashboard summary={summary} timeseries={timeseries} loading={loadingDash} />}
        {tab === 'batiments'   && <BatimentsTab onRefresh={() => setRev(v => v + 1)} />}
        {tab === 'compteurs'   && <CompteursTab />}
        {tab === 'releves'     && <RelevedsTab />}
        {tab === 'tertiaire'   && <DecretTertiaireTab />}
        {tab === 'params'      && <ParametresTab />}
      </div>
    </div>
  );
}

Object.assign(window, { CPEMonitoringPage });
