// Batch Rename — pattern-based rename with preview, bundled as a zip.
// Patterns: {n} = sequence (1-based, padded), {name} = original base, {ext} = extension.

const FFLATE_URL = 'https://cdn.jsdelivr.net/npm/fflate@0.8.2/umd/index.js';

window.TOOL_HANDLERS['rename-batch'] = function RenameBatchTool() {
  const [files, setFiles] = React.useState([]);
  const [pattern, setPattern] = React.useState('photo-{n}.{ext}');
  const [pad, setPad] = React.useState(3);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  const addFiles = (picked) => {
    const list = Array.isArray(picked) ? picked : [picked];
    setFiles((prev) => [...prev, ...list]);
  };

  const newNames = React.useMemo(() => files.map((f, i) => {
    const dot = f.name.lastIndexOf('.');
    const base = dot > 0 ? f.name.slice(0, dot) : f.name;
    const ext = dot > 0 ? f.name.slice(dot + 1) : '';
    return (pattern || '{name}')
      .replace(/\{n\}/g, String(i + 1).padStart(pad, '0'))
      .replace(/\{name\}/g, base)
      .replace(/\{ext\}/g, ext);
  }), [files, pattern, pad]);

  const run = async () => {
    setBusy(true); setErr('');
    try {
      await window.loadScript(FFLATE_URL);
      const zip = {};
      for (let i = 0; i < files.length; i++) zip[newNames[i]] = new Uint8Array(await files[i].arrayBuffer());
      window.fflate.zip(zip, (zerr, data) => {
        setBusy(false);
        if (zerr) return setErr(zerr.message);
        window.downloadBlob(new Blob([data], { type: 'application/zip' }), 'renamed.zip');
      });
    } catch (e) { setErr(e.message); setBusy(false); }
  };

  if (files.length === 0) return <window.Dropzone onFile={addFiles} multiple title="Drop files here" hint="we'll rename them and zip the result" />;

  return (
    <div className="mini-tool">
      <div className="mini-label">Pattern · use {`{n}`}, {`{name}`}, {`{ext}`}</div>
      <input className="mini-input" value={pattern} onChange={(e) => setPattern(e.target.value)} placeholder="photo-{n}.{ext}" />

      <div className="cmp-slider-row" style={{ marginTop: 10 }}>
        <div className="cmp-label"><span>Zero-padding</span><span className="val">{pad}</span></div>
        <input type="range" min="1" max="6" value={pad} onChange={(e) => setPad(+e.target.value)} className="cmp-slider" />
      </div>

      <div className="mini-label" style={{ marginTop: 14 }}>Preview ({files.length} file{files.length === 1 ? '' : 's'})</div>
      <div style={{ maxHeight: 240, overflowY: 'auto', border: '1px solid var(--id-border)', borderRadius: 10 }}>
        {files.map((f, i) => (
          <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px', borderBottom: '1px solid var(--id-border)', fontSize: 12 }}>
            <span className="cmp-meta" style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{f.name}</span>
            <window.Icon name="arrow" size={12} />
            <span style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--id-brand-blue)', fontWeight: 600 }}>{newNames[i]}</span>
          </div>
        ))}
      </div>

      {err && <div style={{ color: '#c8321f', marginTop: 10 }}>{err}</div>}
      <div className="cmp-actions">
        <label className="btn btn-secondary">
          <window.Icon name="upload" size={16} /> Add more
          <input type="file" multiple hidden onChange={(e) => addFiles(Array.from(e.target.files))} />
        </label>
        <button className="btn btn-primary" onClick={run} disabled={busy}>
          <window.Icon name="archive" size={16} /> {busy ? 'Zipping…' : 'Download renamed.zip'}
        </button>
      </div>
    </div>
  );
};
