/* Immobase App — modules 1/2 : Dashboard, Tracker, PropertyModal */

function toast(msg) {
  const el = document.getElementById('toast');
  if (!el) return;
  el.querySelector('.tmsg').textContent = msg;
  el.classList.add('show');
  clearTimeout(window.__toastT);
  window.__toastT = setTimeout(() => el.classList.remove('show'), 2200);
}

const STATUS_DOT = {
  'a-visiter': 'var(--sage)',
  'visite': 'var(--blue)',
  'offre-envoyee': 'var(--clay)',
  'compromis-signe': 'var(--clay-deep)',
  'financement-en-cours': 'var(--blue)',
  'signe-acte': 'var(--sage-deep)',
  'elimine': 'var(--muted)',
};

/* ---------- Grille de visite ---------- */
const VISITE_CRITERES = [
  'Luminosité', 'État général', 'Agencement', 'Calme / voisinage', 'Vis-à-vis',
  'Extérieur', 'Cuisine & salle de bain', 'Rangements', 'Quartier & commerces', 'Transports',
];

// Liste des critères actifs = critères par défaut + critères perso (globaux, dans le profil)
function activeCriteres(store) {
  return VISITE_CRITERES.concat((store && store.state && store.state.visiteCriteres) || []);
}

function visiteScore(grille, valid) {
  const r = grille && grille.ratings ? grille.ratings : null;
  if (!r) return null;
  // moyenne des critères actifs notés (on ignore d'éventuelles notes orphelines)
  const keys = valid && valid.length ? valid : Object.keys(r);
  const vals = keys.map((k) => r[k]).filter((v) => typeof v === 'number' && v > 0);
  if (!vals.length) return null;
  const avg = vals.reduce((a, b) => a + b, 0) / vals.length;
  return { avg: Math.round(avg * 10) / 10, count: vals.length };
}

function GrilleModal({ p, store, onClose }) {
  const customList = store.state.visiteCriteres || []; // liste globale (profil)
  const [grille, setGrille] = React.useState(() => ({
    ratings: { ...((p.visiteGrille && p.visiteGrille.ratings) || {}) },
    notes: (p.visiteGrille && p.visiteGrille.notes) || '',
  }));
  const [newCrit, setNewCrit] = React.useState('');
  const setRating = (c, v) => setGrille((g) => ({ ...g, ratings: { ...g.ratings, [c]: g.ratings[c] === v ? 0 : v } }));
  const sc = visiteScore(grille, activeCriteres(store));

  function addCustom() {
    const name = newCrit.trim();
    if (!name) return;
    const exists = VISITE_CRITERES.concat(customList).some((c) => c.toLowerCase() === name.toLowerCase());
    if (exists) { toast('Ce critère existe déjà'); return; }
    store.setVisiteCriteres([...customList, name]); // global → présent sur tous les biens
    setNewCrit('');
  }
  function removeCustom(name) {
    store.setVisiteCriteres(customList.filter((c) => c !== name));
  }

  function save() {
    store.updateProperty(p.id, { visiteGrille: grille });
    toast('Grille de visite enregistrée ✓');
    onClose();
  }

  const renderDots = (c) => (
    <div className="gr-dots">
      {[1, 2, 3, 4, 5].map((v) => (
        <button key={v} type="button"
          className={'gr-dot' + ((grille.ratings[c] || 0) >= v ? ' on' : '')}
          onClick={() => setRating(c, v)} aria-label={c + ' : ' + v + '/5'}></button>
      ))}
    </div>
  );

  const modalRef = useModalA11y(onClose);
  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" ref={modalRef} aria-label="Grille de visite" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <h2 className="disp" style={{ margin: 0 }}>Grille de visite</h2>
            <p style={{ margin: '4px 0 0', fontSize: 13, color: 'var(--muted)' }}>{p.title}</p>
          </div>
          <button className="icon-btn" onClick={onClose}><IconX size={18} /></button>
        </div>
        <div className="modal-body">
          <div className="grille-score">
            <b className="disp">{sc ? sc.avg.toFixed(1) : '—'}</b><span>/5</span>
            <span className="gs-sub">{sc ? `moyenne sur ${sc.count} critère${sc.count > 1 ? 's' : ''}` : 'notez les critères ci-dessous'}</span>
          </div>

          {VISITE_CRITERES.map((c) => (
            <div className="grille-row" key={c}>
              <span className="gr-label">{c}</span>
              {renderDots(c)}
            </div>
          ))}

          {customList.map((c) => (
            <div className="grille-row" key={c}>
              <span className="gr-label">
                {c}
                <button type="button" className="gr-del" onClick={() => removeCustom(c)} title="Retirer ce critère (de tous les biens)"><IconX size={11} sw={2.4} /></button>
              </span>
              {renderDots(c)}
            </div>
          ))}

          <div className="grille-add">
            <input value={newCrit} onChange={(e) => setNewCrit(e.target.value)}
              onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addCustom(); } }}
              placeholder="Ajouter un critère perso (box, fibre, exposition…)" />
            <button type="button" className="btn btn-out" onClick={addCustom}><IconPlus size={15} /> Ajouter</button>
          </div>
          <p className="grille-hint">Les critères perso sont communs à tous vos biens (réutilisés dans le comparateur).</p>

          <div className="field" style={{ marginTop: 18 }}>
            <label>Commentaire libre</label>
            <textarea value={grille.notes} onChange={(e) => setGrille((g) => ({ ...g, notes: e.target.value }))}
              placeholder="Impressions générales, points à revérifier, marge de négociation…"></textarea>
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn btn-ghost" onClick={onClose}>Annuler</button>
          <button className="btn btn-sage" onClick={save}>Enregistrer</button>
        </div>
      </div>
    </div>
  );
}

