// Import Kandidat — upload CV files; AI reads each one (interactively) → review → import.

function ImportView({ state, go, onImport }) {
  const { JOBS } = window.TalentirData;
  const openJobs = JOBS.filter(j => j.status === 'Buka');
  const [step, setStep] = useState(1); // 1 upload · 2 AI reading · 3 preview · 4 done
  const [jobId, setJobId] = useState(state.jobId || openJobs[0]?.id || '');
  const [files, setFiles] = useState([]);        // display rows { name, size }
  const [realFiles, setRealFiles] = useState([]); // actual File objects
  const [parsed, setParsed] = useState([]);
  const [aiProgress, setAiProgress] = useState({ done: 0, total: 0, items: [] });
  const [aiError, setAiError] = useState(null);
  const [parseInfo, setParseInfo] = useState(null);
  const [autoTrigger, setAutoTrigger] = useState(true);

  const job = JOBS.find(j => j.id === jobId);
  const fmtSize = (b) => (b > 1e6 ? (b / 1e6).toFixed(1) + ' MB' : Math.round(b / 1024) + ' KB');
  const onFilesPicked = (list) => {
    setRealFiles(prev => [...prev, ...list]);
    setFiles(prev => [...prev, ...list.map(f => ({ name: f.name, size: fmtSize(f.size) }))]);
  };
  const removeFile = (i) => { setFiles(files.filter((_, j) => j !== i)); setRealFiles(realFiles.filter((_, j) => j !== i)); };

  const toRow = (p, i) => ({
    id: 'imp-' + i, name: p.name, email: p.email || '', phone: p.phone || '',
    location: p.location || '', experience: p.experience || '', current: '', salary: '',
    skills: p.skills || [], score: p.score || 0, matched: p.skills || [],
    source: 'jobportal', include: true, file: p.name, summary: p.summary,
    cvFileId: p.cvFileId || null, cvUrl: p.cvUrl || null,
  });

  // Read each CV one-by-one so the user sees real, per-file progress.
  const runAI = async () => {
    setAiError(null); setParseInfo(null);
    const list = realFiles;
    if (list.length === 0) return;
    setStep(2);
    setAiProgress({ done: 0, total: list.length, items: list.map(f => ({ name: f.name, status: 'wait' })) });
    const results = [];
    let info = null;
    for (let i = 0; i < list.length; i++) {
      setAiProgress(p => ({ ...p, items: p.items.map((it, idx) => idx === i ? { ...it, status: 'reading' } : it) }));
      try {
        const fd = new FormData();
        fd.append('files', list[i]);
        const url = window.TalentirAPI.base + '/api/import/upload' + (jobId ? '?jobId=' + jobId : '');
        const resp = await fetch(url, { method: 'POST', credentials: 'include', body: fd })
          .then(r => { if (!r.ok) throw new Error('upload ' + r.status); return r.json(); });
        const one = (resp.parsed || [])[0];
        if (info === null) info = { usedAI: !!resp.usedAI, provider: resp.provider };
        if (one) results.push(one);
        setAiProgress(p => ({ ...p, done: i + 1, items: p.items.map((it, idx) => idx === i ? { ...it, status: 'done', extracted: one?.name } : it) }));
      } catch (e) {
        console.error('Gagal membaca CV:', e);
        // Bubble the actual error onto the per-file row + a banner so the user
        // knows *why* (network, server crash, unsupported PDF, etc.) instead of
        // just seeing a silent red dot.
        const msg = e?.message || 'Gagal upload / parse CV.';
        setAiProgress(p => ({ ...p, done: i + 1, items: p.items.map((it, idx) => idx === i ? { ...it, status: 'error', error: msg } : it) }));
        setAiError((prev) => prev ? prev : `Sebagian CV gagal dibaca: ${msg}`);
      }
    }
    if (results.length === 0) { setAiError('Tidak ada CV yang berhasil dibaca. Coba file lain (PDF berbasis teks).'); setStep(1); return; }
    setParsed(results.map(toRow));
    setParseInfo(info || { usedAI: false, provider: 'heuristic' });
    setTimeout(() => setStep(3), 700); // brief beat so the user sees everything done
  };

  const finish = () => {
    const selected = parsed.filter(p => p.include);
    if (onImport) onImport(selected, jobId, autoTrigger);
    setStep(4);
  };
  const reset = () => { setStep(1); setFiles([]); setRealFiles([]); setParsed([]); setParseInfo(null); setAiError(null); };

  return (
    <div className="view">
      <div className="view-head">
        <div>
          <div className="title">Import Kandidat</div>
          <div className="subtitle">Unggah CV (PDF/DOC), AI akan membaca, menilai, dan memasukkannya ke pipeline.</div>
        </div>
        <button className="btn ghost sm" onClick={() => go({ view: 'jobs' })}><Icon name="x" size={12}/> Tutup</button>
      </div>

      {/* Stepper */}
      <div style={{ display: 'flex', gap: 10, marginBottom: 22 }}>
        {[[1, 'Unggah CV'], [2, 'AI Membaca'], [3, 'Tinjau'], [4, 'Selesai']].map(([n, lbl], i, arr) => (
          <React.Fragment key={n}>
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 10 }}>
              <div style={{ width: 28, height: 28, borderRadius: 99, background: step >= n ? 'var(--ink)' : 'var(--surface-2)', color: step >= n ? 'var(--bg)' : 'var(--muted)', display: 'grid', placeItems: 'center', fontWeight: 700, fontSize: 12, flexShrink: 0 }}>
                {step > n ? <Icon name="check" size={13} stroke={2.4}/> : n}
              </div>
              <div style={{ fontWeight: 700, fontSize: 13 }}>{lbl}</div>
            </div>
            {i < arr.length - 1 && <div style={{ width: 28, height: 1, background: 'var(--border)', flexShrink: 0 }}/>}
          </React.Fragment>
        ))}
      </div>

      {/* STEP 1 — Upload CVs */}
      {step === 1 && (
        <div className="card card-pad" style={{ maxWidth: 760 }}>
          <div className="field">
            <label>Lowongan tujuan</label>
            {openJobs.length === 0 ? (
              <div style={{ fontSize: 13, color: 'var(--muted)', padding: '8px 0' }}>
                Belum ada lowongan terbuka. <a style={{ color: 'var(--accent)', cursor: 'pointer' }} onClick={() => go({ view: 'jobs', subview: 'new' })}>Buat lowongan dulu</a> agar skor AI relevan (atau lanjut tanpa lowongan).
              </div>
            ) : (
              <select className="select" value={jobId} onChange={(e) => setJobId(e.target.value)}>
                {openJobs.map(j => <option key={j.id} value={j.id}>{j.title} — {j.dept}</option>)}
              </select>
            )}
            <span className="hint">Kandidat masuk pipeline lowongan ini di kolom "Disaring AI" setelah dibaca AI.</span>
          </div>

          <div style={{ marginTop: 14 }}>
            <DropZone onFiles={onFilesPicked} accept=".pdf,.txt,.doc,.docx" subtitle="PDF / DOC / TXT · bisa banyak file sekaligus (maks 50)"/>
          </div>
          {aiError && <div style={{ color: 'oklch(0.55 0.18 25)', fontSize: 13, fontWeight: 600, marginTop: 10 }}>{aiError}</div>}

          {files.length > 0 && (
            <div style={{ marginTop: 18 }}>
              <div className="section-title" style={{ marginBottom: 10 }}>{files.length} CV siap dibaca</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                {files.map((f, i) => (
                  <div key={i} className="row-flex" style={{ padding: '7px 10px', border: '1px solid var(--border)', borderRadius: 7, background: 'var(--surface)' }}>
                    <Icon name="cv" size={14} style={{ color: 'var(--muted)' }}/>
                    <span style={{ fontSize: 12.5, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{f.name}</span>
                    <span className="mono" style={{ fontSize: 11, color: 'var(--muted)' }}>{f.size}</span>
                    <button className="btn ghost sm" style={{ padding: 4 }} onClick={() => removeFile(i)}><Icon name="x" size={12}/></button>
                  </div>
                ))}
              </div>
            </div>
          )}

          <div className="row-flex" style={{ marginTop: 18, justifyContent: 'flex-end' }}>
            <Btn kind="accent" icon="sparkles" disabled={realFiles.length === 0} onClick={runAI}>
              Baca {realFiles.length || ''} CV dengan AI
            </Btn>
          </div>
        </div>
      )}

      {/* STEP 2 — interactive AI reading */}
      {step === 2 && <AIReading progress={aiProgress}/>}

      {/* STEP 3 — Preview & edit */}
      {step === 3 && (
        <PreviewParsed parsed={parsed} setParsed={setParsed} job={job} parseInfo={parseInfo}
          autoTrigger={autoTrigger} setAutoTrigger={setAutoTrigger}
          onBack={() => setStep(1)} onConfirm={finish}/>
      )}

      {/* STEP 4 — Success */}
      {step === 4 && (
        <div className="card card-pad" style={{ maxWidth: 640, margin: '40px auto', textAlign: 'center', padding: 40 }}>
          <div style={{ width: 72, height: 72, borderRadius: 99, background: 'var(--good-2)', color: 'oklch(0.45 0.13 155)', display: 'grid', placeItems: 'center', margin: '0 auto 18px' }}>
            <Icon name="check" size={32} stroke={2.4}/>
          </div>
          <h2 style={{ fontSize: 22, letterSpacing: '-0.02em', margin: '0 0 8px' }}>{parsed.filter(p => p.include).length} kandidat berhasil diimpor</h2>
          <p style={{ color: 'var(--ink-2)', fontSize: 14, maxWidth: 420, margin: '0 auto' }}>
            Semua masuk pipeline <b>{job?.title || 'kandidat'}</b> di kolom <i>Disaring AI</i>, lengkap dengan CV yang bisa diunduh.
          </p>
          <div style={{ display: 'flex', gap: 10, justifyContent: 'center', marginTop: 22 }}>
            {job && <Btn kind="primary" icon="briefcase" onClick={() => go({ view: 'jobs', jobId: job.id, tab: 'kandidat' })}>Buka Pipeline</Btn>}
            <Btn icon="plus" onClick={reset}>Import lagi</Btn>
          </div>
        </div>
      )}
    </div>
  );
}

