/* Immobase App — modules 2/2 : Checklist, Emails, Simulateur, Comparateur */

const RECIP_BG = { sage: 'bg-sage', clay: 'bg-clay', blue: 'bg-blue' };

/* ---------- PaywallGate ---------- */
const PAYWALL_FEATURES = {
  checklist: {
    title: 'Checklist de documents',
    desc: 'Accédez à la liste complète des documents à préparer, personnalisée selon votre profil (type de bien, financement, statut).',
  },
  emails: {
    title: 'Générateur d\'emails',
    desc: 'Des emails prêts à envoyer à votre notaire, votre banque, le syndic ou votre assureur — rédigés pour vous.',
  },
  comparateur: {
    title: 'Comparateur de biens',
    desc: 'Comparez deux biens côte à côte sur tous les critères clés pour trancher en toute clarté.',
  },
};

function PaywallGate({ feature, children }) {
  const pro = window.isPro();
  React.useEffect(() => {
    if (!pro) window.track?.('paywall_viewed', { feature });
  }, [feature, pro]);
  if (pro) return children;
  const info = PAYWALL_FEATURES[feature] || {};
  return (
    <div className="view paywall-gate">
      <div className="pw-icon"><IconLock size={32} stroke="var(--sage-deep)" sw={1.5} /></div>
      <h2 className="disp pw-title">{info.title}</h2>
      <p className="pw-desc">{info.desc}</p>
      <div className="pw-perks">
        <span><IconCheck size={15} sw={2.2} stroke="var(--sage-deep)" /> Biens illimités</span>
        <span><IconCheck size={15} sw={2.2} stroke="var(--sage-deep)" /> Checklist personnalisée</span>
        <span><IconCheck size={15} sw={2.2} stroke="var(--sage-deep)" /> Emails prêts à envoyer</span>
        <span><IconCheck size={15} sw={2.2} stroke="var(--sage-deep)" /> Comparateur de biens</span>
      </div>
      <button type="button" className="btn btn-sage pw-cta" onClick={() => window.openUpgrade()}>Passer au plan Complet</button>
      <p className="pw-sub">Déjà abonné ? <a href="#" onClick={async (e) => { e.preventDefault(); await window.sb.auth.refreshSession(); window.location.reload(); }}>Rafraîchir la session</a></p>
    </div>
  );
}

/* ---------- ProfileSetup ---------- */
function ProfileSetup({ store, onClose }) {
  const [p, setP] = React.useState({ ...store.state.profile });
  const set = (k, v) => setP(prev => ({ ...prev, [k]: v }));
  const isComplete = p.type_bien && p.financement && p.statut_emploi;

  function save() { store.setProfile(p); onClose(); }

  const modalRef = useModalA11y(onClose);
  const Q = ({ label, children }) => (
    <div className="profile-q">
      <div className="profile-qlabel">{label}</div>
      <div className="profile-opts">{children}</div>
    </div>
  );
  const Opt = ({ k, v, label, icon }) => (
    <button className={'profile-opt' + (p[k] === v ? ' on' : '')} onClick={() => set(k, v)}>
      {icon && <span className="poi">{icon}</span>}{label}
    </button>
  );

  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" ref={modalRef} aria-label="Votre profil d'achat" style={{ maxWidth: 520 }} onClick={e => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <h2 className="disp" style={{ margin: 0 }}>Votre profil d'achat</h2>
            <p style={{ margin: '4px 0 0', fontSize: 13, color: 'var(--muted)' }}>Personnalise votre checklist et vos emails automatiquement.</p>
          </div>
          <button className="icon-btn" onClick={onClose}><IconX size={18} /></button>
        </div>
        <div className="modal-body" style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
          <Q label="Quel type de bien achetez-vous ?">
            <Opt k="type_bien" v="appartement" label="Appartement / Studio" icon="🏢" />
            <Opt k="type_bien" v="maison"      label="Maison / Villa" icon="🏡" />
          </Q>
          <Q label="Mode de financement ?">
            <Opt k="financement" v="credit" label="Crédit immobilier" icon="🏦" />
            <Opt k="financement" v="cash"   label="Cash (sans emprunt)" icon="💶" />
          </Q>
          <Q label="Statut professionnel ?">
            <Opt k="statut_emploi" v="salarie"     label="Salarié(e)" icon="💼" />
            <Opt k="statut_emploi" v="independant" label="Indépendant(e)" icon="🧑‍💻" />
            <Opt k="statut_emploi" v="retraite"    label="Retraité(e)" icon="🌴" />
          </Q>
        </div>
        <div className="modal-foot">
          <button className="btn btn-ghost" onClick={onClose}>Annuler</button>
          <button className="btn btn-sage" onClick={save} disabled={!isComplete}
            style={{ opacity: isComplete ? 1 : 0.5 }}>
            Enregistrer mon profil
          </button>
        </div>
      </div>
    </div>
  );
}

