// ============================================================================
// BULK-REGISTRATION EXPORTS — SCREEN
// Target picker → Scope → Validate → Preview → Download.
// ============================================================================
const { useState, useMemo, useEffect } = React;

const KIND_LABELS = {
  works: 'works (compositions)',
  recordings: 'recordings (ISRCs)',
  releases: 'releases (UPCs)',
};

function StatBlock({ label, value, tone }) {
  const fg = tone === 'err' ? 'var(--err, #b34735)'
           : tone === 'warn' ? 'var(--warn, #b8860b)'
           : tone === 'ok' ? 'var(--ok, #2a6b3a)'
           : 'var(--ink)';
  return (
    <div style={{ borderLeft:'2px solid var(--rule)', padding:'4px 14px', minWidth:88 }}>
      <div style={{ fontFamily:'ui-monospace,monospace', fontSize:10, letterSpacing:'.08em', textTransform:'uppercase', opacity:.55 }}>{label}</div>
      <div style={{ fontFamily:'ui-monospace,monospace', fontSize:22, color:fg, marginTop:2 }}>{value}</div>
    </div>
  );
}

function TargetCard({ target, selected, onPick, recommended }) {
  const fmtBadge = {
    tsv: { bg:'#f5e6c8', fg:'#7a5520' },
    csv: { bg:'#dfead8', fg:'#3a5524' },
    xml: { bg:'#dde6f0', fg:'#2a4564' },
    fixed: { bg:'#ecdde9', fg:'#5a2a52' },
  }[target.format] || { bg:'#eee', fg:'#444' };

  return (
    <button onClick={() => onPick(target.id)}
      style={{
        textAlign:'left', cursor:'pointer',
        background: selected ? 'var(--ink)' : 'var(--paper)',
        color: selected ? 'var(--paper)' : 'var(--ink)',
        border:'1px solid', borderColor: selected ? 'var(--ink)' : 'var(--rule)',
        padding:'14px 16px', display:'flex', flexDirection:'column', gap:8,
        fontFamily:'inherit', minHeight:120, position:'relative',
      }}>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', gap:8 }}>
        <div style={{ fontFamily:'ui-monospace,monospace', fontSize:11, letterSpacing:'.06em', opacity: selected ? .8 : .55, textTransform:'uppercase' }}>
          {target.short} · {target.kind}
        </div>
        <span style={{ background: fmtBadge.bg, color: fmtBadge.fg, padding:'2px 6px', fontSize:10, fontFamily:'ui-monospace,monospace', textTransform:'uppercase', letterSpacing:'.06em' }}>
          {target.format}
        </span>
      </div>
      <div style={{ fontSize:15, fontWeight:600, lineHeight:1.25 }}>{target.name}</div>
      <div style={{ fontSize:12, lineHeight:1.4, opacity:.78 }}>{target.description}</div>
      {recommended && !selected && (
        <div style={{ position:'absolute', top:6, right:6, background:'var(--ink)', color:'var(--paper)', fontSize:9, padding:'2px 5px', fontFamily:'ui-monospace,monospace', letterSpacing:'.06em' }}>NEW SINCE LAST</div>
      )}
    </button>
  );
}

function PreviewBox({ content, format }) {
  const trimmed = content.length > 12000
    ? content.slice(0, 12000) + `\n\n… (${(content.length - 12000).toLocaleString()} more bytes)`
    : content;
  return (
    <pre style={{
      background:'#1a1714', color:'#e8e2d8', padding:14,
      fontFamily:'ui-monospace,monospace', fontSize:11, lineHeight:1.55,
      whiteSpace:'pre', overflow:'auto', maxHeight:420, margin:0,
      border:'1px solid #2a2620',
    }}>{trimmed}</pre>
  );
}

