/* ============================================================
   CSV IMPORT — a reusable wizard used by People, Components and Tools.
   Parses client-side, maps columns to fields, then submits each row
   through the module's own create endpoint so validation and
   permissions stay exactly as they are for a hand-typed record.
   ============================================================ */

const IMPORT_PEOPLE_FIELDS = [
  {key:'name', label:'Name', required:true},
  {key:'jobTitle', label:'Job title'},
  {key:'department', label:'Department'},
  {key:'email', label:'Email'},
  {key:'phone', label:'Phone'}
];

const IMPORT_TOOL_FIELDS = [
  {key:'name', label:'Name', required:true},
  {key:'description', label:'Description'},
  {key:'category', label:'Category'},
  {key:'status', label:'Status', guess:['status'],
    transform: v => Object.keys(TOOL_STATUS_TONE).find(s => s.toLowerCase() === v.toLowerCase()) || 'Active'},
  {key:'primaryUrl', label:'Primary link (URL)', required:true, guess:['url','link','primary url']},
  {key:'primaryLabel', label:'Primary link label'},
  {key:'vendor', label:'Vendor'},
  {key:'accessNotes', label:'Access notes'},
  {key:'notes', label:'Notes'}
];

function componentImportFields(state){
  return [
    {key:'name', label:'Name', required:true},
    {key:'identifier', label:'Identifier'},
    {key:'description', label:'Description'},
    {key:'typeId', label:'Type', guess:['type','component type'],
      transform: v => {
        if (!v) return '';
        const t = state.componentTypes.find(t => t.name.toLowerCase() === v.trim().toLowerCase());
        return t ? t.id : '';
      }},
    {key:'status', label:'Status', transform: v => STATUSES.includes(v) ? v : 'Active'},
    {key:'tier', label:'Tier (1-4)', transform: v => {
      const n = parseInt(v, 10);
      return TIERS.includes(n) ? n : 3;
    }},
    {key:'vendor', label:'Vendor'},
    {key:'environment', label:'Environment'},
    {key:'businessCapability', label:'Business capability'},
    {key:'hostingLocation', label:'Hosting location'},
    {key:'goLiveDate', label:'Go-live date (YYYY-MM-DD)'},
    {key:'lastReviewed', label:'Last reviewed (YYYY-MM-DD)'},
    {key:'costCentre', label:'Cost centre'},
    {key:'recoveryTier', label:'Recovery tier'},
    {key:'notes', label:'Notes'}
  ];
}

