/* AIWine CRM — spreadsheet importer UI (Drop → Map → Preview → Commit) */

function ImportFlow({ country, onClose, onDone }) {
  const store = window.UI.useStore();
  const { Field, Ic, toast } = window.UI;
  const IMP = window.CRMImport;

  const [step, setStep] = React.useState('drop');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [file, setFile] = React.useState(null);
  const [parsed, setParsed] = React.useState(null);      // { headers, rows }
  const [entity, setEntity] = React.useState('wines');
  const [mapping, setMapping] = React.useState({});       // { colIndex: fieldKey|null }
  const [wMode, setWMode] = React.useState('single');     // 'single' | 'column'
  const [wineryName, setWineryName] = React.useState('');
  const [preview, setPreview] = React.useState(null);
  const [result, setResult] = React.useState(null);
  const [undone, setUndone] = React.useState(false);
  const fileInputRef = React.useRef(null);

  const wineries = store.t('wineries').filter((w) => window.UI.inCountry(w, country));
  const wineryId = React.useMemo(() => {
    const hit = store.t('wineries').find((w) => w.name.toLowerCase() === wineryName.trim().toLowerCase());
    return hit ? hit.id : null;
  }, [wineryName]);

  const remap = (hdrs, ent) => setMapping(IMP.autoMap(hdrs, ent));

  async function onFile(f) {
    if (!f) return;
    setErr(''); setBusy(true); setFile(f);
    try {
      const p = await IMP.parseFile(f);
      const ent = IMP.detectEntity(p.headers);
      setParsed(p); setEntity(ent); remap(p.headers, ent);
      const hasWineryCol = Object.values(IMP.autoMap(p.headers, ent)).includes('winery');
      setWMode(ent === 'wineries' ? 'single' : (hasWineryCol ? 'column' : 'single'));
      setStep('map');
    } catch (e) { setErr(e.message); }
    setBusy(false);
  }

  // Catch file drops anywhere over the importer. Without this, a file dropped
  // beside the dashed zone hits the browser default and downloads/opens instead.
  const onFileRef = React.useRef(onFile); onFileRef.current = onFile;
  const stepRef = React.useRef(step); stepRef.current = step;
  React.useEffect(() => {
    const over = (e) => { e.preventDefault(); };
    const drop = (e) => {
      e.preventDefault();
      const f = e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files[0];
      if (f && stepRef.current === 'drop') onFileRef.current(f);
    };
    window.addEventListener('dragover', over);
    window.addEventListener('drop', drop);
    return () => { window.removeEventListener('dragover', over); window.removeEventListener('drop', drop); };
  }, []);

  function changeEntity(ent) { setEntity(ent); remap(parsed.headers, ent); const hasW = Object.values(IMP.autoMap(parsed.headers, ent)).includes('winery'); setWMode(ent === 'wineries' ? 'single' : (hasW ? 'column' : 'single')); }

  function toPreview() {
    setErr('');
    if (entity !== 'wineries' && wMode === 'single' && !wineryId) { setErr('Choose which winery these rows belong to.'); return; }
    const pv = IMP.buildPreview({ headers: parsed.headers, rows: parsed.rows, entity, mapping, store, country, singleWineryId: entity !== 'wineries' && wMode === 'single' ? wineryId : null });
    setPreview(pv); setStep('preview');
  }

  async function doImport() {
    setBusy(true); setErr('');
    try {
      const res = await IMP.commit({ entity, items: preview.items, store, country, filename: file.name });
      setResult(res); setStep('done');
      if (onDone) onDone();
    } catch (e) { setErr(e.message); }
    setBusy(false);
  }

  async function undo() {
    if (!result || !result.insertedIds || !result.insertedIds.length) return;
    if (!confirm('Remove the ' + result.insertedIds.length + ' record' + (result.insertedIds.length === 1 ? '' : 's') + ' this import added? This cannot be undone.')) return;
    setBusy(true);
    try {
      const removed = await IMP.undoImport(store, result.insertedIds);
      setUndone(true);
      if (onDone) onDone();
      toast('Removed ' + removed + ' imported record' + (removed === 1 ? '' : 's'));
    } catch (e) { setErr(e.message); }
    setBusy(false);
  }
  const mappedKeys = Object.values(mapping).filter(Boolean);
  const missingReq = fields.filter((f) => f.required && !mappedKeys.includes(f.key)).map((f) => f.label);

  /* ---------- foot buttons per step ---------- */
  let foot = null;
  if (step === 'map') foot = (
    <React.Fragment>
      <button className="btn btn-ghost" onClick={() => setStep('drop')}>Back</button>
      <button className="btn btn-primary" onClick={toPreview} disabled={missingReq.length > 0}>{missingReq.length ? 'Map ' + missingReq.join(', ') : 'Preview rows'}</button>
    </React.Fragment>
  );
  else if (step === 'preview') foot = (
    <React.Fragment>
      <button className="btn btn-ghost" onClick={() => setStep('map')}>Back to mapping</button>
      <button className="btn btn-primary" onClick={doImport} disabled={busy || (preview.counts.new + preview.counts.update === 0)}>
        {busy ? 'Importing…' : 'Import ' + (preview.counts.new + preview.counts.update) + ' row' + (preview.counts.new + preview.counts.update === 1 ? '' : 's')}
      </button>
    </React.Fragment>
  );
  else if (step === 'done') foot = <button className="btn btn-primary" onClick={onClose}>Done</button>;

  const sample = parsed && parsed.rows[0] ? parsed.rows[0] : [];

  return (
    <window.UI.Modal wide title="Import a spreadsheet" sub={'Smart column mapping · ' + (file ? file.name : 'CSV or Excel')} onClose={onClose} foot={foot}>
      {/* progress dots */}
      <div style={{ display: 'flex', gap: 8, marginBottom: 18 }}>
        {['drop', 'map', 'preview', 'done'].map((s, i) => {
          const order = ['drop', 'map', 'preview', 'done'];
          const on = order.indexOf(step) >= i;
          return <div key={s} style={{ flex: 1, height: 3, borderRadius: 2, background: on ? 'var(--claret)' : 'var(--line)' }}></div>;
        })}
      </div>

      {err && <div className="card card-pad" style={{ borderColor: 'var(--claret)', color: 'var(--claret)', fontWeight: 600, fontSize: 13, marginBottom: 14 }}>{err}</div>}

      {/* ---------- STEP: DROP ---------- */}
      {step === 'drop' && (
        <div onDragOver={(e) => { e.preventDefault(); }} onDrop={(e) => { e.preventDefault(); e.stopPropagation(); if (e.dataTransfer.files && e.dataTransfer.files[0]) onFile(e.dataTransfer.files[0]); }}>
          <input ref={fileInputRef} type="file" accept=".csv,.xls,.xlsx,text/csv" style={{ display: 'none' }} onChange={(e) => onFile(e.target.files[0])} />
          <div className="dropzone-lg">
            <Ic name="upload" w={26} c="var(--brass)" />
            <div className="serif" style={{ fontSize: 22, fontWeight: 600, margin: '10px 0 4px' }}>{busy ? 'Reading your file…' : 'Add your spreadsheet'}</div>
            <div style={{ fontSize: 13, color: 'var(--muted)', marginBottom: 18 }}>CSV or Excel (.csv, .xlsx) — we match the columns for you</div>
            <button className="btn btn-primary" type="button" disabled={busy} onClick={() => { if (fileInputRef.current) fileInputRef.current.click(); }} style={{ fontSize: 14, padding: '12px 24px' }}>
              <Ic name="upload" w={15} /> Choose a file…
            </button>
            <div style={{ fontSize: 12, color: 'var(--faint)', marginTop: 14 }}>… or drag a file anywhere onto this panel</div>
          </div>
          <div className="card card-pad" style={{ marginTop: 16, background: 'var(--card-2)' }}>
            <div className="label" style={{ marginBottom: 10 }}>Not sure of the format? Start from a template</div>
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
              {Object.keys(IMP.TEMPLATES).map((k) => (
                <button key={k} className="btn btn-ghost btn-sm" onClick={() => store.download('AIWine_' + k + '_template.csv', IMP.TEMPLATES[k])}>
                  <Ic name="download" w={14} /> {window.CRMImport.ENTITY_LABEL[k]} template
                </button>
              ))}
            </div>
          </div>
          <p style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 14, lineHeight: 1.6 }}>
            Columns can be named anything — the importer recognises common headings (e.g. <i>RRP</i>, <i>varietal</i>, <i>year</i>) and lets you correct any it gets wrong before anything is saved.
          </p>
        </div>
      )}

      {/* ---------- STEP: MAP ---------- */}
      {step === 'map' && parsed && (
        <div>
          <div style={{ display: 'flex', gap: 18, flexWrap: 'wrap', alignItems: 'flex-end', marginBottom: 16 }}>
            <Field label="This sheet describes">
              <window.UI.Seg options={Object.keys(IMP.ENTITY_LABEL).map((k) => ({ value: k, label: IMP.ENTITY_LABEL[k] }))} value={entity} onChange={changeEntity} />
            </Field>
            <div style={{ flex: 1 }}></div>
            <div className="label">{parsed.rows.length} rows · {parsed.headers.length} columns detected</div>
          </div>

          {entity !== 'wineries' && (
            <div className="card card-pad" style={{ marginBottom: 16, background: 'var(--card-2)' }}>
              <div className="label" style={{ marginBottom: 10 }}>Which winery do these {entity} belong to?</div>
              <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', alignItems: 'center' }}>
                <window.UI.Seg
                  options={[{ value: 'single', label: 'One winery for the whole file' }].concat(mappedKeys.includes('winery') ? [{ value: 'column', label: 'Match each row by its Winery column' }] : [])}
                  value={wMode} onChange={setWMode} />
                {wMode === 'single' && (
                  <div style={{ flex: 1, minWidth: 220 }}>
                    <input className="input" list="winery-list" placeholder="Type to find a winery…" value={wineryName} onChange={(e) => setWineryName(e.target.value)} />
                    <datalist id="winery-list">{wineries.slice(0, 800).map((w) => <option key={w.id} value={w.name} />)}</datalist>
                    {wineryName && !wineryId && <div style={{ fontSize: 11.5, color: 'var(--claret)', marginTop: 4 }}>No exact match — pick from the list</div>}
                    {wineryId && <div style={{ fontSize: 11.5, color: 'var(--green)', marginTop: 4 }}>✓ matched</div>}
                  </div>
                )}
              </div>
            </div>
          )}

          <div className="tbl-wrap">
            <table className="tbl">
              <thead><tr><th>Column in your file</th><th>First value</th><th>→ Maps to</th></tr></thead>
              <tbody>
                {parsed.headers.map((h, ci) => (
                  <tr key={ci}>
                    <td className="main-cell" style={{ fontWeight: 600 }}>{h || <span style={{ color: 'var(--muted)' }}>(blank header)</span>}</td>
                    <td className="mono" style={{ fontSize: 11.5, color: 'var(--muted)', maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{sample[ci] || '—'}</td>
                    <td>
                      <select className="select" style={{ width: 220 }} value={mapping[ci] || ''} onChange={(e) => setMapping({ ...mapping, [ci]: e.target.value || null })}>
                        <option value="">— ignore this column —</option>
                        {fields.map((f) => {
                          const takenElse = mappedKeys.includes(f.key) && mapping[ci] !== f.key;
                          return <option key={f.key} value={f.key} disabled={takenElse}>{f.label}{f.required ? ' *' : ''}{takenElse ? ' (mapped)' : ''}</option>;
                        })}
                      </select>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          {missingReq.length > 0 && <div style={{ fontSize: 12.5, color: 'var(--claret)', marginTop: 10, fontWeight: 600 }}>Still need a column for: {missingReq.join(', ')}</div>}
        </div>
      )}

      {/* ---------- STEP: PREVIEW ---------- */}
      {step === 'preview' && preview && (
        <div>
          <div style={{ display: 'flex', gap: 10, marginBottom: 16, flexWrap: 'wrap' }}>
            <PvStat n={preview.counts.new} label="new" color="var(--green)" />
            <PvStat n={preview.counts.update} label="update existing" color="var(--brass)" />
            <PvStat n={preview.counts.error} label="skipped" color="var(--claret)" />
          </div>
          <div className="tbl-wrap" style={{ maxHeight: 380, overflow: 'auto' }}>
            <table className="tbl">
              <thead><tr><th>#</th><th>{entity === 'wineries' ? 'Winery' : entity === 'wines' ? 'Wine' : 'Contact'}</th><th>Details</th>{entity !== 'wineries' && <th>Winery</th>}<th>Action</th></tr></thead>
              <tbody>
                {preview.items.slice(0, 100).map((it) => (
                  <tr key={it.idx} style={it.action === 'error' ? { opacity: 0.6 } : null}>
                    <td className="num" style={{ color: 'var(--muted)' }}>{it.idx + 2}</td>
                    <td className="main-cell" style={{ fontWeight: 600 }}>{it.data.name || <span style={{ color: 'var(--claret)' }}>—</span>}</td>
                    <td style={{ fontSize: 12, color: 'var(--muted)' }}>
                      {entity === 'wines' && [it.data.variety, it.data.vintage, it.data.price != null ? '$' + it.data.price : null, it.data.stock].filter(Boolean).join(' · ')}
                      {entity === 'wineries' && [it.data.region, it.data.email].filter(Boolean).join(' · ')}
                      {entity === 'contacts' && [it.data.role, it.data.email].filter(Boolean).join(' · ')}
                      {it.warns.length > 0 && <div style={{ color: 'var(--brass)', fontSize: 11 }}>⚠ {it.warns.join('; ')}</div>}
                    </td>
                    {entity !== 'wineries' && <td style={{ fontSize: 12 }}>{it.wineryName || '—'}</td>}
                    <td>
                      {it.action === 'new' && <span className="badge badge-green">New</span>}
                      {it.action === 'update' && <span className="badge badge-brass">Update</span>}
                      {it.action === 'error' && <span className="badge badge-claret" title={it.reason}>Skip</span>}
                      {it.action === 'error' && <div style={{ fontSize: 11, color: 'var(--claret)' }}>{it.reason}</div>}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          {preview.items.length > 100 && <div className="label" style={{ marginTop: 10 }}>Showing first 100 of {preview.items.length} rows — all will be imported</div>}
          {preview.counts.error > 0 && <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 10 }}>Skipped rows aren’t imported and won’t change anything — fix them in your file and re-import if needed.</div>}
        </div>
      )}

      {/* ---------- STEP: DONE ---------- */}
      {step === 'done' && result && !undone && (
        <div style={{ textAlign: 'center', padding: '20px 0' }}>
          <div style={{ width: 56, height: 56, borderRadius: '50%', background: 'color-mix(in oklab, var(--green), white 84%)', color: 'var(--green)', display: 'grid', placeItems: 'center', margin: '0 auto 16px', fontSize: 26 }}>✓</div>
          <h3 className="serif" style={{ fontSize: 26, fontWeight: 500, margin: 0 }}>Imported.</h3>
          <p style={{ color: 'var(--ink-soft)', marginTop: 8 }}>
            <b>{result.inserted}</b> added · <b>{result.updated}</b> updated{result.failed ? ' · ' + result.failed + ' failed' : ''}.
          </p>
          {store.mode === 'demo' && <div className="card card-pad" style={{ marginTop: 16, fontSize: 12.5, color: 'var(--muted)', background: 'var(--card-2)', textAlign: 'left' }}>Saved to this browser. When Supabase is connected these writes go straight to the live database.</div>}
          {result.errors && result.errors.length > 0 && <div className="card card-pad" style={{ marginTop: 12, fontSize: 12, color: 'var(--claret)', textAlign: 'left' }}>{result.errors.slice(0, 6).map((e, i) => <div key={i}>{e}</div>)}</div>}
          {result.insertedIds && result.insertedIds.length > 0 && (
            <div style={{ marginTop: 18, paddingTop: 16, borderTop: '1px solid var(--line-soft)' }}>
              <button className="btn btn-danger btn-sm" disabled={busy} onClick={undo}>{busy ? 'Removing…' : 'Undo this import — remove the ' + result.insertedIds.length + ' new record' + (result.insertedIds.length === 1 ? '' : 's')}</button>
              <div style={{ fontSize: 11.5, color: 'var(--faint)', marginTop: 8 }}>Removes only the rows this import added — updates to existing records aren’t reverted.</div>
            </div>
          )}
        </div>
      )}
      {step === 'done' && undone && (
        <div style={{ textAlign: 'center', padding: '20px 0' }}>
          <div style={{ width: 56, height: 56, borderRadius: '50%', background: 'var(--bone-alt)', color: 'var(--muted)', display: 'grid', placeItems: 'center', margin: '0 auto 16px', fontSize: 26 }}>↩</div>
          <h3 className="serif" style={{ fontSize: 26, fontWeight: 500, margin: 0 }}>Import undone.</h3>
          <p style={{ color: 'var(--ink-soft)', marginTop: 8 }}>The records this import added have been removed.{result.updated ? ' (Any updates to existing records were left as they are.)' : ''}</p>
        </div>
      )}
    </window.UI.Modal>
  );
}

function PvStat({ n, label, color }) {
  return (
    <div className="card" style={{ padding: '12px 18px', display: 'flex', alignItems: 'baseline', gap: 8, borderLeft: '3px solid ' + color }}>
      <span className="serif" style={{ fontSize: 26, fontWeight: 500, color }}>{n}</span>
      <span className="label">{label}</span>
    </div>
  );
}

window.ImportFlow = ImportFlow;
