// Compress Image — re-encode an image as JPEG at a chosen quality level.
// Single-file mode shows a before/after slider; Batch mode processes many files → zip.

async function compressBlob(file, opts) {
  const { blob } = await window.workerEncodeImage(file, {
    format: 'jpeg',
    quality: (opts.quality || 70) / 100,
    flatten: true,
  });
  return { blob, ext: 'jpg' };
}

window.TOOL_HANDLERS['compress-image'] = function CompressImageTool() {
  const [mode, setMode] = React.useState('single');
  const [batchOpts, setBatchOpts] = React.useState({ quality: 70 });
  const [file, setFile] = React.useState(null);
  const [srcUrl, setSrcUrl] = React.useState('');
  const [srcSize, setSrcSize] = React.useState(0);
  const [srcDims, setSrcDims] = React.useState({ w: 0, h: 0 });
  const [quality, setQuality] = React.useState(70);
  const [outUrl, setOutUrl] = React.useState('');
  const [outSize, setOutSize] = React.useState(0);
  const [busy, setBusy] = React.useState(false);
  const imgElRef = React.useRef(null);

  const fmt = window.fmtBytes;

  const fileRef = React.useRef(null);

  const handleFile = async (f) => {
    if (!f || !f.type.startsWith('image/')) return;
    fileRef.current = f;
    setFile(f); setSrcSize(f.size);
    const { img, url } = await window.loadImageFromFile(f);
    setSrcUrl(url); setSrcDims({ w: img.width, h: img.height });
    imgElRef.current = img; compress(f, quality);
  };

  const compress = async (source, q) => {
    if (!source) return;
    setBusy(true);
    const t0 = performance.now();
    try {
      const { blob } = await window.workerEncodeImage(source, {
        format: 'jpeg', quality: q / 100, flatten: true,
      });
      if (outUrl) URL.revokeObjectURL(outUrl);
      setOutUrl(URL.createObjectURL(blob));
      setOutSize(blob.size);
      window.mmTrackComplete?.('compress-image', { durationMs: Math.round(performance.now() - t0), success: true });
    } catch (e) {
      window.mmTrackComplete?.('compress-image', { durationMs: Math.round(performance.now() - t0), success: false });
      throw e;
    } finally {
      setBusy(false);
    }
  };

  React.useEffect(() => {
    if (fileRef.current) {
      const id = setTimeout(() => compress(fileRef.current, quality), 120);
      return () => clearTimeout(id);
    }
  }, [quality]);

  const reset = () => {
    if (srcUrl) URL.revokeObjectURL(srcUrl);
    if (outUrl) URL.revokeObjectURL(outUrl);
    setFile(null); setSrcUrl(''); setOutUrl(''); setSrcSize(0); setOutSize(0);
  };
  const download = () => {
    if (!outUrl) return;
    const a = document.createElement('a'); a.href = outUrl;
    a.download = file.name.replace(/\.[^.]+$/, '') + '-compressed.jpg'; a.click();
  };
  const reduction = srcSize && outSize ? Math.max(0, Math.round((1 - outSize / srcSize) * 100)) : 0;

  if (mode === 'batch') {
    return (
      <window.BatchMode
        onExit={() => setMode('single')}
        process={compressBlob} opts={batchOpts} setOpts={setBatchOpts}
        accept="image/*" title="Drop images here" hint="JPEG re-encode, one quality for all"
        defaultExt="jpg" zipName="compressed"
        renderControls={({ opts, setOpts }) => (
          <div className="cmp-slider-row" style={{ marginBottom: 8 }}>
            <div className="cmp-label"><span>Quality</span><span className="val">{opts.quality}%</span></div>
            <input type="range" min="10" max="100" value={opts.quality}
                   onChange={(e) => setOpts({ ...opts, quality: +e.target.value })}
                   className="cmp-slider" />
          </div>
        )}
      />
    );
  }

  if (!file) return (
    <>
      <window.Dropzone onFile={handleFile} title="Drop an image here" hint="PNG, JPG, WebP" accept="image/*" />
      <div style={{ textAlign: 'center', marginTop: 10 }}>
        <button className="filter-pill" onClick={() => setMode('batch')}><window.Icon name="grid" size={12} /> Batch mode</button>
      </div>
    </>
  );

  return (
    <div>
      <div className="cmp-slider-row">
        <div className="cmp-label"><span>Quality</span><span className="val">{quality}%</span></div>
        <input type="range" min="10" max="100" step="1" value={quality} onChange={(e) => setQuality(+e.target.value)} className="cmp-slider" />
      </div>
      <window.BeforeAfterSlider
        before={srcUrl}
        after={outUrl || srcUrl}
        labelBefore={`Original · ${fmt(srcSize)}`}
        labelAfter={`Compressed · ${outSize ? fmt(outSize) : '…'}`}
        caption={`${srcDims.w} × ${srcDims.h} · JPEG q${quality}%`}
      />
      <div className="cmp-stats">
        <div className={`cmp-stat ${reduction > 0 ? 'success' : ''}`}>
          <div className="sv">{reduction > 0 ? `−${reduction}%` : '0%'}</div>
          <div className="sl">Size reduction</div>
        </div>
        <div className="cmp-stat">
          <div className="sv">{outSize ? fmt(Math.max(0, srcSize - outSize)) : '…'}</div>
          <div className="sl">Saved</div>
        </div>
        <div className="cmp-stat"><div className="sv">100%</div><div className="sl">Private · local</div></div>
      </div>
      <div className="cmp-actions">
        <button className="btn btn-secondary" onClick={reset}><window.Icon name="upload" size={16} /> Choose another</button>
        <button className="filter-pill" onClick={() => setMode('batch')}><window.Icon name="grid" size={14} /> Batch mode</button>
        <button className="btn btn-primary" onClick={download} disabled={busy || !outUrl}><window.Icon name="download" size={16} /> Download JPG</button>
      </div>
    </div>
  );
};
