// ─── AppelsFonds.jsx — Écran dédié appels de fonds (Phase 2, lecture seule) ───
// Pas de build, pas d'import/export — tout est global (React CDN).
// Données : GET /api/appels-eg (enrichi : montant_attendu, etat, programme_nom,
// travaux_reel). L'état "payé" (réconciliation) et la zone "À vérifier" arrivent
// dans un second temps. Les boutons d'action sont INERTES en Phase 2.

function AppelsFondsView({ C, projects }) {
  const [appels, setAppels]   = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError]     = React.useState(null);
  const [prog, setProg]       = React.useState('');
  const [openLots, setOpenLots] = React.useState(new Set());

  // ── États du workflow ──────────────────────────────────────────────────────
  const ETATS = {
    archi_relancer:   { label: 'Archi à relancer',          color: '#0C447C', bg: '#E6F1FB', dot: '#185FA5', action: 'Relancer' },
    attente_attest:   { label: 'Attente attestation',       color: '#633806', bg: '#FAEEDA', dot: '#BA7517', action: 'Relancer' },
    facture:          { label: 'Facture à envoyer',         color: '#26215C', bg: '#EEEDFE', dot: '#534AB7', action: 'Générer' },
    attente_paiement: { label: 'Envoyé — attente paiement', color: '#712B13', bg: '#FAECE7', dot: '#D85A30', action: 'Voir' },
    partiel:          { label: 'Partiellement payé',        color: '#633806', bg: '#FAEEDA', dot: '#BA7517', action: 'Voir' },
    paye:             { label: 'Payé',                       color: '#173404', bg: '#EAF3DE', dot: '#639922', action: 'Voir' },
  };
  const PRIO = { archi_relancer: 0, attente_attest: 1, facture: 2, attente_paiement: 3, partiel: 4, paye: 9 };
  const BUCKET_ORDER = ['paye', 'attente_paiement', 'facture', 'attente_attest', 'archi_relancer', 'partiel'];

  function em(e) { return ETATS[e] || { label: e || '?', color: C.muted, bg: C.bg, dot: C.muted, action: 'Voir' }; }

  // ── Chargement ─────────────────────────────────────────────────────────────
  async function load() {
    setLoading(true); setError(null);
    try {
      const r = await fetch('/api/appels-eg');
      if (!r.ok) throw new Error('Erreur ' + r.status);
      setAppels(await r.json());
    } catch (e) { setError(e.message); }
    finally { setLoading(false); }
  }
  React.useEffect(() => { load(); }, []);

  // ── Helpers ────────────────────────────────────────────────────────────────
  function eur(n) {
    if (n == null || n === '') return '—';
    return Number(n).toLocaleString('fr-FR', { maximumFractionDigits: 0 }) + ' €';
  }
  function pct(n) {
    if (n == null || n === '') return '—';
    return (Math.round(Number(n) * 100) / 100) + ' %';
  }
  // Montant d'un appel : montant_client réel (stocké) en priorité, sinon estimé.
  function mont(a) {
    if (a.montant_client != null && a.montant_client !== '') return a.montant_client;
    return a.montant_attendu;
  }
  function fmtDate(iso) {
    if (!iso) return null;
    const d = new Date(iso);
    if (isNaN(d)) return null;
    return d.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: '2-digit' });
  }
  function progName(id) {
    const a = appels.find(x => x.programme_id === id && x.programme_nom);
    if (a) return a.programme_nom;
    const p = (projects || []).find(x => x.id === id);
    return (p && (p.nom || p.ville)) || id;
  }

  // ── Dérivés ────────────────────────────────────────────────────────────────
  const enCours = appels
    .filter(a => a.etat !== 'paye')
    .slice()
    .sort((a, b) => (PRIO[a.etat] ?? 8) - (PRIO[b.etat] ?? 8));

  const mAppelsEnCours = enCours.length;
  const mATraiter      = appels.filter(a => ['archi_relancer', 'attente_attest', 'facture'].includes(a.etat)).length;
  const mAttenteAttest = appels.filter(a => ['archi_relancer', 'attente_attest'].includes(a.etat)).length;
  const mEnAttPaie     = appels.filter(a => a.etat === 'attente_paiement').reduce((s, a) => s + (Number(mont(a)) || 0), 0);

  const programmes = React.useMemo(() => {
    const m = new Map();
    appels.forEach(a => { if (!m.has(a.programme_id)) m.set(a.programme_id, progName(a.programme_id)); });
    return [...m.entries()].sort((x, y) => String(x[1]).localeCompare(String(y[1]), 'fr'));
  }, [appels]);

  React.useEffect(() => {
    if (!prog && programmes.length) setProg(programmes[0][0]);
  }, [programmes, prog]);

  const progAppels = appels.filter(a => a.programme_id === prog);

  // Cumul par statut (programme sélectionné)
  const cumul = React.useMemo(() => {
    const tot = {}, cnt = {}; let grand = 0;
    progAppels.forEach(a => {
      const m = Number(mont(a)) || 0;
      tot[a.etat] = (tot[a.etat] || 0) + m; cnt[a.etat] = (cnt[a.etat] || 0) + 1; grand += m;
    });
    return { tot, cnt, grand };
  }, [prog, appels]);

  // Groupement par lot
  const lots = React.useMemo(() => {
    const by = {};
    progAppels.forEach(a => { const k = String(a.lot_id); (by[k] = by[k] || []).push(a); });
    return Object.keys(by)
      .sort((x, y) => (Number(x) || 0) - (Number(y) || 0))
      .map(k => ({
        lot: k,
        appels: by[k].slice().sort((p, q) => new Date(p.created_at || 0) - new Date(q.created_at || 0)),
        travaux: by[k][0] && by[k][0].travaux_reel,
        cumul: by[k][0] ? Number(by[k][0].pct_cumule) || 0 : 0,
      }));
  }, [prog, appels]);

  function toggleLot(k) {
    setOpenLots(prev => { const n = new Set(prev); n.has(k) ? n.delete(k) : n.add(k); return n; });
  }

  // ── Styles ─────────────────────────────────────────────────────────────────
  const card = { background: C.card, border: '1px solid ' + C.border, borderRadius: 12 };
  const th = { padding: '8px 12px', textAlign: 'left', fontSize: 11, fontWeight: 700, color: C.muted, borderBottom: '1px solid ' + C.border, whiteSpace: 'nowrap' };
  const td = { padding: '10px 12px', fontSize: 13, borderBottom: '1px solid ' + C.border, verticalAlign: 'middle' };
  const badge = (e) => ({ display: 'inline-block', background: em(e).bg, color: em(e).color, borderRadius: 6, padding: '3px 8px', fontSize: 11, fontWeight: 700 });
  const btnInert = { fontSize: 12, padding: '5px 10px', borderRadius: 6, border: '1px solid ' + C.border, background: C.card, color: C.muted, cursor: 'not-allowed', whiteSpace: 'nowrap' };
  const metric = { background: C.bg, borderRadius: 8, padding: '14px 16px' };

  // ── Render ──────────────────────────────────────────────────────────────────
  return (
    <div style={{ padding: '20px 24px', maxWidth: 1100, margin: '0 auto' }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 20 }}>
        <h2 style={{ margin: 0, fontSize: 18, fontWeight: 700 }}>💶 Appels de fonds</h2>
        <button onClick={load} style={{ background: C.accent, color: '#fff', border: 'none', borderRadius: 7, padding: '7px 16px', fontSize: 13, fontWeight: 600, cursor: 'pointer' }}>
          ↻ Actualiser
        </button>
      </div>

      {loading && <div style={{ textAlign: 'center', padding: 48, color: C.muted }}>Chargement…</div>}
      {error && <div style={{ background: '#fef2f2', border: '1px solid #fecaca', borderRadius: 8, padding: '12px 16px', color: '#dc2626', fontSize: 13 }}>Erreur : {error}</div>}

      {!loading && !error && (
        <React.Fragment>
          {/* ── Indicateurs ── */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))', gap: 12, marginBottom: 24 }}>
            <div style={metric}><div style={{ fontSize: 12, color: C.muted, marginBottom: 4 }}>Appels en cours</div><div style={{ fontSize: 22, fontWeight: 700 }}>{mAppelsEnCours}</div></div>
            <div style={metric}><div style={{ fontSize: 12, color: C.muted, marginBottom: 4 }}>À traiter maintenant</div><div style={{ fontSize: 22, fontWeight: 700 }}>{mATraiter}</div></div>
            <div style={metric}><div style={{ fontSize: 12, color: C.muted, marginBottom: 4 }}>Attente attestation</div><div style={{ fontSize: 22, fontWeight: 700 }}>{mAttenteAttest}</div></div>
            <div style={metric}><div style={{ fontSize: 12, color: C.muted, marginBottom: 4 }}>En attente de paiement</div><div style={{ fontSize: 22, fontWeight: 700 }}>{eur(mEnAttPaie)}</div></div>
          </div>

          {/* ── Dashboard appels en cours ── */}
          <div style={{ fontSize: 16, fontWeight: 700, margin: '0 0 10px' }}>Appels en cours</div>
          {enCours.length === 0 ? (
            <div style={{ ...card, padding: 32, textAlign: 'center', color: C.muted, fontSize: 14, marginBottom: 28 }}>Aucun appel en cours.</div>
          ) : (
            <div style={{ ...card, overflow: 'hidden', marginBottom: 28 }}>
              <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                <thead><tr style={{ background: C.bg }}>
                  <th style={th}>Programme / lot</th>
                  <th style={th}>Appel</th>
                  <th style={{ ...th, textAlign: 'right' }}>Montant attendu</th>
                  <th style={th}>État</th>
                  <th style={th}></th>
                </tr></thead>
                <tbody>
                  {enCours.map(a => (
                    <tr key={a.id}>
                      <td style={td}>
                        <div style={{ fontWeight: 600 }}>{progName(a.programme_id)}</div>
                        <div style={{ fontSize: 12, color: C.muted }}>Lot {a.lot_id}</div>
                      </td>
                      <td style={td}>
                        <div style={{ fontWeight: 600 }}>+ {pct(a.pct_delta)}</div>
                        <div style={{ fontSize: 11, color: C.muted }}>cumulé {pct(a.pct_cumule)}</div>
                      </td>
                      <td style={{ ...td, textAlign: 'right' }}>{eur(mont(a))}</td>
                      <td style={td}><span style={badge(a.etat)}>{em(a.etat).label}</span></td>
                      <td style={td}><button style={btnInert} title="Action disponible en Phase 3">{em(a.etat).action}</button></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}

          {/* ── Détail par programme ── */}
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap', margin: '0 0 12px' }}>
            <div style={{ fontSize: 16, fontWeight: 700 }}>Détail par programme</div>
            <select value={prog} onChange={e => setProg(e.target.value)}
              style={{ padding: '6px 10px', borderRadius: 6, border: '1px solid ' + C.border, background: C.card, color: C.text, fontSize: 13, minWidth: 200 }}>
              {programmes.map(([id, nom]) => <option key={id} value={id}>{nom}</option>)}
            </select>
          </div>

          {progAppels.length === 0 ? (
            <div style={{ ...card, padding: 28, textAlign: 'center', color: C.muted, fontSize: 14 }}>Aucun appel pour ce programme.</div>
          ) : (
            <React.Fragment>
              {/* Cumul par statut */}
              <div style={{ ...card, padding: '14px 18px', marginBottom: 14 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 10 }}>
                  <span style={{ fontSize: 13, color: C.muted }}>Cumul des appels par statut</span>
                  <span style={{ fontSize: 13 }}>Total <b>{eur(cumul.grand)}</b></span>
                </div>
                <div style={{ height: 14, borderRadius: 7, overflow: 'hidden', display: 'flex', background: C.bg }}>
                  {BUCKET_ORDER.filter(k => cumul.tot[k]).map(k => (
                    <span key={k} title={em(k).label + ' : ' + eur(cumul.tot[k])}
                      style={{ width: (cumul.grand ? (cumul.tot[k] / cumul.grand * 100) : 0) + '%', background: em(k).dot, height: '100%' }} />
                  ))}
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: 8, marginTop: 12 }}>
                  {BUCKET_ORDER.filter(k => cumul.cnt[k]).map(k => (
                    <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', background: C.bg, borderRadius: 6 }}>
                      <span style={{ width: 9, height: 9, borderRadius: '50%', background: em(k).dot, flex: 'none' }} />
                      <div style={{ flex: 1 }}>
                        <div style={{ fontSize: 12, color: C.muted }}>{em(k).label}</div>
                        <div style={{ fontWeight: 600 }}>{eur(cumul.tot[k])} <span style={{ fontWeight: 400, color: C.muted, fontSize: 12 }}>· {cumul.cnt[k]} appel{cumul.cnt[k] > 1 ? 's' : ''}</span></div>
                      </div>
                    </div>
                  ))}
                </div>
              </div>

              {/* Drill-down lots */}
              {lots.map(L => {
                const open = openLots.has(L.lot);
                return (
                  <div key={L.lot} style={{ ...card, marginBottom: 10, overflow: 'hidden' }}>
                    <div onClick={() => toggleLot(L.lot)} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', cursor: 'pointer' }}>
                      <span style={{ color: C.muted, fontSize: 13, width: 14 }}>{open ? '▾' : '▸'}</span>
                      <div style={{ fontWeight: 600, minWidth: 54 }}>Lot {L.lot}</div>
                      <div style={{ fontSize: 12, color: C.muted }}>travaux {eur(L.travaux)}</div>
                      <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 8, justifyContent: 'flex-end' }}>
                        <div style={{ width: 120, height: 6, borderRadius: 6, background: C.bg, overflow: 'hidden' }}>
                          <span style={{ display: 'block', height: '100%', width: Math.min(100, L.cumul) + '%', background: '#639922' }} />
                        </div>
                        <span style={{ fontSize: 12, color: C.muted, minWidth: 40 }}>cumulé {L.cumul} %</span>
                      </div>
                    </div>
                    {open && (
                      <div>
                        {L.appels.map(a => {
                          const d = fmtDate(a.appel_client_date) || fmtDate(a.attestation_date) || fmtDate(a.eg_date);
                          return (
                            <div key={a.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 14px', borderTop: '1px solid ' + C.border }}>
                              <span style={{ width: 9, height: 9, borderRadius: '50%', background: em(a.etat).dot, flex: 'none' }} />
                              <div style={{ width: 78, fontWeight: 600 }}>+ {pct(a.pct_delta)}</div>
                              <div style={{ width: 100, textAlign: 'right', fontWeight: 600 }}>{eur(mont(a))}</div>
                              <div style={{ flex: 1 }}><span style={badge(a.etat)}>{em(a.etat).label}</span></div>
                              <div style={{ fontSize: 12, color: C.muted, minWidth: 70, textAlign: 'right' }}>{d || ''}</div>
                            </div>
                          );
                        })}
                      </div>
                    )}
                  </div>
                );
              })}
            </React.Fragment>
          )}

          <p style={{ fontSize: 11, color: C.muted, marginTop: 18 }}>
            Lecture seule (Phase 2). L'état « payé » (réconciliation), la zone « À vérifier » et les actions arrivent ensuite.
          </p>
        </React.Fragment>
      )}
    </div>
  );
}
