/* =========================================================
   Tappt — Exchange (contact exchange + mini-CRM)
   - ExchangeConfigSheet: build your form (fields, display, sticky)
   - ExchangeForm: visitor-facing form (photo, location, fields)
   - LeadDetailSheet: CRM record (stage, potential, met-at, notes, next action)
   Shared by dashboard + public profile. Loaded after app-dash.jsx.
   ========================================================= */
const { useState: exUse, useRef: exRef } = React;

/* curated dial-code list (searchable in the phone picker) */
const DIAL_CODES = [
  { c: 'GB', d: '+44', n: 'United Kingdom', f: '🇬🇧' }, { c: 'US', d: '+1', n: 'United States', f: '🇺🇸' },
  { c: 'IE', d: '+353', n: 'Ireland', f: '🇮🇪' }, { c: 'CA', d: '+1', n: 'Canada', f: '🇨🇦' },
  { c: 'AU', d: '+61', n: 'Australia', f: '🇦🇺' }, { c: 'NZ', d: '+64', n: 'New Zealand', f: '🇳🇿' },
  { c: 'FR', d: '+33', n: 'France', f: '🇫🇷' }, { c: 'DE', d: '+49', n: 'Germany', f: '🇩🇪' },
  { c: 'ES', d: '+34', n: 'Spain', f: '🇪🇸' }, { c: 'IT', d: '+39', n: 'Italy', f: '🇮🇹' },
  { c: 'PT', d: '+351', n: 'Portugal', f: '🇵🇹' }, { c: 'NL', d: '+31', n: 'Netherlands', f: '🇳🇱' },
  { c: 'BE', d: '+32', n: 'Belgium', f: '🇧🇪' }, { c: 'CH', d: '+41', n: 'Switzerland', f: '🇨🇭' },
  { c: 'AT', d: '+43', n: 'Austria', f: '🇦🇹' }, { c: 'SE', d: '+46', n: 'Sweden', f: '🇸🇪' },
  { c: 'NO', d: '+47', n: 'Norway', f: '🇳🇴' }, { c: 'DK', d: '+45', n: 'Denmark', f: '🇩🇰' },
  { c: 'FI', d: '+358', n: 'Finland', f: '🇫🇮' }, { c: 'PL', d: '+48', n: 'Poland', f: '🇵🇱' },
  { c: 'CZ', d: '+420', n: 'Czechia', f: '🇨🇿' }, { c: 'GR', d: '+30', n: 'Greece', f: '🇬🇷' },
  { c: 'AE', d: '+971', n: 'United Arab Emirates', f: '🇦🇪' }, { c: 'SA', d: '+966', n: 'Saudi Arabia', f: '🇸🇦' },
  { c: 'QA', d: '+974', n: 'Qatar', f: '🇶🇦' }, { c: 'IN', d: '+91', n: 'India', f: '🇮🇳' },
  { c: 'PK', d: '+92', n: 'Pakistan', f: '🇵🇰' }, { c: 'SG', d: '+65', n: 'Singapore', f: '🇸🇬' },
  { c: 'HK', d: '+852', n: 'Hong Kong', f: '🇭🇰' }, { c: 'JP', d: '+81', n: 'Japan', f: '🇯🇵' },
  { c: 'KR', d: '+82', n: 'South Korea', f: '🇰🇷' }, { c: 'CN', d: '+86', n: 'China', f: '🇨🇳' },
  { c: 'ZA', d: '+27', n: 'South Africa', f: '🇿🇦' }, { c: 'NG', d: '+234', n: 'Nigeria', f: '🇳🇬' },
  { c: 'KE', d: '+254', n: 'Kenya', f: '🇰🇪' }, { c: 'EG', d: '+20', n: 'Egypt', f: '🇪🇬' },
  { c: 'BR', d: '+55', n: 'Brazil', f: '🇧🇷' }, { c: 'MX', d: '+52', n: 'Mexico', f: '🇲🇽' },
  { c: 'AR', d: '+54', n: 'Argentina', f: '🇦🇷' }, { c: 'TR', d: '+90', n: 'Turkey', f: '🇹🇷' },
  { c: 'IL', d: '+972', n: 'Israel', f: '🇮🇱' }, { c: 'TH', d: '+66', n: 'Thailand', f: '🇹🇭' },
  { c: 'ID', d: '+62', n: 'Indonesia', f: '🇮🇩' }, { c: 'MY', d: '+60', n: 'Malaysia', f: '🇲🇾' },
  { c: 'PH', d: '+63', n: 'Philippines', f: '🇵🇭' }, { c: 'VN', d: '+84', n: 'Vietnam', f: '🇻🇳' },
];

