// preview-run.jsx — Preview drawer + Run progress modal
// Exposes: window.PreviewDrawer, window.RunModal, window.ageToMs, window.formatMime

const { useState: useState_pr, useEffect: useEffect_pr, useRef: useRef_pr } = React;

function ageToMs(value, unit) {
  const v = Number(value);
  const day = 86_400_000;
  switch (unit) {
    case 'days': return v * day;
    case 'weeks': return v * 7 * day;
    case 'months': return v * 30 * day;
    case 'years': return v * 365 * day;
    default: return v * day;
  }
}

function formatMime(mime) {
  if (mime.includes('folder')) return 'folder';
  if (mime.includes('image/')) return 'image';
  if (mime.includes('video/')) return 'video';
  if (mime.includes('pdf')) return 'pdf';
  if (mime.includes('word') || mime.includes('document')) return 'doc';
  if (mime.includes('sheet')) return 'sheet';
  if (mime.includes('zip')) return 'zip';
  if (mime.includes('text/plain')) return 'text';
  if (mime.includes('csv')) return 'csv';
  return mime.split('/').pop().slice(0, 6);
}

function relativeTime(iso) {
  const d = new Date(iso);
  const diff = Date.now() - d.getTime();
  const days = Math.floor(diff / 86_400_000);
  if (days === 0) return 'today';
  if (days === 1) return 'yesterday';
  if (days < 30) return days + ' days ago';
  if (days < 365) return Math.floor(days / 30) + ' months ago';
  return Math.floor(days / 365) + ' years ago';
}

function PreviewDrawer({ rule, onClose, onConfirm }) {
  const [state, setState] = useState_pr({ status: 'loading', files: [], error: null });

  useEffect_pr(() => {
    let cancel = false;
    setState({ status: 'loading', files: [], error: null });
    window.driveAPI
      .listMatching({
        folderId: rule.folderId,
        olderThanMs: ageToMs(rule.ageValue, rule.ageUnit),
        recursive: rule.recursive,
        mimeFilter: rule.mimeFilter,
      })
      .then((files) => { if (!cancel) setState({ status: 'ok', files, error: null }); })
      .catch((e) => { if (!cancel) setState({ status: 'error', files: [], error: e.message }); });
    return () => { cancel = true; };
  }, [rule.folderId, rule.ageValue, rule.ageUnit, rule.recursive, rule.mimeFilter]);

  const overCap = state.files.length > rule.perRunCap;
  const totalSize = state.files.reduce((a, f) => a + f.size, 0);

  return (
    <div className="drawer-scrim" onClick={onClose}>
      <div className="drawer" onClick={(e) => e.stopPropagation()}>
        <header>
          <div>
            <h2>Preview cleanup — {rule.folderName}</h2>
            <div className="mono" style={{ fontSize: 12, color: 'var(--fg-faint)', marginTop: 4 }}>
              {rule.folderPath}
            </div>
          </div>
          <button className="btn btn-ghost btn-sm" onClick={onClose}>✕ Close</button>
        </header>

        <div className="body">
          {state.status === 'loading' && (
            <div style={{ padding: 40, textAlign: 'center', color: 'var(--fg-soft)' }}>
              Scanning folder…
            </div>
          )}
          {state.status === 'error' && (
            <div style={{ padding: 40, textAlign: 'center', color: 'var(--danger)' }}>
              {state.error}
            </div>
          )}
          {state.status === 'ok' && state.files.length === 0 && (
            <div style={{ padding: 40, textAlign: 'center', color: 'var(--fg-soft)' }}>
              ✓ No files match these criteria. Nothing to delete.
            </div>
          )}
          {state.status === 'ok' && state.files.length > 0 && (
            <table className="file-table">
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Type</th>
                  <th>Modified</th>
                  <th style={{ textAlign: 'right' }}>Size</th>
                </tr>
              </thead>
              <tbody>
                {state.files.slice(0, 500).map((f) => (
                  <tr key={f.id}>
                    <td title={f.path}>
                      <div style={{ fontWeight: 500 }}>{f.name}</div>
                      <div className="mono" style={{ fontSize: 11, color: 'var(--fg-faint)' }}>
                        {f.path.split(' / ').slice(0, -1).join(' / ')}
                      </div>
                    </td>
                    <td><span className="chip">{formatMime(f.mimeType)}</span></td>
                    <td className="mtime">{relativeTime(f.modifiedTime)}</td>
                    <td className="size" style={{ textAlign: 'right' }}>{formatBytes(f.size)}</td>
                  </tr>
                ))}
                {state.files.length > 500 && (
                  <tr><td colSpan="4" style={{ textAlign: 'center', color: 'var(--fg-faint)', fontStyle: 'italic' }}>
                    … and {state.files.length - 500} more
                  </td></tr>
                )}
              </tbody>
            </table>
          )}
        </div>

        <footer>
          <div className="summary">
            {state.status === 'ok' && (
              <div>
                <div style={{ fontWeight: 600, fontSize: 14 }}>
                  {state.files.length} files · {formatBytes(totalSize)}
                </div>
                <div style={{ fontSize: 12, color: 'var(--fg-soft)' }}>
                  {rule.dryRun
                    ? 'Dry run — nothing will be deleted'
                    : rule.mode === 'permanent'
                      ? 'will be permanently deleted'
                      : 'will be moved to Trash (recoverable for 30 days)'}
                  {overCap && <span style={{ color: 'var(--danger)', marginLeft: 8 }}>
                    ⚠ Exceeds per-run cap of {rule.perRunCap}
                  </span>}
                </div>
              </div>
            )}
          </div>
          <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
          <button
            className={'btn ' + (rule.mode === 'permanent' && !rule.dryRun ? 'btn-danger' : 'btn-primary')}
            disabled={state.status !== 'ok' || state.files.length === 0 || overCap}
            onClick={() => onConfirm(state.files)}
          >
            {rule.dryRun
              ? `Simulate ${state.files.length}`
              : rule.mode === 'permanent'
                ? `Delete ${state.files.length} permanently`
                : `Move ${state.files.length} to Trash`}
          </button>
        </footer>
      </div>
    </div>
  );
}