// ── Subcomponents ──

const DropZone = ({ onFiles, accept, subtitle }) => {
  const ref = useRef(null);
  return (
    <div onClick={() => ref.current && ref.current.click()}
       style={{ border: '2px dashed var(--border-strong)', borderRadius: 10, padding: 40, textAlign: 'center', cursor: 'pointer', background: 'var(--bg-soft)' }}>
      <div style={{ width: 48, height: 48, borderRadius: 99, background: 'var(--surface)', display: 'grid', placeItems: 'center', margin: '0 auto 12px', border: '1px solid var(--border)' }}>
        <Icon name="download" size={20} style={{ color: 'var(--muted)', transform: 'rotate(180deg)' }}/>
      </div>
      <div style={{ fontWeight: 700, fontSize: 14 }}>Tarik CV ke sini, atau <span style={{ color: 'var(--accent)' }}>browse</span></div>
      <div style={{ color: 'var(--muted)', fontSize: 12, marginTop: 4 }}>{subtitle}</div>
      <input ref={ref} type="file" multiple accept={accept} style={{ display: 'none' }}
             onChange={(e) => { onFiles(Array.from(e.target.files || [])); e.target.value = ''; }}/>
    </div>
  );
};

// Interactive AI reading — shows each CV's live status as it's parsed.
const AIReading = ({ progress }) => {
  const { done, total, items } = progress;
  const pct = total ? Math.round((done / total) * 100) : 0;
  const dot = (status) => {
    if (status === 'done') return { bg: 'var(--good)', col: 'white', icon: 'check' };
    if (status === 'reading') return { bg: 'var(--accent)', col: 'white', icon: 'sparkles' };
    if (status === 'error') return { bg: 'oklch(0.6 0.16 25)', col: 'white', icon: 'x' };
    return { bg: 'var(--surface-2)', col: 'var(--muted)', icon: 'cv' };
  };
  return (
    <div style={{ maxWidth: 720, margin: '20px auto' }}>
      <div className="card card-pad" style={{ padding: 28 }}>
        <div style={{ textAlign: 'center', marginBottom: 20 }}>
          <div style={{ width: 56, height: 56, borderRadius: 99, background: 'var(--accent-2)', display: 'grid', placeItems: 'center', margin: '0 auto 12px', animation: 'tl-pulse 1.6s ease-in-out infinite' }}>
            <Icon name="sparkles" size={26} style={{ color: 'var(--accent)' }}/>
          </div>
          <h2 style={{ fontSize: 20, letterSpacing: '-0.02em', margin: 0 }}>AI sedang membaca CV</h2>
          <p style={{ color: 'var(--muted)', fontSize: 13, marginTop: 6 }}><b style={{ color: 'var(--ink)' }}>{done}</b> dari {total} CV terbaca</p>
        </div>
        <div style={{ height: 6, background: 'var(--surface-2)', borderRadius: 99, overflow: 'hidden', marginBottom: 18 }}>
          <div style={{ width: pct + '%', height: '100%', background: 'var(--accent)', transition: 'width .3s' }}/>
        </div>
        <div className="col-flex" style={{ gap: 8, maxHeight: 360, overflow: 'auto' }}>
          {items.map((it, i) => {
            const d = dot(it.status);
            return (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '9px 12px', border: '1px solid ' + (it.status === 'reading' ? 'var(--accent)' : 'var(--border)'), background: it.status === 'reading' ? 'var(--accent-2)' : it.status === 'done' ? 'var(--good-2)' : 'var(--surface)', borderRadius: 8 }}>
                <div style={{ width: 26, height: 26, borderRadius: 99, background: d.bg, color: d.col, display: 'grid', placeItems: 'center', flexShrink: 0, animation: it.status === 'reading' ? 'tl-pulse 1.2s ease-in-out infinite' : 'none' }}>
                  <Icon name={d.icon} size={13} stroke={2.2}/>
                </div>
                <span style={{ fontSize: 13, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{it.name}</span>
                {it.status === 'reading' && <span style={{ fontSize: 12, color: 'var(--accent)', fontWeight: 600 }}>membaca…</span>}
                {it.status === 'done' && <span style={{ fontSize: 12, color: 'var(--ink-2)' }}>{it.extracted ? '→ ' + it.extracted : 'selesai'}</span>}
                {it.status === 'error' && <span style={{ fontSize: 12, color: 'oklch(0.55 0.16 25)', fontWeight: 600 }}>gagal dibaca</span>}
                {it.status === 'wait' && <span style={{ fontSize: 12, color: 'var(--muted)' }}>menunggu</span>}
              </div>
            );
          })}
        </div>
      </div>
      <style>{`@keyframes tl-pulse { 0%,100% { transform: scale(1); opacity: 1 } 50% { transform: scale(1.08); opacity: .85 } }`}</style>
    </div>
  );
};