/* searchable dial-code picker overlay */
function DialPicker({ onPick, onClose }) {
  const [q, setQ] = exUse('');
  const list = DIAL_CODES.filter((c) => { const s = q.trim().toLowerCase(); return !s || c.n.toLowerCase().includes(s) || c.d.includes(s) || c.c.toLowerCase().includes(s); });
  return (
    <div className="dial-bg" onClick={(ev) => { if (ev.target === ev.currentTarget) onClose(); }}>
      <div className="dial-sheet">
        <div className="dial-head"><h3>Country code</h3><button className="dial-x" onClick={onClose}>{(window.MI.close ? window.MI.close({ width: 18, height: 18 }) : '✕')}</button></div>
        <input className="dial-search" autoFocus placeholder="Search country or code" value={q} onChange={(ev) => setQ(ev.target.value)} />
        <div className="dial-list">
          {list.map((c) => (
            <button key={c.c + c.d} className="dial-row" onClick={() => onPick(c)}>
              <span className="dial-flag">{c.f}</span>
              <span className="dial-name">{c.n}</span>
              <span className="dial-d">{c.d}</span>
            </button>
          ))}
          {!list.length && <div className="dial-empty">No match</div>}
        </div>
      </div>
    </div>
  );
}
window.DialPicker = DialPicker;

const EX_DEFAULT = {
  on: false,
  headline: 'Leave your details.',
  subtext: "Share your info and I'll send mine.",
  cta: 'Send my details',
  fields: {
    email:    { on: true,  req: 'required' },
    phone:    { on: true,  req: 'required' },
    company:  { on: true,  req: 'optional' },
    jobTitle: { on: false, req: 'optional' },
    linkedin: { on: false, req: 'optional' },
    question: { on: false, label: 'How can I help?' },
  },
  custom: [],
  askPhoto: true,
  askLocation: true,
  display: 'button',   // button · link · card
  sticky: false,
};
function exConf(user) { return Object.assign({}, EX_DEFAULT, user.exchange || {}, { fields: Object.assign({}, EX_DEFAULT.fields, (user.exchange || {}).fields || {}) }); }
window.exConf = exConf;

const EX_STAGES = [
  { id: 'new', label: 'New', color: '#2ED573' },
  { id: 'contacted', label: 'Contacted', color: '#5CC8FF' },
  { id: 'meeting', label: 'Meeting', color: '#7C5CFF' },
  { id: 'client', label: 'Client', color: '#E8C75A' },
  { id: 'cold', label: 'Cold', color: '#8A8A92' },
];
window.EX_STAGES = EX_STAGES;
const exStage = (id) => EX_STAGES.find((s) => s.id === id) || EX_STAGES[0];
window.exStage = exStage;

const ADD_FIELDS = [
  { id: 'company', label: 'Company', icon: 'company' },
  { id: 'jobTitle', label: 'Job title', icon: 'briefcase' },
  { id: 'linkedin', label: 'LinkedIn', icon: 'linkedin' },
];