/* ---------- Onboarding première session (s9q09 / s9q10 / s9q12) ---------- */
function WelcomeTour({ store, go, openModal }) {
  const steps = [
    { n: '1', t: 'Suivez vos biens', d: 'Ajoutez chaque annonce qui vous intéresse : prix, surface, agent, notes. Fini le tableur.' },
    { n: '2', t: 'Préparez vos documents', d: 'La checklist liste tout ce qu’il faut réunir, par interlocuteur, selon votre situation.' },
    { n: '3', t: 'Comparez et décidez', d: 'Notez vos visites, mettez deux biens face à face et tranchez sereinement.' },
  ];
  return (
    <div className="panel" style={{ padding: '28px 26px', marginBottom: 22 }}>
      <h3 className="disp" style={{ fontSize: 22, marginBottom: 6 }}>Bienvenue sur Immoly 👋</h3>
      <p style={{ color: 'var(--muted)', fontSize: 15, marginBottom: 20 }}>Votre visite guidée en trois étapes — vous êtes opérationnel en une minute.</p>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 14, marginBottom: 22 }}>
        {steps.map((s) => (
          <div key={s.n} style={{ background: 'var(--cream-2)', border: '1px solid var(--hair)', borderRadius: 16, padding: '16px 16px' }}>
            <span style={{ display: 'inline-grid', placeItems: 'center', width: 26, height: 26, borderRadius: '50%', background: 'var(--sage)', color: '#fff', fontWeight: 700, fontSize: 13, marginBottom: 10 }}>{s.n}</span>
            <b style={{ display: 'block', fontSize: 15, marginBottom: 4 }}>{s.t}</b>
            <span style={{ fontSize: 13.5, color: 'var(--muted)' }}>{s.d}</span>
          </div>
        ))}
      </div>
      <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
        <button className="btn btn-sage" onClick={() => openModal(null)}><IconPlus size={16} stroke="#fff" /> Ajoutez votre premier bien</button>
        <button className="btn btn-out" onClick={() => { store.addDemoProperty(); go('tracker'); }}>Voir un bien d'exemple</button>
      </div>
    </div>
  );
}