function ValidationTable({ report, onSelectRow }) {
  if (!report) return null;
  const problemRows = report.rowReports.filter(r => r.errors.length || r.warnings.length);
  if (!problemRows.length) {
    return (
      <div style={{ padding:'18px 14px', border:'1px dashed var(--rule)', textAlign:'center', fontFamily:'ui-monospace,monospace', fontSize:12, color:'var(--ok, #2a6b3a)' }}>
        ✓ ALL {report.total} ROWS PASS — NO ERRORS, NO WARNINGS
      </div>
    );
  }
  return (
    <div style={{ border:'1px solid var(--rule)', maxHeight:380, overflow:'auto' }}>
      <table style={{ width:'100%', borderCollapse:'collapse', fontSize:12 }}>
        <thead>
          <tr style={{ background:'var(--bg2, #f6f3ee)', borderBottom:'1px solid var(--rule)' }}>
            <th style={{ textAlign:'left', padding:'8px 10px', width:48, fontFamily:'ui-monospace,monospace', fontSize:10, opacity:.65 }}>#</th>
            <th style={{ textAlign:'left', padding:'8px 10px', fontFamily:'ui-monospace,monospace', fontSize:10, opacity:.65 }}>ROW</th>
            <th style={{ textAlign:'left', padding:'8px 10px', fontFamily:'ui-monospace,monospace', fontSize:10, opacity:.65 }}>ISSUES</th>
          </tr>
        </thead>
        <tbody>
          {problemRows.map(r => (
            <tr key={r.index} style={{ borderTop:'1px solid var(--rule)' }}>
              <td style={{ padding:'8px 10px', fontFamily:'ui-monospace,monospace', fontSize:11, opacity:.6 }}>{r.index + 1}</td>
              <td style={{ padding:'8px 10px' }}>{r.label}</td>
              <td style={{ padding:'8px 10px' }}>
                {r.errors.map((e, i) => (
                  <div key={'e'+i} style={{ color:'var(--err, #b34735)', fontSize:11, marginBottom:2 }}>
                    <span style={{ display:'inline-block', minWidth:26, fontFamily:'ui-monospace,monospace', fontSize:9, padding:'1px 4px', background:'var(--err, #b34735)', color:'#fff', marginRight:6 }}>ERR</span>
                    {e}
                  </div>
                ))}
                {r.warnings.map((w, i) => (
                  <div key={'w'+i} style={{ color:'var(--warn, #8b6810)', fontSize:11, marginBottom:2 }}>
                    <span style={{ display:'inline-block', minWidth:26, fontFamily:'ui-monospace,monospace', fontSize:9, padding:'1px 4px', background:'var(--warn, #b8860b)', color:'#fff', marginRight:6 }}>WARN</span>
                    {w}
                  </div>
                ))}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DiffPanel({ diff }) {
  if (!diff) return null;
  if (!diff.lastCount) {
    return (
      <div style={{ padding:'10px 12px', border:'1px dashed var(--rule)', fontSize:12, fontFamily:'ui-monospace,monospace', color:'var(--ink)', opacity:.7 }}>
        no prior export for this target — full catalog will be sent
      </div>
    );
  }
  return (
    <div style={{ display:'flex', gap:14, flexWrap:'wrap', fontFamily:'ui-monospace,monospace', fontSize:12 }}>
      <div><span style={{ color:'var(--ok, #2a6b3a)' }}>+{diff.added.length}</span> added</div>
      <div><span style={{ color:'var(--err, #b34735)' }}>−{diff.removed.length}</span> removed</div>
      <div style={{ opacity:.6 }}>= {diff.same.length} unchanged</div>
      <div style={{ opacity:.5 }}>(prior export: {diff.lastCount})</div>
    </div>
  );
}

function ScreenBulkExport({ go, payload }) {
  const E = window.BulkExport;
  if (!E) return <div style={{ padding:24 }}>Bulk-export engine not loaded.</div>;

  const initialId = payload?.targetId || 'mlc';
  const [targetId, setTargetId] = useState(initialId);
  const [scopeMode, setScopeMode] = useState('all'); // 'all' | 'sample'
  const [sampleN, setSampleN] = useState(50);
  const [step, setStep] = useState(1); // 1 pick · 2 scope · 3 review · 4 done

  const target = E.targetById(targetId);
  const allRows = useMemo(() => E.rowsFor(target.kind), [target.kind, targetId]);
  const rows = useMemo(
    () => scopeMode === 'sample' ? allRows.slice(0, sampleN) : allRows,
    [allRows, scopeMode, sampleN]
  );

  const report = useMemo(() => E.validate(targetId, { rows }), [targetId, rows]);
  const diff = useMemo(() => E.diffVsLast(targetId, { rows }), [targetId, rows]);
  const preview = useMemo(() => {
    try { return E.build(targetId, { rows: rows.slice(0, 25) }); } catch (e) { return '// build error: ' + e.message; }
  }, [targetId, rows]);

  const totalBytes = useMemo(() => {
    try { return E.build(targetId, { rows }).length; } catch { return 0; }
  }, [targetId, rows]);

  const downloadable = report.errCount === 0;
  const [lastDownload, setLastDownload] = useState(null);

  function handleDownload() {
    const res = E.download(targetId, { rows });
    setLastDownload(res);
    setStep(4);
  }

  // Suggest tags — what's new since last export
  const suggestedIds = useMemo(() => {
    const out = {};
    for (const tid of E.targetIds) {
      try {
        const d = E.diffVsLast(tid);
        if (d.added.length > 0) out[tid] = d.added.length;
      } catch {}
    }
    return out;
  }, []);

  return (
    <div style={{ padding:'20px 28px 60px', maxWidth:1280 }}>
      <window.PageHeader
        eyebrow={['REGISTRATIONS', 'BULK EXPORT', `${E.targetIds.length} TARGETS`]}
        title="Bulk-registration exports"
        highlight="Bulk-registration"
        sub="Generate the wire-format files each society and agency wants for catalog registration. Pick a target, scope, validate, preview, download."
      />

      {/* STEP NAV */}
      <div style={{ display:'flex', gap:0, marginTop:18, marginBottom:22, borderBottom:'1px solid var(--rule)' }}>
        {['1 · Target', '2 · Scope & validate', '3 · Preview', '4 · Done'].map((s, i) => {
          const n = i + 1;
          const active = step === n;
          const past = step > n;
          return (
            <div key={n}
              onClick={() => (past || active) && setStep(n)}
              style={{
                padding:'10px 18px', cursor: past ? 'pointer' : 'default',
                fontFamily:'ui-monospace,monospace', fontSize:11, letterSpacing:'.06em', textTransform:'uppercase',
                borderBottom: active ? '2px solid var(--ink)' : '2px solid transparent',
                color: active ? 'var(--ink)' : past ? 'var(--ink)' : 'var(--ink)',
                opacity: active ? 1 : past ? .8 : .4,
              }}>
              {s}
            </div>
          );
        })}
      </div>

      {/* STEP 1 — TARGET */}
      {step === 1 && (
        <div>
          <div style={{ display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:12 }}>
            {E.targetIds.map(id => (
              <TargetCard key={id}
                target={E.targetById(id)}
                selected={targetId === id}
                onPick={(x) => setTargetId(x)}
                recommended={suggestedIds[id] > 0}
              />
            ))}
          </div>

          <div style={{ marginTop:24, display:'flex', justifyContent:'flex-end' }}>
            <window.Btn onClick={() => setStep(2)}>Continue →</window.Btn>
          </div>
        </div>
      )}

      {/* STEP 2 — SCOPE + VALIDATE */}
      {step === 2 && (
        <div>
          <div style={{ marginBottom:18, display:'flex', alignItems:'baseline', justifyContent:'space-between' }}>
            <div>
              <div style={{ fontFamily:'ui-monospace,monospace', fontSize:10, letterSpacing:'.08em', opacity:.55, textTransform:'uppercase' }}>SELECTED TARGET</div>
              <div style={{ fontSize:18, fontWeight:600, marginTop:2 }}>{target.name}</div>
            </div>
            <window.Btn variant="ghost" size="sm" onClick={() => setStep(1)}>← change target</window.Btn>
          </div>

          {/* SCOPE */}
          <div style={{ border:'1px solid var(--rule)', padding:16, marginBottom:18 }}>
            <div style={{ fontFamily:'ui-monospace,monospace', fontSize:11, letterSpacing:'.08em', opacity:.55, textTransform:'uppercase', marginBottom:8 }}>SCOPE</div>
            <div style={{ display:'flex', gap:18, alignItems:'center', flexWrap:'wrap' }}>
              <label style={{ display:'flex', gap:6, alignItems:'center', cursor:'pointer' }}>
                <input type="radio" checked={scopeMode === 'all'} onChange={() => setScopeMode('all')} />
                <span>Entire catalog — all {allRows.length.toLocaleString()} {KIND_LABELS[target.kind]}</span>
              </label>
              <label style={{ display:'flex', gap:6, alignItems:'center', cursor:'pointer' }}>
                <input type="radio" checked={scopeMode === 'sample'} onChange={() => setScopeMode('sample')} />
                <span>Sample first</span>
                <input type="number" min={1} max={Math.max(allRows.length, 1)}
                  value={sampleN} onChange={e => setSampleN(Math.max(1, Math.min(allRows.length, +e.target.value || 1)))}
                  style={{ width:80, fontFamily:'ui-monospace,monospace', fontSize:12, padding:'3px 6px', border:'1px solid var(--rule)' }}
                  disabled={scopeMode !== 'sample'}
                />
                <span style={{ opacity:.6 }}>rows</span>
              </label>
              <div style={{ marginLeft:'auto', fontFamily:'ui-monospace,monospace', fontSize:12, opacity:.7 }}>
                ≈ {(totalBytes / 1024).toFixed(1)} KB output
              </div>
            </div>
            <div style={{ marginTop:14, paddingTop:14, borderTop:'1px solid var(--rule)' }}>
              <div style={{ fontFamily:'ui-monospace,monospace', fontSize:11, letterSpacing:'.08em', opacity:.55, textTransform:'uppercase', marginBottom:6 }}>DIFF VS LAST EXPORT</div>
              <DiffPanel diff={diff} />
            </div>
          </div>

          {/* STATS */}
          <div style={{ display:'flex', flexWrap:'wrap', marginBottom:18, padding:'8px 0', borderTop:'1px solid var(--rule)', borderBottom:'1px solid var(--rule)' }}>
            <StatBlock label="Total rows" value={report.total.toLocaleString()} />
            <StatBlock label="Clean" value={report.cleanRows.toLocaleString()} tone="ok" />
            <StatBlock label="With warnings" value={(report.total - report.cleanRows - report.errorRows).toLocaleString()} tone="warn" />
            <StatBlock label="Blocking errors" value={report.errorRows.toLocaleString()} tone={report.errorRows ? 'err' : 'ok'} />
            <StatBlock label="Total issues" value={(report.errCount + report.warnCount).toLocaleString()} />
          </div>

          {/* VALIDATION TABLE */}
          <div style={{ marginBottom:18 }}>
            <div style={{ fontFamily:'ui-monospace,monospace', fontSize:11, letterSpacing:'.08em', opacity:.55, textTransform:'uppercase', marginBottom:8 }}>PRE-EXPORT VALIDATION</div>
            <ValidationTable report={report} />
          </div>

          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center' }}>
            <div style={{ fontSize:12, opacity:.7 }}>
              {report.errorRows > 0
                ? <span style={{ color:'var(--err, #b34735)' }}>Fix the {report.errorRows} blocking row{report.errorRows === 1 ? '' : 's'} or sample around them before exporting.</span>
                : <span style={{ color:'var(--ok, #2a6b3a)' }}>No blocking errors — ready to preview.</span>}
            </div>
            <window.Btn onClick={() => setStep(3)}>Preview →</window.Btn>
          </div>
        </div>
      )}

      {/* STEP 3 — PREVIEW */}
      {step === 3 && (
        <div>
          <div style={{ marginBottom:14, display:'flex', alignItems:'baseline', justifyContent:'space-between' }}>
            <div>
              <div style={{ fontFamily:'ui-monospace,monospace', fontSize:10, letterSpacing:'.08em', opacity:.55, textTransform:'uppercase' }}>OUTPUT PREVIEW · FIRST 25 ROWS</div>
              <div style={{ fontSize:18, fontWeight:600, marginTop:2 }}>{target.filenameOf()}</div>
              <div style={{ fontSize:12, fontFamily:'ui-monospace,monospace', opacity:.6, marginTop:2 }}>
                {target.format.toUpperCase()} · {rows.length.toLocaleString()} rows · {(totalBytes / 1024).toFixed(1)} KB
              </div>
            </div>
            <window.Btn variant="ghost" size="sm" onClick={() => setStep(2)}>← back</window.Btn>
          </div>

          <PreviewBox content={preview} format={target.format} />

          <div style={{ marginTop:20, display:'flex', justifyContent:'space-between', alignItems:'center', borderTop:'1px solid var(--rule)', paddingTop:18 }}>
            <div style={{ fontSize:12, opacity:.65 }}>
              Downloading commits this export — diff next time will be relative to this run.
            </div>
            <div style={{ display:'flex', gap:10 }}>
              <window.Btn variant="ghost" onClick={() => navigator.clipboard?.writeText(preview)}>Copy preview</window.Btn>
              <window.Btn onClick={handleDownload} disabled={!downloadable}>
                {downloadable ? `Download ${target.format.toUpperCase()}` : `${report.errorRows} blocking errors`}
              </window.Btn>
            </div>
          </div>
        </div>
      )}

      {/* STEP 4 — DONE */}
      {step === 4 && lastDownload && (
        <div style={{ textAlign:'center', padding:'40px 20px' }}>
          <div style={{ fontSize:48, marginBottom:18 }}>✓</div>
          <div style={{ fontSize:24, fontWeight:600, marginBottom:8 }}>Export ready</div>
          <div style={{ fontFamily:'ui-monospace,monospace', fontSize:13, marginBottom:6 }}>{lastDownload.filename}</div>
          <div style={{ fontSize:12, opacity:.6, marginBottom:30 }}>
            {(lastDownload.bytes / 1024).toFixed(1)} KB · {rows.length.toLocaleString()} rows · {target.name}
          </div>
          <div style={{ display:'flex', gap:10, justifyContent:'center' }}>
            <window.Btn variant="ghost" onClick={() => { setStep(1); setLastDownload(null); }}>Export another</window.Btn>
            <window.Btn onClick={() => go('reg')}>Back to Registrations</window.Btn>
          </div>
        </div>
      )}
    </div>
  );
}

window.ScreenBulkExport = ScreenBulkExport;