const PreviewParsed = ({ parsed, setParsed, job, parseInfo, autoTrigger, setAutoTrigger, onBack, onConfirm }) => {
  const toggle = (id) => setParsed(parsed.map(p => p.id === id ? { ...p, include: !p.include } : p));
  const selected = parsed.filter(p => p.include).length;
  const avgScore = Math.round(parsed.filter(p => p.include).reduce((s, p) => s + p.score, 0) / Math.max(1, selected));
  const aiOff = parseInfo && !parseInfo.usedAI;

  return (
    <div>
      {aiOff && (
        <div style={{ marginBottom: 14, padding: '12px 14px', borderRadius: 8, background: 'oklch(0.97 0.04 75)', border: '1px solid oklch(0.85 0.1 75)', display: 'flex', gap: 10, alignItems: 'flex-start' }}>
          <span style={{ fontSize: 16, lineHeight: 1 }}>⚠️</span>
          <div style={{ fontSize: 12.5, color: 'oklch(0.42 0.08 60)', lineHeight: 1.5 }}>
            <b>AI belum aktif</b> — pembacaan memakai mode dasar (regex), sebagian data CV mungkin tidak lengkap.
            Aktifkan di <b>Pengaturan → AI</b> (isi API key), lalu ulangi import. Tetap bisa lanjut & lengkapi manual.
          </div>
        </div>
      )}
      <div className="ai-block" style={{ marginBottom: 16 }}>
        <div className="lbl"><Icon name="sparkles" size={12}/>{aiOff ? 'Pembacaan dasar selesai' : 'Pembacaan AI selesai'}</div>
        <div className="body">
          {aiOff ? 'Mode dasar' : 'AI'} berhasil membaca <b>{parsed.length} CV</b>. Skor cocok dihitung terhadap kriteria <b>{job?.title || 'lowongan'}</b>:
          rata-rata <b>{avgScore}</b>, {parsed.filter(p => p.score >= 80).length} kandidat skor ≥80. Periksa & edit sebelum dimasukkan ke pipeline.
        </div>
      </div>

      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ display: 'flex', alignItems: 'center', padding: '12px 16px', borderBottom: '1px solid var(--border)' }}>
          <strong>{selected} dari {parsed.length} kandidat dipilih</strong>
          <div style={{ flex: 1 }}/>
          <button className="btn ghost sm" onClick={() => setParsed(parsed.map(p => ({ ...p, include: true })))}>Pilih semua</button>
          <button className="btn ghost sm" onClick={() => setParsed(parsed.map(p => ({ ...p, include: false })))}>Kosongkan</button>
        </div>
        <table className="tbl">
          <thead>
            <tr>
              <th style={{ width: 40 }}></th>
              <th style={{ width: '26%' }}>Kandidat</th>
              <th>Skill</th>
              <th style={{ width: 120 }}>Kontak</th>
              <th style={{ width: 130 }}>Skor AI</th>
            </tr>
          </thead>
          <tbody>
            {parsed.map(p => (
              <tr key={p.id} style={{ background: p.include ? 'transparent' : 'var(--bg-soft)', opacity: p.include ? 1 : 0.55 }}>
                <td><input type="checkbox" checked={p.include} onChange={() => toggle(p.id)} style={{ width: 16, height: 16, accentColor: 'var(--accent)' }}/></td>
                <td>
                  <div className="row-flex">
                    <Avatar name={p.name}/>
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontWeight: 700, fontSize: 13 }}>{p.name}</div>
                      <div style={{ fontSize: 11, color: 'var(--muted)' }}>{[p.location, p.experience && p.experience + ' pengalaman'].filter(Boolean).join(' · ') || p.file}</div>
                    </div>
                  </div>
                </td>
                <td>
                  <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
                    {p.skills.length ? p.skills.map(s => <Badge key={s}>{s}</Badge>) : <span style={{ fontSize: 12, color: 'var(--muted)' }}>—</span>}
                  </div>
                </td>
                <td>
                  <div className="mono" style={{ fontSize: 11.5 }}>{p.phone || '—'}</div>
                  <div style={{ fontSize: 10.5, color: 'var(--muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 150 }}>{p.email}</div>
                </td>
                <td>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    <span className="mono" style={{ fontWeight: 700, fontSize: 14, width: 26, color: p.score >= 80 ? 'oklch(0.45 0.13 155)' : p.score >= 60 ? 'var(--ink)' : 'oklch(0.5 0.13 70)' }}>{p.score}</span>
                    <div style={{ flex: 1 }}><ScoreBar value={p.score}/></div>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="row-flex" style={{ marginTop: 18, padding: '14px 16px', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 10 }}>
        <Icon name="message" size={16} style={{ color: 'var(--wa)' }}/>
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 700, fontSize: 13 }}>Auto-trigger setelah import</div>
          <div style={{ fontSize: 12, color: 'var(--muted)' }}>{autoTrigger ? `WA Bot mengirim pesan perkenalan ke ${selected} kandidat (yang punya nomor)` : 'Tidak mengirim pesan otomatis — kandidat hanya masuk pipeline'}</div>
        </div>
        <Toggle on={autoTrigger} onChange={setAutoTrigger}/>
      </div>

      <div className="row-flex" style={{ marginTop: 18, justifyContent: 'space-between' }}>
        <button className="btn ghost sm" onClick={onBack}><Icon name="arrowL" size={12}/>Unggah ulang</button>
        <Btn kind="accent" icon="check" onClick={onConfirm} disabled={selected === 0}>Import {selected} kandidat ke pipeline</Btn>
      </div>
    </div>
  );
};

window.ImportView = ImportView;