function ImportCsvModal({title, fields, onImportRow, onDone, onClose, toast}){
  const [step, setStep] = useState('source');
  const [pasteText, setPasteText] = useState('');
  const [parsed, setParsed] = useState(null);
  const [mapping, setMapping] = useState({});
  const [results, setResults] = useState([]);
  const fileRef = useRef(null);

  const norm = (s) => String(s || '').toLowerCase().replace(/[\s_-]+/g, '');

  const load = (text) => {
    const p = parseCsv(text);
    if (!p.headers.length) { toast('No rows found in that CSV', true); return; }
    const guess = {};
    fields.forEach(f => {
      const names = [f.label, f.key, ...(f.guess || [])].map(norm);
      guess[f.key] = p.headers.findIndex(h => names.includes(norm(h)));
    });
    setMapping(guess);
    setParsed(p);
    setStep('map');
  };

  const onFile = (file) => {
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => load(String(reader.result));
    reader.readAsText(file);
  };

  const buildRow = (arr) => {
    const out = {};
    fields.forEach(f => {
      const ci = mapping[f.key];
      let v = (ci != null && ci >= 0 && arr[ci] != null) ? String(arr[ci]).trim() : '';
      if (f.transform) v = f.transform(v);
      out[f.key] = v;
    });
    return out;
  };

  const preview = parsed ? parsed.rows.slice(0, 5).map(buildRow) : [];
  const missingRequiredMapping = fields.some(f => f.required && !(mapping[f.key] >= 0));

  const startImport = async () => {
    setStep('importing');
    const res = [];
    for (let i = 0; i < parsed.rows.length; i++) {
      const values = buildRow(parsed.rows[i]);
      const missing = fields.filter(f => f.required && !values[f.key]);
      if (missing.length) {
        res.push({row: i + 2, ok: false, error: `Missing ${missing.map(m => m.label).join(', ')}`, values});
      } else {
        try { await onImportRow(values); res.push({row: i + 2, ok: true, values}); }
        catch (err) { res.push({row: i + 2, ok: false, error: err.message, values}); }
      }
      setResults([...res]);
    }
    setStep('done');
    if (onDone) onDone();
  };

  const downloadFailed = () => {
    const failed = results.filter(r => !r.ok);
    exportCsv('import-failures.csv', [...fields.map(f => f.label), 'Error'],
      failed.map(r => [...fields.map(f => r.values[f.key]), r.error]));
  };

  const okCount = results.filter(r => r.ok).length;

  return (
    <Modal wide title={title} onClose={onClose} footer={
      step === 'map' ? <>
        <button className="btn" onClick={()=>{ setParsed(null); setStep('source'); }}>Back</button>
        <button className="btn primary" disabled={missingRequiredMapping || !parsed.rows.length}
          onClick={startImport}>Import {parsed.rows.length} row{parsed.rows.length===1?'':'s'}</button>
      </> : step === 'done' ? <>
        {results.some(r => !r.ok) &&
          <button className="btn" onClick={downloadFailed}><I.down size={13}/>Download failed rows</button>}
        <button className="btn primary" onClick={onClose}>Done</button>
      </> : null
    }>
      {step === 'source' &&
        <div className="stack">
          <div className="info-box">
            Upload a CSV file, or paste its contents below. The first row must be column headers.
          </div>
          <input ref={fileRef} type="file" accept=".csv,text/csv" style={{display:'none'}}
            onChange={e=>onFile(e.target.files[0])}/>
          <button className="btn" onClick={()=>fileRef.current.click()}><I.up size={14}/>Choose a CSV file</button>
          <Field label="Or paste CSV text">
            <textarea rows={8} value={pasteText} onChange={e=>setPasteText(e.target.value)}
              placeholder={'name,jobTitle,email\nJane Doe,Engineer,jane@example.com'}/>
          </Field>
          <div className="row" style={{justifyContent:'flex-end'}}>
            <button className="btn primary" disabled={!pasteText.trim()} onClick={()=>load(pasteText)}>
              Parse pasted text</button>
          </div>
        </div>}

      {step === 'map' && parsed &&
        <div className="stack">
          <div className="xsmall dim">
            {parsed.rows.length} row{parsed.rows.length===1?'':'s'} found. Match each field to a CSV column.
          </div>
          <div className="tbl-wrap">
            <table>
              <thead><tr><th>Field</th><th>CSV column</th></tr></thead>
              <tbody>
                {fields.map(f =>
                  <tr key={f.key}>
                    <td>{f.label}{f.required && <span style={{color:'var(--red)'}}> *</span>}</td>
                    <td>
                      <select value={mapping[f.key] != null ? mapping[f.key] : -1}
                        onChange={e=>setMapping(m=>({...m, [f.key]: Number(e.target.value)}))}>
                        <option value={-1}>Skip this field</option>
                        {parsed.headers.map((h,i) => <option key={i} value={i}>{h}</option>)}
                      </select>
                    </td>
                  </tr>)}
              </tbody>
            </table>
          </div>
          <div className="xsmall dim">Preview (first {preview.length} rows)</div>
          <div className="tbl-wrap" style={{maxHeight:220}}>
            <table>
              <thead><tr>{fields.map(f => <th key={f.key}>{f.label}</th>)}</tr></thead>
              <tbody>
                {preview.map((r,i) =>
                  <tr key={i}>{fields.map(f =>
                    <td key={f.key} className="small">{r[f.key] || <span className="dim">—</span>}</td>)}</tr>)}
              </tbody>
            </table>
          </div>
        </div>}

      {step === 'importing' &&
        <div className="stack">
          <div className="row" style={{gap:10}}>
            <span className="spinner"/>Importing row {results.length} of {parsed.rows.length}…</div>
          <div className="progress">
            <span style={{width: Math.round(results.length / parsed.rows.length * 100) + '%'}}/></div>
        </div>}

      {step === 'done' &&
        <div className="stack">
          <div className={okCount === results.length ? 'info-box' : 'warn-box'}>
            Imported {okCount} of {results.length} row{results.length===1?'':'s'}.
            {results.length - okCount > 0 && ` ${results.length - okCount} failed — see below.`}
          </div>
          {results.some(r => !r.ok) &&
            <div className="tbl-wrap" style={{maxHeight:260}}>
              <table>
                <thead><tr><th>Row</th><th>Name</th><th>Error</th></tr></thead>
                <tbody>
                  {results.filter(r => !r.ok).map(r =>
                    <tr key={r.row}>
                      <td className="mono small">{r.row}</td>
                      <td className="small">{r.values.name || <span className="dim">—</span>}</td>
                      <td className="small" style={{color:'var(--red)'}}>{r.error}</td>
                    </tr>)}
                </tbody>
              </table>
            </div>}
        </div>}
    </Modal>
  );
}