/* ---------- Checklist ---------- */
function Checklist({ store, go }) {
  const { documents, profile } = store.state;
  const [showProfile, setShowProfile] = React.useState(false);
  const [newLine, setNewLine] = React.useState(''); // ligne perso (s10q08)

  function addLine() {
    store.addCustomDoc(newLine);
    setNewLine('');
  }

  const profileComplete = profile?.type_bien && profile?.financement && profile?.statut_emploi;
  const done = documents.filter((d) => d.done).length;
  const pct = documents.length > 0 ? Math.round((done / documents.length) * 100) : 0;

  const groups = {};
  documents.forEach((d) => { (groups[d.recipient] = groups[d.recipient] || []).push(d); });

  return (
    <div className="view">
      {!profileComplete && (
        <div className="profile-banner">
          <div className="pb-text">
            <b>Personnalisez votre checklist</b>
            <span>Appartement ou maison, crédit ou cash, salarié ou indépendant — votre liste s'adapte à votre situation réelle.</span>
          </div>
          <button className="btn btn-sage" onClick={() => setShowProfile(true)}>
            Configurer mon profil
          </button>
        </div>
      )}

      {profileComplete && (
        <div className="profile-tag-row">
          <span className="profile-tag">{profile.type_bien === 'appartement' ? '🏢 Appartement' : '🏡 Maison'}</span>
          <span className="profile-tag">{profile.financement === 'credit' ? '🏦 Crédit' : '💶 Cash'}</span>
          <span className="profile-tag">{profile.statut_emploi === 'salarie' ? '💼 Salarié' : profile.statut_emploi === 'independant' ? '🧑‍💻 Indépendant' : '🌴 Retraité'}</span>
          <button className="profile-edit-btn" onClick={() => setShowProfile(true)}>Modifier</button>
        </div>
      )}

      <div className="cl-top">
        <div className="cl-bar">
          <div className="lab"><span>Progression globale</span><span>{done} / {documents.length} documents</span></div>
          <div className="cl-track"><i style={{ width: pct + '%' }}></i></div>
        </div>
        <div style={{ textAlign: 'center', flex: 'none' }}>
          <div className="disp" style={{ fontSize: 30, color: 'var(--sage-deep)' }}>{pct}%</div>
        </div>
      </div>

      {Object.keys(groups).map((rec) => {
        const r = RECIPIENTS[rec];
        const items = groups[rec];
        const gdone = items.filter((d) => d.done).length;
        return (
          <div className="cl-group" key={rec}>
            <div className="cl-ghead">
              <span className={'gi ' + RECIP_BG[r.color]}><IconUser size={18} /></span>
              <div>
                <h3 className="disp">{r.label}</h3>
              </div>
              <span className="cnt">{gdone} / {items.length}</span>
            </div>
            {items.map((d) => {
              const hasMail = !!EMAIL_TEMPLATES[d.id];
              return (
                <div className={'cl-item' + (d.done ? ' done' : '')} key={d.id}>
                  <button className={'cl-check' + (d.done ? ' on' : '')} onClick={() => store.toggleDoc(d.id)}>
                    <IconCheck size={15} sw={2.3} />
                  </button>
                  <div className="cl-name">
                    <b>{d.name}</b>
                    <span>{d.note}</span>
                  </div>
                  {hasMail && (
                    <button className="cl-mail" onClick={() => go('emails', d.id)}>
                      <IconMail size={14} /> Demander
                    </button>
                  )}
                  {d.custom && (
                    <button className="icon-btn" title="Retirer cette ligne" onClick={() => store.removeCustomDoc(d.id)}>
                      <IconX size={14} />
                    </button>
                  )}
                </div>
              );
            })}
          </div>
        );
      })}

      {/* Ligne personnalisée : l'utilisateur complète sa propre checklist (s10q08) */}
      <div className="cl-group">
        <div className="cl-ghead">
          <span className="gi bg-clay"><IconPlus size={18} /></span>
          <div><h3 className="disp">Il manque un document ?</h3></div>
        </div>
        <div style={{ display: 'flex', gap: 10, padding: '4px 2px 6px', flexWrap: 'wrap' }}>
          <input
            value={newLine}
            onChange={(e) => setNewLine(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addLine(); } }}
            placeholder="Ajoutez votre propre ligne (ex. attestation de donation…)"
            aria-label="Nouvelle ligne de checklist"
            style={{ flex: 1, minWidth: 220, fontFamily: 'inherit', fontSize: 14.5, padding: '11px 14px', border: '1.5px solid var(--hair)', borderRadius: 12, background: 'var(--card)', color: 'var(--ink)' }}
          />
          <button type="button" className="btn btn-out" onClick={addLine}><IconPlus size={15} /> Ajouter</button>
        </div>
      </div>

      {showProfile && <ProfileSetup store={store} onClose={() => setShowProfile(false)} />}
    </div>
  );
}