/* ---------- Dashboard ---------- */
function Dashboard({ store, go, openModal }) {
  const { properties, documents } = store.state;
  const prenom = window.IMMOBASE_USER?.user_metadata?.prenom
    || window.IMMOBASE_USER?.user_metadata?.full_name?.split(' ')[0]
    || 'vous';
  const active = properties.filter((p) => p.status !== 'elimine');
  const favs = properties.filter((p) => p.favori);
  const doneDocs = documents.filter((d) => d.done).length;
  const pct = documents.length > 0 ? Math.round((doneDocs / documents.length) * 100) : 0;
  const upcoming = active
    .filter((p) => p.visitDate && new Date(p.visitDate + 'T00:00') >= new Date(new Date().toDateString()))
    .sort((a, b) => a.visitDate.localeCompare(b.visitDate));
  const nextDocs = documents.filter((d) => !d.done).slice(0, 3);

  return (
    <div className="view">
      <div className="greet">
        <h2 className="disp">Bonjour {prenom} 👋</h2>
        <p>Voici où en est votre projet aujourd'hui.</p>
      </div>

      {properties.length === 0 && <WelcomeTour store={store} go={go} openModal={openModal} />}

      <div className="stat-row">
        <div className="stat-card">
          <div className="si bg-sage"><IconHome size={20} /></div>
          <div className="sv disp">{active.length}</div>
          <div className="sl">Biens suivis</div>
        </div>
        <div className="stat-card">
          <div className="si bg-clay"><IconHeart size={20} /></div>
          <div className="sv disp">{favs.length}</div>
          <div className="sl">Coups de cœur</div>
        </div>
        <div className="stat-card">
          <div className="si bg-blue"><IconCal size={20} /></div>
          <div className="sv disp">{upcoming.length}</div>
          <div className="sl">Visites à venir</div>
        </div>
        <div className="stat-card">
          <div className="si bg-sage"><IconDoc size={20} /></div>
          <div className="sv disp">{pct}%</div>
          <div className="sl">Documents prêts</div>
        </div>
      </div>

      <div className="dash-cols">
        <div className="panel">
          <div className="panel-head">
            <h3 className="disp">Prochaines visites</h3>
            <button onClick={() => go('tracker')}>Tous les biens</button>
          </div>
          {upcoming.length === 0 ? (
            <div className="empty" style={{ padding: '30px 10px' }}>
              <p style={{ margin: 0 }}>Aucune visite programmée pour l'instant.</p>
            </div>
          ) : (
            <div className="next-list">
              {upcoming.map((p) => (
                <button key={p.id} className="next-item" onClick={() => go('tracker')}>
                  <span className="ni" style={{ background: 'var(--blue-soft)', color: 'var(--blue)' }}><IconCal size={18} /></span>
                  <span className="nb">
                    <b>{p.title} · {p.city.split(',')[0]}</b>
                    <span>{fmtDate(p.visitDate)} · {fmtEur(p.price)}</span>
                  </span>
                  <span className={'tag st-' + p.status}>{STATUS_LABELS[p.status]}</span>
                </button>
              ))}
            </div>
          )}

          <div className="panel-head" style={{ marginTop: 24 }}>
            <h3 className="disp">À faire ensuite</h3>
          </div>
          <div className="next-list">
            {window.isPro() && (
              <button className="next-item" onClick={() => go('emails')}>
                <span className="ni bg-clay"><IconMail size={18} /></span>
                <span className="nb"><b>Demander 3 documents en attente</b><span>Les emails sont déjà rédigés pour vous</span></span>
                <IconArrow size={18} stroke="var(--muted)" />
              </button>
            )}
            <button className="next-item" onClick={() => go('simulateur')}>
              <span className="ni bg-sage"><IconCalc size={18} /></span>
              <span className="nb"><b>Vérifier votre mensualité</b><span>Ajustez apport, durée et taux</span></span>
              <IconArrow size={18} stroke="var(--muted)" />
            </button>
            {window.isPro() && (
              <button className="next-item" onClick={() => go('comparateur')}>
                <span className="ni bg-blue"><IconCompare size={18} /></span>
                <span className="nb"><b>Comparer vos deux favoris</b><span>Tranchez sur les critères clés</span></span>
                <IconArrow size={18} stroke="var(--muted)" />
              </button>
            )}
            {!window.isPro() && (
              <a href="../Tarifs.html" className="next-item" style={{ textDecoration: 'none' }}>
                <span className="ni" style={{ background: 'var(--cream-deep, var(--cream-2))' }}><IconLock size={18} stroke="var(--muted)" /></span>
                <span className="nb"><b style={{ color: 'var(--muted)' }}>Checklist, emails, comparateur</b><span>Disponibles dans le plan Complet</span></span>
                <IconArrow size={18} stroke="var(--muted)" />
              </a>
            )}
          </div>
        </div>

        <div className="panel">
          <div className="panel-head">
            <h3 className="disp">Vos documents</h3>
            {window.isPro() && <button onClick={() => go('checklist')}>Voir tout</button>}
          </div>
          {!window.isPro() ? (
            <div className="dash-locked">
              <IconLock size={22} stroke="var(--muted)" sw={1.5} />
              <p>La checklist de documents est disponible dans le <b>plan Complet</b>.</p>
              <button type="button" className="btn btn-sage" style={{ fontSize: 13, padding: '8px 16px' }} onClick={() => window.openUpgrade()}>Passer au plan Complet</button>
            </div>
          ) : (
            <>
              <div className="prog-wrap">
                <div className="ring" style={{ '--p': pct, position: 'relative', display: 'grid' }}>
                  <b className="disp">{pct}%</b>
                </div>
                <div className="prog-info">
                  <b>{doneDocs} sur {documents.length} prêts</b>
                  <span>{documents.length - doneDocs} document{documents.length - doneDocs > 1 ? 's' : ''} encore à réunir</span>
                </div>
              </div>
              {nextDocs.map((d) => (
                <div className="mini-doc" key={d.id}>
                  <span className="mc" onClick={() => store.toggleDoc(d.id)} style={{ cursor: 'pointer' }}><IconCheck size={13} sw={2.2} /></span>
                  <span className="mn">{d.name}<span>{d.note}</span></span>
                  <span className="who">{RECIPIENTS[d.recipient].label}</span>
                </div>
              ))}
              {nextDocs.length === 0 && (
                <div className="mini-doc" style={{ color: 'var(--sage-deep)', fontWeight: 700 }}>
                  <span className="mc on"><IconCheck size={13} sw={2.2} /></span>
                  <span className="mn">Tous vos documents sont prêts !</span>
                </div>
              )}
            </>
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------- Tracker ---------- */
function Tracker({ store, openModal }) {
  const { properties } = store.state;
  const [filter, setFilter] = React.useState('tous');
  const [openStatus, setOpenStatus] = React.useState(null);
  const [detail, setDetail] = React.useState(null);
  const [wallDismissed, setWallDismissed] = React.useState(false); // « Plus tard » (s5q13)

  const filtered = filter === 'tous' ? properties : properties.filter((p) => p.status === filter);
  const counts = {
    tous: properties.length,
    ...STATUS_ORDER.reduce((a, s) => ({ ...a, [s]: properties.filter((p) => p.status === s).length }), {}),
  };

  // Le bien d'exemple ne compte pas dans la limite du plan gratuit (s9q10)
  const limitReached = !window.isPro() && properties.filter((p) => !p.demo).length >= window.FREE_PLAN_MAX_PROPERTIES;

  return (
    <div className="view">
      {limitReached && !wallDismissed && (
        <div className="tracker-limit-banner" role="region" aria-label="Limite du plan Découverte">
          <div className="tlb-text">
            <b>Votre {window.FREE_PLAN_MAX_PROPERTIES + 1}e bien ne tient plus dans le plan Découverte.</b>
            <span>Passez au Complet pour suivre tous vos biens — et les comparer.</span>
          </div>
          <div className="tlb-actions">
            <button type="button" className="btn btn-sage tlb-btn" onClick={() => window.openUpgrade()}>Passer au plan Complet</button>
            <button type="button" className="btn btn-ghost tlb-later" style={{ fontSize: 13, color: 'var(--muted)' }} onClick={() => setWallDismissed(true)}>Plus tard</button>
          </div>
        </div>
      )}
      <div className="tracker-toolbar">
        <button className={'filter-chip' + (filter === 'tous' ? ' on' : '')} onClick={() => setFilter('tous')}>Tous · {counts.tous}</button>
        {STATUS_ORDER.map((s) => (
          <button key={s} className={'filter-chip' + (filter === s ? ' on' : '')} onClick={() => setFilter(s)}>
            {STATUS_LABELS[s]} · {counts[s]}
          </button>
        ))}
        <div style={{ flex: 1 }}></div>
        {!limitReached && (
          <button className="btn btn-sage" onClick={() => openModal(null)}>
            <IconPlus size={16} stroke="#fff" /> Ajouter un bien
          </button>
        )}
        {limitReached && (
          <button type="button" className="btn btn-ghost" style={{ fontSize: 13, color: 'var(--muted)' }} onClick={() => window.openUpgrade()}>
            <IconLock size={14} /> Limite atteinte
          </button>
        )}
      </div>

      {filtered.length === 0 ? (
        <div className="empty">
          <div className="ei"><IconHome size={28} /></div>
          {properties.length === 0 ? (
            <>
              <h3 className="disp">Votre projet commence ici</h3>
              <p>Ajoutez le premier bien que vous suivez — annonce, prix, notes. Cela prend 30 secondes.</p>
              <button className="btn btn-sage" style={{ marginTop: 14 }} onClick={() => openModal(null)}>
                <IconPlus size={16} stroke="#fff" /> Ajoutez votre premier bien
              </button>
            </>
          ) : (
            <>
              <h3 className="disp">Aucun bien dans cette catégorie</h3>
              <p>Changez de filtre ou ajoutez un nouveau bien depuis le bouton « Ajouter un bien ».</p>
            </>
          )}
        </div>
      ) : (
        <div className="prop-grid">
          {filtered.map((p) => (
            <PropertyCard
              key={p.id} p={p} store={store} openModal={openModal}
              openDetail={() => setDetail(p)}
              openStatus={openStatus} setOpenStatus={setOpenStatus}
            />
          ))}
        </div>
      )}

      {detail && (
        <PropertyDetail
          p={detail}
          store={store}
          onClose={() => setDetail(null)}
          onEdit={() => { openModal(detail); setDetail(null); }}
        />
      )}
    </div>
  );
}

function PropertyCard({ p, store, openModal, openDetail, openStatus, setOpenStatus }) {
  const ppm = p.surface ? Math.round(p.price / p.surface) : 0;
  const isFav = !!p.favori;
  const initials = (p.agentName || '').split(' ').map((w) => w[0]).slice(0, 2).join('').toUpperCase();

  return (
    <div className={'prop-card' + (p.status === 'elimine' ? ' is-elimine' : '')}
      onClick={openDetail} style={{ cursor: 'pointer' }}>
      <div className="prop-img">
        {p.photoUrl && (
          <img src={p.photoUrl} alt="" className="prop-img-photo"
            onError={(e) => { e.target.style.display = 'none'; e.target.nextSibling.style.display = 'flex'; }}
          />
        )}
        <span className="note mono" style={p.photoUrl ? { display: 'none' } : {}}>photo · annonce</span>
        {p.demo && <span className="tag" style={{ position: 'absolute', top: 10, left: 10, background: 'var(--ink)', color: '#fff' }}>Exemple</span>}
        <button className={'fav' + (isFav ? ' on' : '')} title={isFav ? 'Retirer des coups de cœur' : 'Coup de cœur'}
          aria-pressed={isFav}
          onClick={(e) => { e.stopPropagation(); store.updateProperty(p.id, { favori: !isFav }); }}>
          <IconHeart size={18} fill={isFav ? 'var(--clay)' : 'none'} />
        </button>
        {(() => { const vs = visiteScore(p.visiteGrille, activeCriteres(store)); return vs ? <span className="visite-badge" title="Note de visite">★ {vs.avg.toFixed(1)}</span> : null; })()}
      </div>
      <div className="prop-b">
        <div className="price disp">{fmtEur(p.price)} {ppm > 0 && <span className="ppm">{fmtEur2(ppm)}/m²</span>}</div>
        <div className="ttl">{p.title} · {p.type}</div>
        <div className="loc"><IconPin size={13} stroke="var(--muted)" /> {p.city}</div>
        <div className="prop-meta">
          {p.surface > 0 && <span>{p.surface} m²</span>}
          {p.rooms > 0 && <span>{p.rooms} pièces</span>}
          {p.visitDate && <span>Visite {fmtDate(p.visitDate)}</span>}
        </div>

        {p.agentName && (
          <div className="agent-line">
            <span className="aav">{initials}</span>
            <span className="ai"><b>{p.agentName}</b><span>{p.agentAgency}</span></span>
          </div>
        )}

        <div className="prop-foot" onClick={(e) => e.stopPropagation()}>
          <div className="status-select">
            <button className={'status-btn st-' + p.status}
              onClick={() => setOpenStatus(openStatus === p.id ? null : p.id)}>
              <span style={{ width: 8, height: 8, borderRadius: 9, background: STATUS_DOT[p.status] }}></span>
              {STATUS_LABELS[p.status]}
              <IconChevron size={12} style={{ transform: 'rotate(90deg)' }} />
            </button>
            {openStatus === p.id && (
              <div className="status-menu">
                {STATUS_ORDER.map((s) => (
                  <button key={s} onClick={() => { store.updateProperty(p.id, { status: s }); setOpenStatus(null); }}>
                    <span className="sw" style={{ background: STATUS_DOT[s] }}></span>{STATUS_LABELS[s]}
                  </button>
                ))}
              </div>
            )}
          </div>
          <div className="prop-actions">
            <button title="Modifier" onClick={() => openModal(p)}><IconEdit size={16} /></button>
            <button title={p.demo ? "Supprimer le bien d'exemple" : 'Supprimer'} onClick={() => { if (p.demo || confirm('Supprimer ce bien ?')) { store.removeProperty(p.id); toast(p.demo ? "Bien d'exemple supprimé" : 'Bien supprimé'); } }}><IconTrash size={16} /></button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ---------- Property detail ---------- */
function PropertyDetail({ p, store, onClose, onEdit }) {
  const live = store.state.properties.find((x) => x.id === p.id) || p;
  const ppm = p.surface ? Math.round(p.price / p.surface) : 0;
  const annonceUrl = p.url ? (p.url.startsWith('http') ? p.url : 'https://' + p.url) : null;
  const initials = (p.agentName || '').split(' ').map((w) => w[0]).slice(0, 2).join('').toUpperCase();
  const [showGrille, setShowGrille] = React.useState(false);
  const sc = visiteScore(live.visiteGrille, activeCriteres(store));

  function handleDelete() {
    // Le bien d'exemple se supprime en un clic, sans confirmation (s9q10)
    if (p.demo || confirm('Supprimer ce bien ?')) {
      store.removeProperty(p.id);
      toast(p.demo ? "Bien d'exemple supprimé" : 'Bien supprimé');
      onClose();
    }
  }

  const modalRef = useModalA11y(onClose);
  return (
    <>
    <div className="modal-bg" onClick={onClose}>
      <div className="modal detail-modal" ref={modalRef} aria-label={'Fiche du bien ' + p.title} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            <h2 className="disp" style={{ margin: 0 }}>{p.title}</h2>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span className={'tag st-' + p.status}>{STATUS_LABELS[p.status]}</span>
              {p.type && <span style={{ fontSize: 13, color: 'var(--muted)' }}>{p.type}</span>}
            </div>
          </div>
          <button className="icon-btn" onClick={onClose}><IconX size={18} /></button>
        </div>

        <div className="modal-body detail-body">
          {p.photoUrl && (
            <div className="detail-photo" style={{ backgroundImage: `url(${p.photoUrl})` }}></div>
          )}
          <div className="detail-price">
            <span className="disp">{fmtEur(p.price)}</span>
            {ppm > 0 && <span className="detail-ppm">{fmtEur2(ppm)}/m²</span>}
          </div>

          <div className="detail-chips">
            {p.city && <span><IconPin size={12} /> {p.city}</span>}
            {p.surface > 0 && <span>{p.surface} m²</span>}
            {p.rooms > 0 && <span>{p.rooms} pièces</span>}
            {p.floor > 0 && <span>Étage {p.floor}</span>}
          </div>

          {p.visitDate && (
            <div className="detail-row">
              <IconCal size={15} stroke="var(--sage-deep)" />
              <span>Visite prévue le <b>{fmtDate(p.visitDate)}</b></span>
            </div>
          )}

          {p.agentName && (
            <div className="detail-agent">
              <span className="aav">{initials}</span>
              <div className="detail-agent-info">
                <b>{p.agentName}</b>
                {p.agentAgency && <span>{p.agentAgency}</span>}
                {p.agentPhone && (
                  <a href={'tel:' + p.agentPhone} className="detail-phone" onClick={(e) => e.stopPropagation()}>
                    <IconPhone size={13} /> {p.agentPhone}
                  </a>
                )}
              </div>
            </div>
          )}

          {annonceUrl && (
            <a href={annonceUrl} target="_blank" rel="noopener noreferrer"
              className="detail-link" onClick={(e) => e.stopPropagation()}>
              <IconExternal size={14} /> Voir l'annonce
            </a>
          )}

          {p.notes && (
            <div className="detail-notes">
              <div className="detail-notes-label"><IconNote size={14} /> Notes personnelles</div>
              <p>{p.notes}</p>
            </div>
          )}

          {window.isPro() ? (
            <button className="detail-grille-btn" onClick={() => setShowGrille(true)}>
              <span className="dg-ico"><IconCheck size={16} sw={2.2} /></span>
              <span className="dg-txt">
                <b>Note d'évaluation</b>
                <span>{sc ? `Note ${sc.avg.toFixed(1)}/5 · ${sc.count} critère${sc.count > 1 ? 's' : ''}` : 'Pas encore évaluée'}</span>
              </span>
              {sc && <span className="dg-score">{sc.avg.toFixed(1)}</span>}
              <IconArrow size={16} stroke="var(--muted)" />
            </button>
          ) : (
            <button type="button" className="detail-grille-btn detail-grille-locked" onClick={() => window.openUpgrade()}>
              <span className="dg-ico"><IconLock size={15} sw={2.2} /></span>
              <span className="dg-txt">
                <b>Note d'évaluation</b>
                <span>Évaluez vos biens (grille de visite) avec le plan Complet</span>
              </span>
              <IconArrow size={16} stroke="var(--muted)" />
            </button>
          )}
        </div>

        <div className="modal-foot">
          <button className="btn btn-ghost" style={{ color: 'var(--clay-deep)' }} onClick={handleDelete}>
            <IconTrash size={15} /> Supprimer
          </button>
          <button className="btn btn-sage" onClick={onEdit}>
            <IconEdit size={15} stroke="#fff" /> Modifier
          </button>
        </div>
      </div>
    </div>
    {showGrille && window.isPro() && <GrilleModal p={live} store={store} onClose={() => setShowGrille(false)} />}
    </>
  );
}

/* ---------- Property modal (add / edit) ---------- */
function PropertyModal({ initial, store, onClose }) {
  const blank = { title: '', type: 'Appartement', city: '', price: '', surface: '', rooms: '', status: 'a-visiter', favori: false, visitDate: '', agentName: '', agentAgency: '', agentPhone: '', notes: '', url: '', photoUrl: '', photoPath: '', fees: '', charges: '', dpe: '', travaux: '' };
  const [f, setF] = React.useState(initial ? { ...initial } : blank);
  const [uploadingPhoto, setUploadingPhoto] = React.useState(false);
  const set = (k) => (e) => setF((prev) => ({ ...prev, [k]: e.target.value }));

  async function handlePhotoUpload(e) {
    const file = e.target.files?.[0];
    if (!file) return;
    setUploadingPhoto(true);
    try {
      const userId = window.IMMOBASE_USER?.id;
      if (!userId) throw new Error('Session expirée — reconnectez-vous');
      // Bucket PRIVÉ (P0-08) : chemin userId/uuid.ext + URL signée (jamais publique)
      const ext = (file.name.split('.').pop() || 'jpg').toLowerCase();
      const uuid = (crypto.randomUUID ? crypto.randomUUID() : Date.now() + '-' + Math.random().toString(36).slice(2));
      const path = `${userId}/${uuid}.${ext}`;
      const { error } = await window.sb.storage
        .from('property-photos')
        .upload(path, file, { upsert: false });
      if (error) throw error;
      const { data, error: signErr } = await window.sb.storage
        .from('property-photos')
        .createSignedUrl(path, 60 * 60 * 24);
      if (signErr) throw signErr;
      setF((prev) => ({ ...prev, photoPath: path, photoUrl: data.signedUrl }));
      toast('Photo ajoutée ✓');
    } catch (err) {
      toast('Erreur upload : ' + err.message);
    } finally {
      setUploadingPhoto(false);
    }
  }

  function save() {
    if (!f.title.trim()) { toast('Donnez un titre au bien'); return; }
    // Frais / charges / travaux : saisis par l'utilisateur. Vide = null (« — »,
    // exclu du verdict du comparateur). Plus AUCUNE valeur inventée (P0-15).
    const data = {
      ...f,
      price:   Number(f.price) || 0,
      surface: Number(f.surface) || 0,
      rooms:   Number(f.rooms) || 0,
      fees:    f.fees === '' || f.fees == null ? null : Number(f.fees),
      charges: f.charges === '' || f.charges == null ? null : Number(f.charges),
      travaux: f.travaux === '' || f.travaux == null ? null : Number(f.travaux),
      dpe:     f.dpe || '',
      favori:  !!f.favori,
    };
    if (initial) { store.updateProperty(initial.id, data); toast('Bien mis à jour ✓'); }
    else { store.addProperty(data); toast('Bien ajouté ✓'); }
    onClose();
  }

  const modalRef = useModalA11y(onClose);
  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" ref={modalRef} aria-label={initial ? 'Modifier le bien' : 'Ajouter un bien'} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h2 className="disp">{initial ? 'Modifier le bien' : 'Ajouter un bien'}</h2>
          <button className="icon-btn" onClick={onClose}><IconX size={18} /></button>
        </div>
        <div className="modal-body">
          <div className="field"><label>Titre</label><input value={f.title} onChange={set('title')} placeholder="Appartement lumineux" /></div>
          <div className="field-row">
            <div className="field"><label>Type</label>
              <select value={f.type} onChange={set('type')}>
                {['Appartement', 'Maison', 'Maison de ville', 'Duplex', 'Studio', 'Loft', 'Villa'].map((t) => <option key={t}>{t}</option>)}
              </select>
            </div>
            <div className="field"><label>Ville / quartier</label><input value={f.city} onChange={set('city')} placeholder="Le Marais, Paris" /></div>
          </div>
          <div className="field-row">
            <div className="field"><label>Prix (€)</label><input type="number" value={f.price} onChange={set('price')} placeholder="319000" /></div>
            <div className="field"><label>Surface (m²)</label><input type="number" value={f.surface} onChange={set('surface')} placeholder="72" /></div>
          </div>
          <div className="field-row">
            <div className="field"><label>Pièces</label><input type="number" value={f.rooms} onChange={set('rooms')} placeholder="4" /></div>
            <div className="field"><label>Statut</label>
              <select value={f.status} onChange={set('status')}>
                {STATUS_ORDER.map((s) => <option key={s} value={s}>{STATUS_LABELS[s]}</option>)}
              </select>
            </div>
          </div>
          <div className="field-row">
            <div className="field"><label>Date de visite</label><input type="date" value={f.visitDate} onChange={set('visitDate')} /></div>
            <div className="field"><label>Lien de l'annonce</label><input value={f.url} onChange={set('url')} placeholder="seloger.com/…" /></div>
          </div>
          <div className="field-row">
            <div className="field"><label>Agent</label><input value={f.agentName} onChange={set('agentName')} placeholder="Camille Durand" /></div>
            <div className="field"><label>Agence</label><input value={f.agentAgency} onChange={set('agentAgency')} placeholder="Century 21 Centre" /></div>
          </div>
          <div className="field-row">
            <div className="field"><label>Frais d'agence (€) <span style={{ color: 'var(--muted)', fontWeight: 400 }}>· optionnel</span></label><input type="number" value={f.fees ?? ''} onChange={set('fees')} placeholder="ex. 9000 — vide si inconnu" /></div>
            <div className="field"><label>Charges / mois (€) <span style={{ color: 'var(--muted)', fontWeight: 400 }}>· optionnel</span></label><input type="number" value={f.charges ?? ''} onChange={set('charges')} placeholder="ex. 120 — vide si inconnu" /></div>
          </div>
          <div className="field-row">
            <div className="field"><label>DPE <span style={{ color: 'var(--muted)', fontWeight: 400 }}>· optionnel</span></label>
              <select value={f.dpe || ''} onChange={set('dpe')}>
                <option value="">Non renseigné</option>
                {['A', 'B', 'C', 'D', 'E', 'F', 'G'].map((g) => <option key={g} value={g}>{g}</option>)}
              </select>
            </div>
            <div className="field"><label>Budget travaux (€) <span style={{ color: 'var(--muted)', fontWeight: 400 }}>· optionnel</span></label><input type="number" value={f.travaux ?? ''} onChange={set('travaux')} placeholder="ex. 15000 — vide si aucun" /></div>
          </div>
          <label style={{ display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer', margin: '2px 0 8px', fontSize: 14, fontWeight: 700 }}>
            <input type="checkbox" checked={!!f.favori} onChange={(e) => setF((prev) => ({ ...prev, favori: e.target.checked }))} style={{ width: 18, height: 18, accentColor: 'var(--clay)' }} />
            <IconHeart size={16} fill={f.favori ? 'var(--clay)' : 'none'} /> Coup de cœur (favori)
          </label>
          <div className="field">
            <label>Photo du bien</label>
            <label className={'photo-upload-btn' + (uploadingPhoto ? ' loading' : '')}>
              <input type="file" accept="image/*" style={{ display: 'none' }} onChange={handlePhotoUpload} disabled={uploadingPhoto} />
              <IconPlus size={15} /> {uploadingPhoto ? 'Envoi en cours…' : f.photoUrl ? 'Changer la photo' : 'Ajouter une photo'}
            </label>
            {f.photoUrl && (
              <div style={{ position: 'relative', marginTop: 10 }}>
                <img src={f.photoUrl} alt="" style={{ width: '100%', height: 140, objectFit: 'cover', borderRadius: 10 }} />
                <button className="photo-remove" onClick={() => setF((prev) => ({ ...prev, photoUrl: '', photoPath: '' }))} title="Supprimer la photo">
                  <IconX size={14} />
                </button>
              </div>
            )}
            {!f.photoUrl && (
              <input style={{ marginTop: 8 }} value={f.photoUrl || ''} onChange={set('photoUrl')} placeholder="Ou collez une URL si l'image est déjà hébergée quelque part" />
            )}
          </div>
          <div className="field"><label>Notes personnelles</label><textarea value={f.notes} onChange={set('notes')} placeholder="Vos impressions, points à vérifier…"></textarea></div>
        </div>
        <div className="modal-foot">
          <button className="btn btn-ghost" onClick={onClose}>Annuler</button>
          <button className="btn btn-sage" onClick={save}>{initial ? 'Enregistrer' : 'Ajouter le bien'}</button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Dashboard, Tracker, PropertyCard, PropertyDetail, PropertyModal, toast, STATUS_DOT });