function RunModal({ rule, files, onClose, onComplete }) {
  const [done, setDone] = useState_pr(0);
  const [failures, setFailures] = useState_pr([]);
  const [cancelled, setCancelled] = useState_pr(false);
  const [phase, setPhase] = useState_pr('running'); // running | done
  const cancelRef = useRef_pr(false);

  useEffect_pr(() => {
    let alive = true;
    (async () => {
      const concurrency = 8;
      let i = 0;
      const fails = [];
      async function worker() {
        while (alive && !cancelRef.current && i < files.length) {
          const f = files[i++];
          try {
            if (!rule.dryRun) {
              if (rule.mode === 'permanent') await window.driveAPI.deleteFile(f.id);
              else await window.driveAPI.trashFile(f.id);
            } else {
              await new Promise((r) => setTimeout(r, 30));
            }
            if (alive) setDone((d) => d + 1);
          } catch (e) {
            fails.push({ file: f, error: e.message });
            if (alive) setDone((d) => d + 1);
          }
        }
      }
      await Promise.all(Array.from({ length: concurrency }, worker));
      if (alive) {
        setFailures(fails);
        setPhase('done');
      }
    })();
    return () => { alive = false; };
  }, []);

  const pct = files.length === 0 ? 100 : Math.round((done / files.length) * 100);
  const successCount = done - failures.length;

  return (
    <div className="modal-scrim">
      <div className="modal" style={{ width: 'min(520px, 100%)' }}>
        <header>
          <h2>
            {phase === 'done'
              ? rule.dryRun ? 'Dry run complete' : 'Cleanup complete'
              : rule.dryRun ? 'Simulating…' : 'Cleaning up…'}
          </h2>
          {phase === 'done' && (
            <button className="btn btn-ghost btn-sm" onClick={() => onComplete(successCount, failures)}>✕</button>
          )}
        </header>
        <div className="body">
          <div style={{ marginBottom: 14, display: 'flex', justifyContent: 'space-between', fontSize: 13 }}>
            <span style={{ color: 'var(--fg-soft)' }}>{rule.folderName} · {rule.folderPath}</span>
            <span className="mono">{done} / {files.length}</span>
          </div>
          <div className="progress-track">
            <div className="progress-fill" style={{ width: pct + '%' }}></div>
          </div>
          {phase === 'running' && files[done] && (
            <div className="mono" style={{ marginTop: 14, fontSize: 12, color: 'var(--fg-faint)' }}>
              → {files[done].name}
            </div>
          )}
          {phase === 'done' && (
            <div style={{ marginTop: 18, fontSize: 13 }}>
              <div>
                <span className="chip chip-ok"><span className="dot"></span>{successCount} succeeded</span>
                {failures.length > 0 && (
                  <span className="chip chip-danger" style={{ marginLeft: 6 }}>
                    <span className="dot"></span>{failures.length} failed
                  </span>
                )}
              </div>
              {!rule.dryRun && rule.mode === 'trash' && successCount > 0 && (
                <div style={{ marginTop: 10, color: 'var(--fg-soft)' }}>
                  Files are in Drive's Trash — recoverable for 30 days.
                </div>
              )}
              {rule.dryRun && (
                <div style={{ marginTop: 10, color: 'var(--fg-soft)' }}>
                  Nothing was deleted. Toggle Dry run off on the folder rule to run for real.
                </div>
              )}
            </div>
          )}
        </div>
        <footer>
          {phase === 'running' ? (
            <button className="btn btn-danger" onClick={() => { cancelRef.current = true; setCancelled(true); }}>
              {cancelled ? 'Stopping…' : 'Cancel'}
            </button>
          ) : (
            <button className="btn btn-primary" onClick={() => onComplete(successCount, failures)}>Done</button>
          )}
        </footer>
      </div>
    </div>
  );
}

Object.assign(window, { PreviewDrawer, RunModal, ageToMs, formatMime, relativeTime });