/* ---------- CONFIG SHEET (edit your exchange form) ---------- */
function ExchangeConfigSheet({ user, draft, onChange, onClose }) {
  const e = exConf({ exchange: draft });
  const [iconFor, setIconFor] = exUse(null);
  const setF = (key, patch) => onChange({ fields: Object.assign({}, e.fields, { [key]: Object.assign({}, e.fields[key], patch) }) });
  const reqDD = (key) => (
    <select className="ex-req" value={e.fields[key].req} onChange={(ev) => setF(key, { req: ev.target.value })}>
      <option value="required">Required</option>
      <option value="optional">Optional</option>
    </select>
  );
  const removed = e.removed || [];
  const rmField = (key) => onChange({ removed: removed.concat([key]), fields: Object.assign({}, e.fields, { [key]: Object.assign({}, e.fields[key], { on: false }) }) });
  const row = (key, label, iconId) => (removed.indexOf(key) >= 0 ? null : (
    <div className={'ex-field' + (e.fields[key].on ? '' : ' off')}>
      <span className="ex-fic">{XI[iconId] ? XI[iconId]({ width: 17, height: 17 }) : null}</span>
      <span className="ex-flabel">{label}</span>
      {e.fields[key].on && reqDD(key)}
      <button className={'switch' + (e.fields[key].on ? ' on' : '')} onClick={() => setF(key, { on: !e.fields[key].on })} />
      <button className="ex-field-x" onClick={() => rmField(key)} aria-label="Remove">{XI.close ? XI.close({ width: 14, height: 14 }) : '✕'}</button>
    </div>
  ));
  const CF_ICONS = ['link', 'company', 'briefcase', 'mail', 'phone', 'pin', 'help', 'user', 'instagram', 'linkedin', 'globe', 'calendar', 'star', 'heart', 'card', 'image'];
  return (
    <div className="sheet-bg" onClick={(ev) => { if (ev.target === ev.currentTarget) onClose(); }}>
      <div className="sheet">
        <div className="sheet-grab" />
        <div className="sheet-head">
          <span style={{ width: 56 }} />
          <h3>Exchange form</h3>
          <button className="glass-pill" style={{ background: 'var(--accent)', color: 'var(--accent-ink)', border: 'none' }} onClick={onClose}>Done</button>
        </div>
        <div className="sheet-scroll">
          {/* headline */}
          <div className="field"><label>Headline</label>
            <input className="input" value={e.headline} onChange={(ev) => onChange({ headline: ev.target.value })} placeholder="Leave your details." />
            <div className="ex-hint">Visitors see this at the top of the exchange form.</div>
          </div>
          <div className="field"><label>Subtext</label>
            <input className="input" value={e.subtext} onChange={(ev) => onChange({ subtext: ev.target.value })} placeholder="Share your info and I'll send mine." />
          </div>

          {/* core fields */}
          <div className="ex-grouplabel">Fields</div>
          <div className="ex-field locked"><span className="ex-fic">{XI.user ? XI.user({ width: 17, height: 17 }) : '◔'}</span><span className="ex-flabel">Name</span><span className="ex-always">Always on</span></div>
          {row('email', 'Email', 'mail')}
          {row('phone', 'Phone', 'phone')}

          {/* additional */}
          <div className="ex-grouplabel">Additional fields</div>
          {row('company', 'Company', 'company')}
          {row('jobTitle', 'Job title', 'briefcase')}
          {row('linkedin', 'LinkedIn', 'linkedin')}
          {/* custom question */}
          <div className={'ex-field q' + (e.fields.question.on ? '' : ' off')}>
            <span className="ex-fic">{XI.help ? XI.help({ width: 17, height: 17 }) : '?'}</span>
            <input className="ex-qinput" placeholder="Ask a question…" value={e.fields.question.label} onChange={(ev) => setF('question', { label: ev.target.value })} />
            <button className={'switch' + (e.fields.question.on ? ' on' : '')} onClick={() => setF('question', { on: !e.fields.question.on })} />
          </div>
          {/* custom fields the user adds */}
          {(e.custom || []).map((cf, i) => (
            <div className="ex-field q" key={cf.id}>
              <button className="ex-fic ex-fic-pick" onClick={() => setIconFor(iconFor === cf.id ? null : cf.id)} aria-label="Pick icon">{XI[cf.icon || 'help'] ? XI[cf.icon || 'help']({ width: 17, height: 17 }) : '+'}</button>
              <input className="ex-qinput" placeholder="Field label…" value={cf.label} onChange={(ev) => onChange({ custom: (e.custom || []).map((x) => x.id === cf.id ? Object.assign({}, x, { label: ev.target.value }) : x) })} />
              <select className="ex-req" value={cf.req || 'optional'} onChange={(ev) => onChange({ custom: (e.custom || []).map((x) => x.id === cf.id ? Object.assign({}, x, { req: ev.target.value }) : x) })}>
                <option value="required">Required</option>
                <option value="optional">Optional</option>
              </select>
              <button className="ex-field-x" onClick={() => onChange({ custom: (e.custom || []).filter((x) => x.id !== cf.id) })}>{XI.close ? XI.close({ width: 14, height: 14 }) : '✕'}</button>
              {iconFor === cf.id && (
                <div className="ex-iconpop">
                  {CF_ICONS.map((ic) => (
                    <button key={ic} className={'ex-iconopt' + ((cf.icon || 'help') === ic ? ' on' : '')} onClick={() => { onChange({ custom: (e.custom || []).map((x) => x.id === cf.id ? Object.assign({}, x, { icon: ic }) : x) }); setIconFor(null); }}>{XI[ic] ? XI[ic]({ width: 18, height: 18 }) : ic}</button>
                  ))}
                </div>
              )}
            </div>
          ))}
          <button className="ex-addfield" onClick={() => onChange({ custom: (e.custom || []).concat([{ id: 'cf' + Date.now(), label: '', req: 'optional', icon: 'help' }]) })}>{XI.plus ? XI.plus({ width: 15, height: 15 }) : '+'} Add a field</button>

          {/* extras */}
          <div className="ex-grouplabel">When someone exchanges</div>
          <button className="ex-toggle-row" onClick={() => onChange({ askPhoto: !e.askPhoto })}>
            <span className="ex-fic">{XI.image ? XI.image({ width: 17, height: 17 }) : '🖼'}</span>
            <span className="ex-tr-meta"><b>Ask for their photo</b><span>So you recognise who you met</span></span>
            <span className={'switch' + (e.askPhoto ? ' on' : '')} />
          </button>
          <button className="ex-toggle-row" onClick={() => onChange({ askLocation: !e.askLocation })}>
            <span className="ex-fic">{XI.pin ? XI.pin({ width: 17, height: 17 }) : '📍'}</span>
            <span className="ex-tr-meta"><b>Capture meeting location</b><span>Pins where you met on your Connections map</span></span>
            <span className={'switch' + (e.askLocation ? ' on' : '')} />
          </button>

          {/* display */}
          <div className="ex-grouplabel">How it shows on your profile</div>
          <div className="ex-display-grid">
            {[['button', 'Button'], ['link', 'Link row'], ['card', 'Card']].map(([id, lb]) => (
              <button key={id} className={'ex-disp' + (e.display === id ? ' sel' : '')} onClick={() => onChange({ display: id })}>
                <span className={'ex-disp-prev dp-' + id} />
                <span className="ex-disp-lb">{lb}</span>
              </button>
            ))}
          </div>
          <button className="ex-toggle-row" onClick={() => onChange({ sticky: !e.sticky })}>
            <span className="ex-fic">{XI.pin ? XI.pin({ width: 17, height: 17 }) : '📌'}</span>
            <span className="ex-tr-meta"><b>Sticky button</b><span>Always visible, pinned to the bottom of your profile</span></span>
            <span className={'switch' + (e.sticky ? ' on' : '')} />
          </button>
          <div style={{ height: 20 }} />
        </div>
      </div>
    </div>
  );
}
window.ExchangeConfigSheet = ExchangeConfigSheet;