/* ---------- Emails ---------- */
function Emails({ store, focusDoc }) {
  const { documents, properties } = store.state;
  const mailDocs = documents.filter((d) => EMAIL_TEMPLATES[d.id]);

  if (mailDocs.length === 0) {
    return (
      <div className="view empty">
        <div className="ei"><IconMail size={28} /></div>
        <p>Chargement des documents…</p>
      </div>
    );
  }

  const [sel, setSel] = React.useState(() => {
    if (focusDoc && EMAIL_TEMPLATES[focusDoc]) return focusDoc;
    return mailDocs[0].id;
  });

  const tpl = EMAIL_TEMPLATES[sel] || EMAIL_TEMPLATES[mailDocs[0].id];

  // Document sélectionné (accessible dans tout le composant)
  const doc = documents.find(d => d.id === sel);

  // Bien concerné : sélectionnable, défaut = coup de cœur (sinon 1er bien)
  const fav = properties.find((p) => p.favori) || properties[0];
  const [bienId, setBienId] = React.useState(fav?.id || '');
  const selectedBien = properties.find((p) => p.id === bienId) || fav;
  const bien = selectedBien ? `${selectedBien.title}, ${selectedBien.city}` : 'le bien concerné';
  const userName = window.IMMOBASE_USER?.user_metadata?.full_name
    || window.IMMOBASE_USER?.email
    || 'Vous';

  const body = renderBody(tpl, bien, userName);

  function copy() {
    const text = `À: ${tpl.to}\nObjet: ${tpl.subject}\n\n${body}`;
    window.track?.('email_copied', { doc: sel });
    navigator.clipboard?.writeText(text).then(() => toast('Email copié ✓'), () => toast('Email copié ✓'));
  }

  return (
    <div className="view em-layout">
      <div className="em-list">
        {mailDocs.map((d) => {
          const r = RECIPIENTS[d.recipient];
          return (
            <button key={d.id} className={'em-li' + (sel === d.id ? ' on' : '')} onClick={() => setSel(d.id)}>
              <span className={'eli ' + RECIP_BG[r.color]}><IconMail size={17} /></span>
              <span className="eb"><b>{d.name}</b><span>{r.label}</span></span>
            </button>
          );
        })}
      </div>

      <div className="em-preview">
        {properties.length > 0 && (
          <div className="em-bien">
            <span className="k">Bien concerné</span>
            <select value={bienId} onChange={(e) => setBienId(e.target.value)}>
              {properties.map((p) => (
                <option key={p.id} value={p.id}>
                  {p.favori ? '❤ ' : ''}{p.title}{p.city ? ' · ' + p.city.split(',')[0] : ''}
                </option>
              ))}
            </select>
          </div>
        )}
        <div className="em-ph">
          <div className="row"><span className="k">À</span><span className="v">{tpl.to}</span></div>
          <div className="row"><span className="k">Objet</span><span className="v">{tpl.subject}</span></div>
        </div>
        <div className="em-pb">{body}</div>
        <div className="em-pf">
          <button className="btn btn-sage" onClick={copy}><IconCopy size={16} stroke="#fff" /> Copier l'email</button>
          {doc && (
            <button className="btn btn-out" style={{ marginLeft: 'auto' }} onClick={() => { store.toggleDoc(doc.id); toast(doc.done ? 'Marqué à faire' : 'Marqué comme demandé ✓'); }}>
              {doc.done ? 'Marquer à faire' : 'Marquer demandé'}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

function renderBody(tpl, bien, nom) {
  return tpl.body.replace(/\{\{bien\}\}/g, bien).replace(/\{\{nom\}\}/g, nom);
}

/* ---------- Simulateur ---------- */
const NOTAIRE_RATES = { ancien: 0.075, neuf: 0.025 };

/* Montant affiché formaté, éditable au clic pour une saisie précise */
function EditableAmount({ value, onCommit, min, max }) {
  const [editing, setEditing] = React.useState(false);
  const [draft, setDraft] = React.useState(String(value));

  function start() { setDraft(String(value)); setEditing(true); }
  function commit() {
    let n = parseInt(draft.replace(/[^\d]/g, ''), 10);
    if (isNaN(n)) n = value;
    if (typeof min === 'number') n = Math.max(min, n);
    if (typeof max === 'number') n = Math.min(max, n);
    onCommit(n);
    setEditing(false);
  }

  if (editing) {
    return (
      <input className="vl-input" autoFocus type="text" inputMode="numeric"
        value={draft}
        onChange={(e) => setDraft(e.target.value)}
        onBlur={commit}
        onKeyDown={(e) => {
          if (e.key === 'Enter') commit();
          if (e.key === 'Escape') { setEditing(false); }
        }} />
    );
  }
  return (
    <button type="button" className="vl vl-btn" onClick={start} title="Cliquer pour saisir un montant précis">
      {fmtEur(value)}
    </button>
  );
}

function Simulateur({ store }) {
  const sim = store.state.sim;
  const set = (k) => (e) => store.setSim({ [k]: Number(e.target.value) });

  const [mode, setMode] = React.useState('mensualite'); // mensualite | capacite
  const [bienType, setBienType] = React.useState('ancien');
  const [revenus, setRevenus] = React.useState(4000);
  const [charges, setCharges] = React.useState(0);
  const [tauxEndett, setTauxEndett] = React.useState(35);
  const notaireRate = NOTAIRE_RATES[bienType];

  // Bloc type de bien (commun aux deux modes)
  const TypeBloc = (
    <div className="sim-block">
      <div className="field-lab"><span className="nm">Type de bien</span></div>
      <div className="sim-seg">
        <button className={bienType === 'ancien' ? 'on' : ''} onClick={() => setBienType('ancien')}>Ancien <span>~7,5 %</span></button>
        <button className={bienType === 'neuf' ? 'on' : ''} onClick={() => setBienType('neuf')}>Neuf <span>~2,5 %</span></button>
      </div>
    </div>
  );

  return (
    <div className="view">
      <div className="sim-mode">
        <button className={mode === 'mensualite' ? 'on' : ''} onClick={() => setMode('mensualite')}>Estimer ma mensualité</button>
        <button className={mode === 'capacite' ? 'on' : ''} onClick={() => setMode('capacite')}>Connaître mon budget</button>
      </div>

      {mode === 'mensualite' ? (() => {
        const res = computeLoan(sim);
        const capShare = res.total > 0 ? (res.principal / res.total) * 100 : 100;
        const fraisNotaire = Math.round(sim.price * notaireRate);
        const budgetTotal = sim.price + fraisNotaire;
        const apportCouvreFrais = sim.apport >= fraisNotaire;
        return (
          <div className="sim-layout">
            <div className="panel sim-controls">
              {TypeBloc}
              <div className="sim-block">
                <div className="field-lab"><span className="nm">Prix du bien</span>
                  <EditableAmount value={sim.price} min={10000} max={1500000} onCommit={(n) => store.setSim({ price: n })} />
                </div>
                <input type="range" aria-label="Prix du bien" min="10000" max="1500000" step="1000" value={Math.min(sim.price, 1500000)} onChange={set('price')} />
                <div className="sim-minmax"><span>10 000 €</span><span>1 500 000 €</span></div>
              </div>
              <div className="sim-block">
                <div className="field-lab"><span className="nm">Apport personnel</span>
                  <EditableAmount value={sim.apport} min={0} max={sim.price} onCommit={(n) => store.setSim({ apport: Math.min(n, sim.price) })} />
                </div>
                <input type="range" aria-label="Apport personnel" min="0" max={sim.price} step="1000" value={Math.min(sim.apport, sim.price)} onChange={set('apport')} />
                <div className="sim-minmax"><span>0 €</span><span>{Math.round((sim.apport / sim.price) * 100) || 0} % du prix</span></div>
              </div>
              <div className="sim-block">
                <div className="field-lab"><span className="nm">Durée</span><span className="vl">{sim.duree} ans</span></div>
                <input type="range" aria-label="Durée du prêt en années" min="5" max="30" step="1" value={sim.duree} onChange={set('duree')} />
                <div className="sim-minmax"><span>5 ans</span><span>30 ans</span></div>
              </div>
              <div className="sim-block" style={{ marginBottom: 0 }}>
                <div className="field-lab"><span className="nm">Taux d'intérêt</span><span className="vl">{sim.taux.toFixed(2)} %</span></div>
                <input type="range" aria-label="Taux d’intérêt" min="0.5" max="6" step="0.05" value={sim.taux} onChange={set('taux')} />
                <div className="sim-minmax"><span>0,5 %</span><span>6 %</span></div>
              </div>
            </div>

            <div className="sim-result">
              <div className="blob"></div>
              <div className="lbl">Mensualité estimée</div>
              <div className="big disp">{fmtEur(res.monthly)}<span>/mois</span></div>
              <div className="sub">Sur {sim.duree} ans · capital emprunté {fmtEur(res.principal)}</div>

              <div className="sim-budget">
                <div className="br"><span className="k">Prix du bien</span><span className="v">{fmtEur(sim.price)}</span></div>
                <div className="br"><span className="k">Frais de notaire <i>· {bienType === 'ancien' ? 'ancien' : 'neuf'}</i></span><span className="v">{fmtEur(fraisNotaire)}</span></div>
                <div className="br total"><span className="k">Budget total à prévoir</span><span className="v">{fmtEur(budgetTotal)}</span></div>
                <div className="sim-apport-note">
                  {apportCouvreFrais
                    ? <span className="ok">✓ Votre apport couvre les frais de notaire</span>
                    : <span className="warn">⚠ Prévoyez au moins {fmtEur(fraisNotaire)} d'apport pour les frais de notaire</span>}
                </div>
              </div>

              <div className="sim-break">
                <div className="br"><span className="k">Coût total du crédit</span><span className="v">{fmtEur(res.total)}</span></div>
                <div className="br"><span className="k">Dont intérêts</span><span className="v">{fmtEur(res.interest)}</span></div>
                <div className="br"><span className="k">Nombre d'échéances</span><span className="v">{res.n}</span></div>
                <div className="sim-bardist">
                  <span className="cap" style={{ width: capShare + '%' }}></span>
                  <span className="intr" style={{ width: (100 - capShare) + '%' }}></span>
                </div>
                <div className="sim-legend">
                  <span><i style={{ background: 'oklch(1 0 0 / .85)' }}></i> Capital</span>
                  <span><i style={{ background: 'var(--clay)' }}></i> Intérêts</span>
                </div>
              </div>
            </div>
          </div>
        );
      })() : (() => {
        const r = sim.taux / 100 / 12;
        const n = sim.duree * 12;
        const mensualiteMax = Math.max(0, Math.round((revenus * tauxEndett) / 100 - charges));
        const principalMax = r === 0 ? mensualiteMax * n : (mensualiteMax * (1 - Math.pow(1 + r, -n))) / r;
        const budgetMax = Math.max(0, Math.round((principalMax + sim.apport) / (1 + notaireRate)));
        const fraisNotaireMax = Math.round(budgetMax * notaireRate);
        return (
          <div className="sim-layout">
            <div className="panel sim-controls">
              {TypeBloc}
              <div className="sim-block">
                <div className="field-lab"><span className="nm">Revenus nets du foyer</span>
                  <EditableAmount value={revenus} min={0} max={50000} onCommit={setRevenus} />
                </div>
                <input type="range" aria-label="Revenus nets du foyer" min="1000" max="15000" step="100" value={Math.min(revenus, 15000)} onChange={(e) => setRevenus(Number(e.target.value))} />
                <div className="sim-minmax"><span>par mois</span><span>net avant impôt</span></div>
              </div>
              <div className="sim-block">
                <div className="field-lab"><span className="nm">Crédits en cours</span>
                  <EditableAmount value={charges} min={0} max={20000} onCommit={setCharges} />
                </div>
                <input type="range" aria-label="Crédits en cours" min="0" max="3000" step="50" value={Math.min(charges, 3000)} onChange={(e) => setCharges(Number(e.target.value))} />
                <div className="sim-minmax"><span>0 €</span><span>auto, conso… /mois</span></div>
              </div>
              <div className="sim-block">
                <div className="field-lab"><span className="nm">Apport personnel</span>
                  <EditableAmount value={sim.apport} min={0} max={1000000} onCommit={(n2) => store.setSim({ apport: n2 })} />
                </div>
                <input type="range" aria-label="Apport personnel" min="0" max="300000" step="1000" value={Math.min(sim.apport, 300000)} onChange={set('apport')} />
                <div className="sim-minmax"><span>0 €</span><span>épargne dispo</span></div>
              </div>
              <div className="sim-block">
                <div className="field-lab"><span className="nm">Durée</span><span className="vl">{sim.duree} ans</span></div>
                <input type="range" aria-label="Durée du prêt en années" min="5" max="30" step="1" value={sim.duree} onChange={set('duree')} />
                <div className="sim-minmax"><span>5 ans</span><span>30 ans</span></div>
              </div>
              <div className="sim-block" style={{ marginBottom: 0 }}>
                <div className="field-lab"><span className="nm">Taux d'endettement max</span><span className="vl">{tauxEndett} %</span></div>
                <input type="range" aria-label="Taux d’endettement maximum" min="25" max="40" step="1" value={tauxEndett} onChange={(e) => setTauxEndett(Number(e.target.value))} />
                <div className="sim-minmax"><span>25 %</span><span>plafond conseillé 35 %</span></div>
              </div>
            </div>

            <div className="sim-result">
              <div className="blob"></div>
              <div className="lbl">Budget d'achat maximum</div>
              <div className="big disp">{fmtEur(budgetMax)}</div>
              <div className="sub">Frais de notaire inclus · apport {fmtEur(sim.apport)}</div>

              <div className="sim-budget">
                <div className="br"><span className="k">Mensualité maximale</span><span className="v">{fmtEur(mensualiteMax)}/mois</span></div>
                <div className="br"><span className="k">Capital empruntable</span><span className="v">{fmtEur(Math.round(principalMax))}</span></div>
                <div className="br"><span className="k">+ Apport</span><span className="v">{fmtEur(sim.apport)}</span></div>
                <div className="br"><span className="k">− Frais de notaire</span><span className="v">{fmtEur(fraisNotaireMax)}</span></div>
                <div className="br total"><span className="k">Prix de bien atteignable</span><span className="v">{fmtEur(budgetMax)}</span></div>
                <div className="sim-apport-note">
                  {mensualiteMax <= 0
                    ? <span className="warn">⚠ Vos crédits en cours dépassent votre capacité — réduisez-les ou augmentez vos revenus</span>
                    : <span className="ok">Calcul au taux d'endettement de {tauxEndett} % (assurance de prêt non incluse)</span>}
                </div>
              </div>
            </div>
          </div>
        );
      })()}
    </div>
  );
}

/* ---------- Comparateur ---------- */
function Comparateur({ store, go }) {
  const props = store.state.properties.filter((p) => p.status !== 'elimine');
  const favs = props.filter((p) => p.favori);
  const [aId, setA] = React.useState((favs[0] || props[0] || {}).id);
  const [bId, setB] = React.useState((favs[1] || props[1] || props[0] || {}).id);

  if (props.length < 2) {
    return (
      <div className="view empty">
        <div className="ei"><IconCompare size={28} /></div>
        <h3 className="disp">Il faut au moins deux biens à comparer</h3>
        <p>Ajoutez des biens dans le Tracker, puis revenez ici pour les mettre face à face.</p>
        <button className="btn btn-sage" onClick={() => go('tracker')}>Aller au Tracker</button>
      </div>
    );
  }

  const a = props.find((p) => p.id === aId) || props[0];
  const b = props.find((p) => p.id === bId) || props[1];
  const ppm = (p) => (p.surface ? Math.round(p.price / p.surface) : 0);

  const valid = (typeof activeCriteres !== 'undefined') ? activeCriteres(store) : null;
  const sa = (typeof visiteScore !== 'undefined') ? visiteScore(a.visiteGrille, valid) : null;
  const sb = (typeof visiteScore !== 'undefined') ? visiteScore(b.visiteGrille, valid) : null;

  // Verdict par critère : « win » attribué UNIQUEMENT si les deux valeurs sont
  // renseignées. Toute valeur manquante → « — » et le critère est exclu du score
  // (pas de double comptage, pas de valeur inventée — s10q01, s10q04).
  const simP = store.state.sim || {};
  const mensualite = (p) => {
    if (!p.price) return null;
    const r = computeLoan({ price: p.price, apport: Math.min(simP.apport || 0, p.price), duree: simP.duree || 20, taux: simP.taux || 3.4 });
    return Math.round(r.monthly);
  };
  const dpeRank = (d) => (d ? 'ABCDEFG'.indexOf(d) : -1); // A = meilleur
  const ma = mensualite(a), mb = mensualite(b);
  const nz = (v) => (v === 0 || v == null ? null : v); // 0/absent traité comme « non renseigné »
  const dash = (v) => (v == null ? '—' : fmtEur(v));
  const lowWin  = (x, y) => (x == null || y == null) ? null : (x < y ? 'a' : y < x ? 'b' : null);
  const highWin = (x, y) => (x == null || y == null) ? null : (x > y ? 'a' : y > x ? 'b' : null);

  const rows = [
    { k: 'Prix', a: fmtEur(a.price), b: fmtEur(b.price), win: lowWin(a.price || null, b.price || null) },
    { k: 'Prix au m²', a: ppm(a) ? fmtEur2(ppm(a)) + '/m²' : '—', b: ppm(b) ? fmtEur2(ppm(b)) + '/m²' : '—', win: lowWin(nz(ppm(a)), nz(ppm(b))) },
    { k: 'Surface', a: a.surface ? a.surface + ' m²' : '—', b: b.surface ? b.surface + ' m²' : '—', win: highWin(nz(a.surface), nz(b.surface)) },
    { k: 'Pièces', a: a.rooms || '—', b: b.rooms || '—', win: highWin(nz(a.rooms), nz(b.rooms)) },
    { k: 'DPE', a: a.dpe || '—', b: b.dpe || '—', win: (a.dpe && b.dpe) ? (dpeRank(a.dpe) < dpeRank(b.dpe) ? 'a' : dpeRank(b.dpe) < dpeRank(a.dpe) ? 'b' : null) : null },
    { k: "Frais d'agence", a: dash(a.fees), b: dash(b.fees), win: lowWin(a.fees, b.fees) },
    { k: 'Charges / mois', a: dash(a.charges), b: dash(b.charges), win: lowWin(a.charges, b.charges) },
    { k: 'Budget travaux', a: dash(a.travaux), b: dash(b.travaux), win: lowWin(a.travaux, b.travaux) },
    { k: 'Mensualité estimée', a: ma == null ? '—' : fmtEur(ma) + '/mois', b: mb == null ? '—' : fmtEur(mb) + '/mois', win: lowWin(ma, mb) },
    { k: 'Note de visite', a: sa ? sa.avg.toFixed(1) + '/5' : '—', b: sb ? sb.avg.toFixed(1) + '/5' : '—', win: (sa && sb) ? (sa.avg > sb.avg ? 'a' : sb.avg > sa.avg ? 'b' : null) : null },
    { k: 'Localisation', a: a.city || '—', b: b.city || '—', win: null },
    { k: 'Statut', a: STATUS_LABELS[a.status] || '—', b: STATUS_LABELS[b.status] || '—', win: null },
  ];

  const scoreA = rows.filter((r) => r.win === 'a').length;
  const scoreB = rows.filter((r) => r.win === 'b').length;
  const overall = scoreA > scoreB ? 'a' : scoreB > scoreA ? 'b' : null;

  return (
    <div className="view">
      <div className="cmp-pick">
        <div className={'cmp-slot' + (a ? ' filled' : '')}>
          <label>Bien A</label>
          <select value={aId} onChange={(e) => setA(e.target.value)}>
            {props.map((p) => <option key={p.id} value={p.id}>{p.title} · {p.city.split(',')[0]}</option>)}
          </select>
        </div>
        <div className={'cmp-slot' + (b ? ' filled' : '')}>
          <label>Bien B</label>
          <select value={bId} onChange={(e) => setB(e.target.value)}>
            {props.map((p) => <option key={p.id} value={p.id}>{p.title} · {p.city.split(',')[0]}</option>)}
          </select>
        </div>
      </div>

      <div className="cmp-table">
        <div className="cmp-headrow">
          <div className="ch" style={{ display: 'flex', alignItems: 'flex-end' }}>
            <span style={{ fontSize: 13, fontWeight: 700, color: 'var(--muted)' }}>{scoreA} vs {scoreB} critères</span>
          </div>
          <div className="ch">
            <div className="cmp-photo" style={a.photoUrl ? { backgroundImage: `url(${a.photoUrl})`, backgroundSize: 'cover', backgroundPosition: 'center' } : undefined}>{overall === 'a' && <span className="win">Recommandé</span>}</div>
            <div className="price disp">{fmtEur(a.price)}</div>
            <div className="ttl">{a.title}</div>
            <div className="loc">{a.city}</div>
          </div>
          <div className="ch">
            <div className="cmp-photo" style={b.photoUrl ? { backgroundImage: `url(${b.photoUrl})`, backgroundSize: 'cover', backgroundPosition: 'center' } : undefined}>{overall === 'b' && <span className="win">Recommandé</span>}</div>
            <div className="price disp">{fmtEur(b.price)}</div>
            <div className="ttl">{b.title}</div>
            <div className="loc">{b.city}</div>
          </div>
        </div>
        {rows.map((r, i) => (
          <div className="cmp-r" key={i}>
            <div className="k">{r.k}</div>
            <div className={'cell' + (r.win === 'a' ? ' win' : '')}>{r.a}{r.win === 'a' && <span className="wt">Mieux</span>}</div>
            <div className={'cell' + (r.win === 'b' ? ' win' : '')}>{r.b}{r.win === 'b' && <span className="wt">Mieux</span>}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------- Carte des biens ---------- */
const GEO_CACHE_KEY = 'immobase_geocode_v1';

function Carte({ store, go }) {
  const props = store.state.properties.filter((p) => p.status !== 'elimine' && p.city);
  const mapEl = React.useRef(null);
  const mapObj = React.useRef(null);
  const layer = React.useRef(null);
  const [coords, setCoords] = React.useState({});
  const [geocoding, setGeocoding] = React.useState(false);

  const geoKey = props.map((p) => p.id + ':' + p.city).join('|');

  // Init Leaflet (une seule fois)
  React.useEffect(() => {
    if (!mapEl.current || mapObj.current || !window.L) return;
    const map = window.L.map(mapEl.current, { scrollWheelZoom: true }).setView([46.6, 2.4], 5);
    window.L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; OpenStreetMap', maxZoom: 19,
    }).addTo(map);
    layer.current = window.L.layerGroup().addTo(map);
    mapObj.current = map;
    setTimeout(() => map.invalidateSize(), 150);
    return () => { map.remove(); mapObj.current = null; layer.current = null; };
  }, []);

  // Géocodage des villes (Nominatim) avec cache localStorage
  React.useEffect(() => {
    let cancelled = false;
    let cache = {};
    try { cache = JSON.parse(localStorage.getItem(GEO_CACHE_KEY) || '{}'); } catch (e) {}

    async function run() {
      const fromCache = {};
      let needNetwork = false;
      props.forEach((p) => {
        const q = p.city.trim() + ', France';
        if (cache[q]) fromCache[p.id] = cache[q]; else needNetwork = true;
      });
      if (!cancelled) setCoords(fromCache);
      if (!needNetwork) return;

      if (!cancelled) setGeocoding(true);
      for (const p of props) {
        if (cancelled) break;
        const q = p.city.trim() + ', France';
        if (cache[q]) continue;
        try {
          const res = await fetch('https://nominatim.openstreetmap.org/search?format=json&limit=1&q=' + encodeURIComponent(q));
          const data = await res.json();
          if (data && data[0]) {
            cache[q] = { lat: parseFloat(data[0].lat), lng: parseFloat(data[0].lon) };
            try { localStorage.setItem(GEO_CACHE_KEY, JSON.stringify(cache)); } catch (e) {}
            if (!cancelled) setCoords((prev) => ({ ...prev, [p.id]: cache[q] }));
          }
        } catch (e) { /* ville introuvable : on ignore ce bien */ }
        await new Promise((r) => setTimeout(r, 1100)); // respecte la limite Nominatim (1 req/s)
      }
      if (!cancelled) setGeocoding(false);
    }
    run();
    return () => { cancelled = true; };
  }, [geoKey]);

  // (Re)dessine les marqueurs
  React.useEffect(() => {
    const map = mapObj.current, lg = layer.current;
    if (!map || !lg) return;
    lg.clearLayers();
    const esc = (s) => String(s || '').replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]));
    const pts = [];
    props.forEach((p) => {
      const c = coords[p.id];
      if (!c) return;
      const color = (typeof STATUS_DOT !== 'undefined' && STATUS_DOT[p.status]) || 'var(--sage)';
      const icon = window.L.divIcon({
        className: 'map-pin',
        html: '<span style="background:' + color + '"></span>',
        iconSize: [22, 22], iconAnchor: [11, 11],
      });
      const html = '<b>' + esc(p.title) + '</b><br>' + fmtEur(p.price)
        + (p.surface ? ' · ' + p.surface + ' m²' : '')
        + '<br><span style="color:#9a8">' + (STATUS_LABELS[p.status] || '') + (p.city ? ' · ' + esc(p.city.split(',')[0]) : '') + '</span>';
      window.L.marker([c.lat, c.lng], { icon }).addTo(lg).bindPopup(html);
      pts.push([c.lat, c.lng]);
    });
    if (pts.length) map.fitBounds(pts, { padding: [50, 50], maxZoom: 13 });
  }, [coords, geoKey]);

  if (!window.L) {
    return (
      <div className="view empty">
        <div className="ei"><IconPin size={28} /></div>
        <h3 className="disp">Carte momentanément indisponible</h3>
        <p>Vérifiez votre connexion puis rechargez la page.</p>
      </div>
    );
  }

  if (props.length === 0) {
    return (
      <div className="view empty">
        <div className="ei"><IconPin size={28} /></div>
        <h3 className="disp">Aucun bien à cartographier</h3>
        <p>Ajoutez des biens (avec une ville) dans Mes biens pour les voir sur la carte.</p>
        <button className="btn btn-sage" onClick={() => go('tracker')}>Aller à Mes biens</button>
      </div>
    );
  }

  const located = props.filter((p) => coords[p.id]).length;

  return (
    <div className="view">
      <div className="map-bar">
        <span>{located} / {props.length} bien{props.length > 1 ? 's' : ''} localisé{located > 1 ? 's' : ''}</span>
        {geocoding && <span className="map-loading">Localisation en cours…</span>}
      </div>
      <div className="map-wrap"><div ref={mapEl} className="map-canvas"></div></div>
      <p className="map-note">Localisation approximative basée sur la ville / le quartier saisi. Fonds de carte © OpenStreetMap.</p>
    </div>
  );
}

/* ---------- Mon compte (s9q13) ---------- */
function Account({ store }) {
  const u = window.IMMOBASE_USER || {};
  const [pwd, setPwd] = React.useState('');
  const [pwd2, setPwd2] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const pro = window.isPro();

  async function changePassword() {
    if (pwd.length < 8) { toast('Le mot de passe doit contenir au moins 8 caractères'); return; }
    if (pwd !== pwd2) { toast('Les deux mots de passe ne correspondent pas'); return; }
    setBusy(true);
    const { error } = await window.sb.auth.updateUser({ password: pwd });
    setBusy(false);
    if (error) { toast(window.frAuthError ? window.frAuthError(error.message) : 'Erreur'); return; }
    setPwd(''); setPwd2(''); toast('Mot de passe mis à jour ✓');
  }

  function exportJson() {
    const data = {
      compte: { email: u.email || null, exporte_le: new Date().toISOString() },
      biens: store.state.properties,
      checklist: store.state.checkedDocs,
      profil: store.state.profile,
      simulateur: store.state.sim,
      criteres_visite_perso: store.state.visiteCriteres,
    };
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = 'immoly-mes-donnees.json';
    document.body.appendChild(a); a.click(); a.remove();
    URL.revokeObjectURL(url);
    toast('Export JSON téléchargé ✓');
  }

  const deleteHref = 'mailto:pierre.alexis@gmail.com?subject=' + encodeURIComponent('Suppression de mon compte Immoly')
    + '&body=' + encodeURIComponent('Bonjour,\n\nJe souhaite la suppression définitive de mon compte Immoly (' + (u.email || '') + ') et de toutes mes données.\n\nMerci de confirmer la prise en compte.\n');

  return (
    <div className="view" style={{ maxWidth: 640 }}>
      <div className="card" style={{ padding: 24, marginBottom: 18 }}>
        <h3 className="disp" style={{ marginBottom: 4 }}>Identifiants</h3>
        <p style={{ color: 'var(--muted)', fontSize: 14, marginBottom: 16 }}>Votre plan : <b>{pro ? 'Complet' : 'Découverte'}</b></p>
        <div className="field"><label>Email</label><input value={u.email || ''} readOnly style={{ opacity: 0.7 }} /></div>
      </div>

      <div className="card" style={{ padding: 24, marginBottom: 18 }}>
        <h3 className="disp" style={{ marginBottom: 12 }}>Changer de mot de passe</h3>
        <div className="field"><label>Nouveau mot de passe</label><input type="password" value={pwd} onChange={(e) => setPwd(e.target.value)} placeholder="8 caractères minimum" /></div>
        <div className="field"><label>Confirmez</label><input type="password" value={pwd2} onChange={(e) => setPwd2(e.target.value)} placeholder="Retapez le mot de passe" /></div>
        <button className="btn btn-sage" disabled={busy} onClick={changePassword}>Mettre à jour</button>
      </div>

      <div className="card" style={{ padding: 24, marginBottom: 18 }}>
        <h3 className="disp" style={{ marginBottom: 6 }}>Vos données</h3>
        <p style={{ color: 'var(--muted)', fontSize: 14, marginBottom: 14 }}>Exportez l'ensemble de vos données (biens, checklist, simulateur) au format JSON. Gratuit.</p>
        <button className="btn btn-out" onClick={exportJson}><IconDoc size={15} /> Exporter mes données (JSON)</button>
      </div>

      <div className="card" style={{ padding: 24, borderColor: 'var(--clay-soft)' }}>
        <h3 className="disp" style={{ marginBottom: 6 }}>Supprimer mon compte</h3>
        <p style={{ color: 'var(--muted)', fontSize: 14, marginBottom: 14 }}>La suppression se fait sur demande par email. Nous supprimons votre compte et vos données après confirmation, sous 48 h ouvrées.</p>
        <a className="btn btn-ghost" style={{ color: 'var(--clay-deep)' }} href={deleteHref}><IconTrash size={15} /> Demander la suppression</a>
      </div>
    </div>
  );
}

Object.assign(window, { Checklist, Emails, Simulateur, Comparateur, Carte, PaywallGate, renderBody, Account });