/* ---------- VISITOR EXCHANGE FORM ---------- */
function ExchangeForm({ user, onClose, onSubmit }) {
  const e = exConf(user);
  const [d, setD] = exUse({ name: '', email: '', phone: '', company: '', jobTitle: '', linkedin: '', answer: '', photo: null, custom: {} });
  const [loc, setLoc] = exUse(false);
  const [busy, setBusy] = exUse(false);
  const [done, setDone] = exUse(false);
  const [dial, setDial] = exUse(DIAL_CODES[0]);   // default GB
  const [dialOpen, setDialOpen] = exUse(false);
  const photoRef = exRef(null);
  const set = (p) => setD((s) => Object.assign({}, s, p));
  const first = (user.name || 'them').split(' ')[0];

  // toggling "share where we met" ON triggers the OS location-permission prompt right away
  // (like iOS does) so the visitor grants it in context, not at submit time
  const toggleLoc = () => {
    const next = !loc;
    setLoc(next);
    if (next && navigator.geolocation) {
      try { navigator.geolocation.getCurrentPosition(function () {}, function () {}, { timeout: 8000 }); } catch (er) {}
    }
  };

  const reqOk = () => {
    if (!d.name.trim()) return false;
    if (e.fields.email && e.fields.email.on && e.fields.email.req === 'required' && !d.email.trim()) return false;
    for (const k of ['phone', 'company', 'jobTitle', 'linkedin']) {
      if (e.fields[k] && e.fields[k].on && e.fields[k].req === 'required' && !String(d[k] || '').trim()) return false;
    }
    for (const cf of (e.custom || [])) {
      if (cf.req === 'required' && !String((d.custom || {})[cf.id] || '').trim()) return false;
    }
    return true;
  };

  const submit = () => {
    if (!reqOk() || busy) return;
    setBusy(true);
    // capture card-vs-bio from the PAGE url now, before `location` is shadowed by the geo param below
    const viaSource = (() => { try { return new URLSearchParams(window.location.search).get('c') ? 'card' : 'bio'; } catch (e2) { return 'bio'; } })();
    const finish = (location) => {
      const lead = {
        id: (window.newId ? window.newId() : 'l' + Date.now()),
        name: d.name.trim(), email: d.email.trim(), phone: d.phone.trim() ? (dial.d + ' ' + d.phone.trim()) : '',
        company: d.company.trim(), jobTitle: d.jobTitle.trim(), linkedin: d.linkedin.trim(),
        answer: d.answer.trim(), photo: d.photo, location: location || null,
        custom: (e.custom || []).filter((cf) => (d.custom || {})[cf.id]).map((cf) => ({ label: cf.label, value: (d.custom || {})[cf.id] })),
        ts: Date.now(), source: 'Exchange · ' + (user.handle ? '@' + user.handle : 'profile'),
        via: viaSource,
        stage: (user.followupStage || 'new'), potential: '', notes: '', nextAction: null,
        metAt: location && location.place ? location.place : '',
      };
      onSubmit && onSubmit(lead);
      setBusy(false); setDone(true);
    };
    if (loc && e.askLocation && navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        (pos) => {
          const lat = pos.coords.latitude, lng = pos.coords.longitude;
          // reverse-geocode to a human place name (e.g. "Tockwith, York")
          fetch('https://nominatim.openstreetmap.org/reverse?format=json&zoom=14&lat=' + lat + '&lon=' + lng, { headers: { 'Accept': 'application/json' } })
            .then((r) => r.json())
            .then((j) => {
              const a = (j && j.address) || {};
              const small = a.village || a.suburb || a.town || a.hamlet || a.neighbourhood || a.city_district || '';
              const big = a.city || a.town || a.county || a.state || '';
              const place = [small, big].filter(Boolean).filter((v, i, arr) => arr.indexOf(v) === i).join(', ') || (j && j.display_name ? j.display_name.split(',').slice(0, 2).join(',') : 'Shared location');
              finish({ lat: lat, lng: lng, place: place });
            })
            .catch(() => finish({ lat: lat, lng: lng, place: 'Shared location' }));
        },
        () => finish(null), { timeout: 6000 }
      );
    } else finish(null);
  };

  const pickPhoto = (ev) => {
    const f = ev.target.files && ev.target.files[0]; if (!f) return;
    const r = new FileReader(); r.onload = () => set({ photo: r.result }); r.readAsDataURL(f); ev.target.value = '';
  };

  return (
    <div className="sheet-bg exchange-bg" onClick={(ev) => { if (ev.target === ev.currentTarget) onClose(); }}>
      <div className="exchange-sheet">
        {done ? (
          <div className="ex-done">
            <div className="ex-done-check">{MI.check ? MI.check({ width: 30, height: 30 }) : '✓'}</div>
            <h2>Sent to {first}</h2>
            <p>{first} now has your details{loc ? ' and where you met' : ''}. Nice to connect.</p>
            <button className="ex-submit" onClick={onClose}>Done</button>
          </div>
        ) : (
          <React.Fragment>
            <button className="ex-close" onClick={onClose} aria-label="Close">{MI.close ? MI.close({ width: 18, height: 18 }) : '✕'}</button>
            <div className="ex-form-head">
              <div className="ex-eyebrow">Let's connect</div>
              <h2 className="ex-h">{e.headline}</h2>
              <p className="ex-sub">{e.subtext}</p>
            </div>
            <div className="ex-form-body">
              {e.askPhoto && (
                <button className="ex-photo" onClick={() => photoRef.current && photoRef.current.click()}>
                  {d.photo ? <img src={d.photo} alt="" /> : <span className="ex-photo-empty">{MI.camera ? MI.camera({ width: 22, height: 22 }) : '📷'}<span>Add your photo</span></span>}
                  <input ref={photoRef} type="file" accept="image/*" capture="user" style={{ display: 'none' }} onChange={pickPhoto} />
                </button>
              )}
              <div className="ex-field-in"><label>Name</label><input className="ex-input" placeholder="Your name" value={d.name} onChange={(ev) => set({ name: ev.target.value })} /></div>
              {e.fields.email.on && <div className="ex-field-in"><label>Email{e.fields.email.req === 'optional' ? ' (optional)' : ''}</label><input className="ex-input" type="email" placeholder="you@email.com" value={d.email} onChange={(ev) => set({ email: ev.target.value })} /></div>}
              {e.fields.phone.on && <div className="ex-field-in"><label>Phone{e.fields.phone.req === 'optional' ? ' (optional)' : ''}</label>
                <div className="ex-phone">
                  <button type="button" className="ex-dial" onClick={() => setDialOpen(true)}><span className="ex-dial-f">{dial.f}</span><span className="ex-dial-d">{dial.d}</span><span className="ex-dial-cv">▾</span></button>
                  <input className="ex-input ex-phone-in" type="tel" inputMode="tel" pattern="[0-9 ]*" placeholder="7700 900000" value={d.phone} onChange={(ev) => set({ phone: ev.target.value.replace(/[^0-9 ]/g, '') })} />
                </div>
              </div>}
              {e.fields.company.on && <div className="ex-field-in"><label>Company{e.fields.company.req === 'optional' ? ' (optional)' : ''}</label><input className="ex-input" placeholder="Where you work" value={d.company} onChange={(ev) => set({ company: ev.target.value })} /></div>}
              {e.fields.jobTitle.on && <div className="ex-field-in"><label>Job title{e.fields.jobTitle.req === 'optional' ? ' (optional)' : ''}</label><input className="ex-input" placeholder="What you do" value={d.jobTitle} onChange={(ev) => set({ jobTitle: ev.target.value })} /></div>}
              {e.fields.linkedin.on && <div className="ex-field-in"><label>LinkedIn{e.fields.linkedin.req === 'optional' ? ' (optional)' : ''}</label><input className="ex-input" placeholder="linkedin.com/in/…" value={d.linkedin} onChange={(ev) => set({ linkedin: ev.target.value })} /></div>}
              {e.fields.question.on && <div className="ex-field-in"><label>{e.fields.question.label || 'Your answer'}</label><textarea className="ex-input" rows={2} value={d.answer} onChange={(ev) => set({ answer: ev.target.value })} /></div>}
              {(e.custom || []).filter((cf) => cf.label).map((cf) => (
                <div className="ex-field-in" key={cf.id}><label>{cf.label}{cf.req === 'optional' ? ' (optional)' : ''}</label><input className="ex-input" value={(d.custom || {})[cf.id] || ''} onChange={(ev) => set({ custom: Object.assign({}, d.custom, { [cf.id]: ev.target.value }) })} /></div>
              ))}
              {e.askLocation && (
                <button className={'ex-loc' + (loc ? ' on' : '')} onClick={toggleLoc}>
                  <span className="ex-fic">{MI.pin ? MI.pin({ width: 17, height: 17 }) : '📍'}</span>
                  <span className="ex-tr-meta"><b>Share where we met</b><span>Helps {first} remember the moment</span></span>
                  <span className={'switch' + (loc ? ' on' : '')} />
                </button>
              )}
              <button className={'ex-submit' + (reqOk() ? '' : ' off')} onClick={submit}>{busy ? 'Sending…' : (e.cta || 'Send my details')} {MI.arrow ? MI.arrow({ width: 17, height: 17 }) : '→'}</button>
              <div className="ex-privacy">
                <img className="ex-priv-dark" src="assets/logo-white.png" alt="Tappt" />
                <img className="ex-priv-light" src="assets/logo-black.png" alt="Tappt" />
                <span>Tappt never sells or shares your data. Your details go only to {first}.</span>
              </div>
              <button className="ex-notnow" onClick={onClose}>Not now</button>
            </div>
            {dialOpen && <DialPicker onPick={(c) => { setDial(c); setDialOpen(false); }} onClose={() => setDialOpen(false)} />}
          </React.Fragment>
        )}
      </div>
    </div>
  );
}
window.ExchangeForm = ExchangeForm;

/* ---------- LEAD CRM DETAIL ---------- */
function LeadDetailSheet({ lead, stages, onClose, onUpdate, onDelete, onConnection, mode, inLeads, onMoveToLeads }) {
  const isConn = mode === 'connection';
  const [d, setD] = exUse(lead);
  const [stageOpen, setStageOpen] = exUse(false);
  const [mapOpen, setMapOpen] = exUse(false);
  const [contactAct, setContactAct] = exUse(null);   // { type:'email'|'phone', value }
  const set = (p) => { const next = Object.assign({}, d, p); setD(next); onUpdate(next); };
  const STAGES = (stages && stages.length) ? stages : (window.EX_STAGES || []);
  const st = STAGES.find((s) => s.id === d.stage) || STAGES[0] || { label: 'New', color: '#2ED573' };
  const when = (ts) => { const x = new Date(ts); return x.toLocaleDateString(undefined, { day: 'numeric', month: 'short' }) + ' · ' + x.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' }); };
  return (
    <div className="sheet-bg" onClick={(ev) => { if (ev.target === ev.currentTarget) onClose(); }}>
      <div className="sheet lead-sheet">
        <div className="sheet-grab" />
        <div className="sheet-head">
          <button className="glass-pill" style={{ background: 'var(--bg-3)', color: 'var(--fg)', border: '1px solid var(--line)' }} onClick={onClose}>{XI.back ? XI.back({ width: 15, height: 15 }) : '‹'}</button>
          <h3>{isConn ? 'Connection' : 'Lead'}</h3>
          <button className="glass-pill" style={{ background: 'var(--bg-3)', color: '#ff5a5a', border: '1px solid var(--line)' }} onClick={() => { onDelete(d.id); onClose(); }}>{XI.trash ? XI.trash({ width: 15, height: 15 }) : '🗑'}</button>
        </div>
        <div className="sheet-scroll">
          {/* identity */}
          <div className="ld-head">
            <span className="ld-av">{d.photo ? <img src={d.photo} alt="" /> : (d.name || '?').charAt(0).toUpperCase()}</span>
            <div className="ld-id">
              <div className="ld-name">{d.name || 'Lead'}</div>
              <div className="ld-sub">{[d.jobTitle, d.company].filter(Boolean).join(' · ') || d.email}</div>
            </div>
          </div>

          {/* stage / met-at / potential */}
          <div className="ld-stats">
            {!isConn && <div className="ld-stat ld-stage-wrap">
              <div className="ld-stat-l">Stage</div>
              <button className="ld-stage" onClick={() => setStageOpen((v) => !v)}><span className="ld-dot" style={{ background: st.color }} />{st.label}{XI.chevron ? XI.chevron({ width: 13, height: 13 }) : '▾'}</button>
              {stageOpen && (
                <React.Fragment>
                  <div className="ld-stage-veil" onClick={() => setStageOpen(false)} />
                  <div className="ld-stage-menu">
                    {STAGES.map((s) => <button key={s.id} className="ld-stage-opt" onClick={() => { set({ stage: s.id }); setStageOpen(false); }}><span className="ld-dot" style={{ background: s.color }} />{s.label}</button>)}
                  </div>
                </React.Fragment>
              )}
            </div>}
            <div className="ld-stat"><div className="ld-stat-l">Met at</div><input className="ld-stat-in" placeholder="Add place" value={d.metAt || ''} onChange={(ev) => set({ metAt: ev.target.value })} /></div>
            <div className="ld-stat"><div className="ld-stat-l">Potential</div><div className="ld-pot"><span>£</span><input className="ld-stat-in" placeholder="0" inputMode="numeric" value={d.potential || ''} onChange={(ev) => set({ potential: ev.target.value.replace(/[^0-9]/g, '') })} /></div></div>
          </div>

          {/* contact rows */}
          <div className="ld-rows">
            {d.email && <button className="ld-row ld-row-btn" onClick={() => setContactAct({ type: 'email', value: d.email })}>{XI.mail ? XI.mail({ width: 16, height: 16 }) : '✉'}<span>{d.email}</span><span className="ld-row-chev">{XI.arrow ? XI.arrow({ width: 15, height: 15 }) : '›'}</span></button>}
            {d.phone && <button className="ld-row ld-row-btn" onClick={() => setContactAct({ type: 'phone', value: d.phone })}>{XI.phone ? XI.phone({ width: 16, height: 16 }) : '📞'}<span>{d.phone}</span><span className="ld-row-chev">{XI.arrow ? XI.arrow({ width: 15, height: 15 }) : '›'}</span></button>}
            {d.linkedin && <a className="ld-row" href={d.linkedin.indexOf('http') === 0 ? d.linkedin : 'https://' + d.linkedin} target="_blank" rel="noreferrer">{XI.linkedin ? XI.linkedin({ width: 16, height: 16 }) : 'in'}<span>{d.linkedin}</span></a>}
            {d.location && <div className="ld-row">{XI.pin ? XI.pin({ width: 16, height: 16 }) : '📍'}<span>{d.location.place || 'Shared location'}</span></div>}
            {d.location && d.location.lat != null && <button className="ld-map-btn" onClick={() => setMapOpen(true)}>{XI.pin ? XI.pin({ width: 16, height: 16 }) : '📍'} View on map</button>}
            {d.answer && <div className="ld-row ld-answer">{XI.help ? XI.help({ width: 16, height: 16 }) : '?'}<span>{d.answer}</span></div>}
            {(d.custom || []).map((cf, i) => <div className="ld-row" key={i}>{XI.help ? XI.help({ width: 16, height: 16 }) : '·'}<span><b style={{ color: 'var(--fg-3)', fontWeight: 700 }}>{cf.label}: </b>{cf.value}</span></div>)}
          </div>

          {/* next action */}
          <div className="ld-block">
            <div className="ld-block-h">Next action</div>
            {d.nextAction ? (
              <div className="ld-action">
                <button className={'ld-action-check' + (d.nextAction.done ? ' done' : '')} onClick={() => set({ nextAction: Object.assign({}, d.nextAction, { done: !d.nextAction.done }) })}>{d.nextAction.done ? (XI.check ? XI.check({ width: 14, height: 14 }) : '✓') : ''}</button>
                <span className={'ld-action-txt' + (d.nextAction.done ? ' done' : '')}>{d.nextAction.text}</span>
                <button className="ld-action-x" onClick={() => set({ nextAction: null })}>{XI.close ? XI.close({ width: 13, height: 13 }) : '✕'}</button>
              </div>
            ) : (
              <div className="ld-action-add">
                <input className="ld-stat-in" placeholder={'What\u2019s next with ' + ((d.name || '').split(' ')[0] || 'them') + '?'} onKeyDown={(ev) => { if (ev.key === 'Enter' && ev.target.value.trim()) { set({ nextAction: { text: ev.target.value.trim(), done: false } }); ev.target.value = ''; } }} />
              </div>
            )}
          </div>

          {/* notes */}
          <div className="ld-block">
            <div className="ld-block-h">Notes</div>
            <textarea className="ld-notes" rows={4} placeholder="Add notes from your conversation…" value={d.notes || ''} onChange={(ev) => set({ notes: ev.target.value })} />
          </div>

          <div className="ld-meta-foot">Captured {when(d.ts)} · {d.source || 'Exchange'}</div>
          {isConn
            ? (inLeads
                ? <div className="cd-inlead">{XI.check ? XI.check({ width: 16, height: 16 }) : '✓'} Already in your Leads</div>
                : <button className="ld-save-conn" onClick={() => onMoveToLeads && onMoveToLeads(d)}>{XI.arrow ? XI.arrow({ width: 16, height: 16 }) : '→'} Move to Leads</button>)
            : (onConnection && <button className="ld-save-conn" onClick={() => onConnection(d)}>{XI.plus ? XI.plus({ width: 16, height: 16 }) : '+'} Save to Connections</button>)}
          <div style={{ height: 16 }} />
        </div>
      </div>
      {mapOpen && <LeadMapOverlay lead={d} onClose={() => setMapOpen(false)} />}
      {contactAct && (() => {
        const v = contactAct.value;
        const digits = (v || '').replace(/[^\d+]/g, '');
        const opts = contactAct.type === 'email'
          ? [
              { t: 'Send email', s: v, ic: 'mail', href: 'mailto:' + v },
              { t: 'Open in Gmail', s: 'Compose in Gmail', ic: 'mail', href: 'https://mail.google.com/mail/?view=cm&to=' + encodeURIComponent(v) },
              { t: 'Copy email', s: '', ic: 'copy', copy: v },
            ]
          : [
              { t: 'Call', s: v, ic: 'phone', href: 'tel:' + digits },
              { t: 'Message', s: 'SMS / iMessage', ic: 'message', href: 'sms:' + digits },
              { t: 'WhatsApp', s: 'Open chat', ic: 'whatsapp', href: 'https://wa.me/' + digits.replace(/^\+/, '') },
              { t: 'FaceTime', s: 'Video call', ic: 'video', href: 'facetime:' + digits },
              { t: 'Copy number', s: '', ic: 'copy', copy: v },
            ];
        return (
          <div className="ld-act-bg" onClick={(ev) => { if (ev.target === ev.currentTarget) setContactAct(null); }}>
            <div className="ld-act-card">
              <div className="ld-act-h">{contactAct.type === 'email' ? 'Email' : 'Phone'}<span>{v}</span></div>
              {opts.map((o, i) => (
                <button key={i} className="ld-act-row" onClick={() => {
                  if (o.copy) { try { navigator.clipboard.writeText(o.copy); } catch (e2) {} }
                  else { try { window.open(o.href, '_blank'); } catch (e2) { window.location.href = o.href; } }
                  setContactAct(null);
                }}>
                  <span className="ld-act-ic">{XI[o.ic] ? XI[o.ic]({ width: 19, height: 19 }) : '·'}</span>
                  <span className="ld-act-meta"><span className="ld-act-t">{o.t}</span>{o.s && <span className="ld-act-s">{o.s}</span>}</span>
                </button>
              ))}
              <button className="ld-act-cancel" onClick={() => setContactAct(null)}>Cancel</button>
            </div>
          </div>
        );
      })()}
    </div>
  );
}
window.LeadDetailSheet = LeadDetailSheet;

/* ---------- LEAD MAP OVERLAY (pan to their dropped pin) ---------- */
function LeadMapOverlay({ lead, onClose }) {
  const mref = exRef(null);
  React.useEffect(() => {
    if (!window.maplibregl || !mref.current || !lead.location) return;
    const dark = document.documentElement.dataset.theme !== 'light';
    const ll = [lead.location.lng, lead.location.lat];
    const map = new window.maplibregl.Map({
      container: mref.current,
      style: 'https://basemaps.cartocdn.com/gl/' + (dark ? 'dark-matter-gl-style' : 'positron-gl-style') + '/style.json',
      center: ll, zoom: 5, attributionControl: false, interactive: true, dragRotate: false, pitchWithRotate: false,
      pixelRatio: Math.min(window.devicePixelRatio || 1, 2),
    });
    map.on('load', () => {
      const el = document.createElement('div');
      el.className = 'lead-marker';
      const av = lead.photo ? '<img src="' + lead.photo + '" alt="" />' : '<span>' + ((lead.name || '?').charAt(0).toUpperCase()) + '</span>';
      el.innerHTML = '<span class="lmk-pin">' + av + '</span><span class="lmk-stem"></span>';
      const meta = [lead.jobTitle, lead.company].filter(Boolean).join(' · ');
      const html = '<div class="leadpop"><b>' + (lead.name || 'Lead') + '</b>' + (meta ? '<span>' + meta + '</span>' : '') + (lead.location.place ? '<span class="leadpop-loc">📍 ' + lead.location.place + '</span>' : '') + '</div>';
      const popup = new window.maplibregl.Popup({ offset: 30, closeButton: true, maxWidth: '240px', className: 'conn-pop' }).setHTML(html);
      new window.maplibregl.Marker({ element: el }).setLngLat(ll).setPopup(popup).addTo(map);
      setTimeout(() => map.flyTo({ center: ll, zoom: 12, duration: 1400, essential: true }), 350);
    });
    return () => map.remove();
  }, []);
  return (
    <div className="leadmap-overlay">
      <div ref={mref} className="leadmap-canvas" />
      <button className="leadmap-x" onClick={onClose}>{MI.close ? MI.close({ width: 18, height: 18 }) : '✕'}</button>
      <div className="leadmap-cap">{lead.location && lead.location.place ? lead.location.place : 'Shared location'}</div>
    </div>
  );
}
window.LeadMapOverlay = LeadMapOverlay;
