/**
 * Cache-dir janitor — deletes stale files under:
 *   <dataDir>/tmp/      — chat-saved files (save_tmp_file)
 *   <dataDir>/scratch/  — legacy chat-saved location (kept for back-compat)
 *
 * Without periodic sweeping the dirs grow forever. Retention is
 * settings.scratchRetentionDays (default 7).
 *
 * Conservative scope: only top-level files. Skips dotfiles, the
 * scratch-project marker CLAUDE.md, and subdirs (could be user-created
 * project trees we don't own).
 */

import { readdirSync, statSync, unlinkSync } from 'node:fs';
import { join } from 'node:path';
import { getDataDir } from './dirs';
import { loadSettings } from './settings';

const DEFAULT_RETENTION_DAYS = 7;
const ONE_DAY_MS = 24 * 60 * 60 * 1000;

function retentionMs(): number {
  let days = DEFAULT_RETENTION_DAYS;
  try {
    const s = loadSettings() as any;
    const v = Number(s?.scratchRetentionDays);
    if (Number.isFinite(v) && v > 0) days = v;
  } catch { /* settings unreadable — fall back to default */ }
  return days * ONE_DAY_MS;
}

function sweepDir(root: string, cutoff: number, skipNames: Set<string>): { scanned: number; deleted: number; freedBytes: number } {
  let scanned = 0, deleted = 0, freedBytes = 0;
  let entries: string[] = [];
  try { entries = readdirSync(root); } catch { return { scanned, deleted, freedBytes }; }
  for (const name of entries) {
    if (name.startsWith('.')) continue;
    if (skipNames.has(name)) continue;
    const p = join(root, name);
    let st;
    try { st = statSync(p); } catch { continue }
    if (!st.isFile()) continue;
    scanned++;
    if (st.mtimeMs > cutoff) continue;
    try { unlinkSync(p); deleted++; freedBytes += st.size; }
    catch (e) { console.warn('[scratch-cleanup] unlink failed:', p, (e as Error).message); }
  }
  return { scanned, deleted, freedBytes };
}

export function cleanupScratch(): { scanned: number; deleted: number; freedBytes: number } {
  const cutoff = Date.now() - retentionMs();
  const tmp = sweepDir(join(getDataDir(), 'tmp'), cutoff, new Set());
  const scratch = sweepDir(join(getDataDir(), 'scratch'), cutoff, new Set(['CLAUDE.md']));
  const total = {
    scanned: tmp.scanned + scratch.scanned,
    deleted: tmp.deleted + scratch.deleted,
    freedBytes: tmp.freedBytes + scratch.freedBytes,
  };
  if (total.deleted > 0) {
    console.log(`[scratch-cleanup] deleted ${total.deleted}/${total.scanned} files (tmp=${tmp.deleted}, scratch=${scratch.deleted}), freed ${total.freedBytes} bytes`);
  }
  return total;
}

let started = false;
export function startScratchCleanup(): void {
  if (started) return;
  started = true;
  // Run once shortly after boot (don't block ensureInitialized), then every 24h.
  setTimeout(() => { try { cleanupScratch(); } catch (e) { console.warn('[scratch-cleanup]', (e as Error).message); } }, 30_000);
  setInterval(() => { try { cleanupScratch(); } catch (e) { console.warn('[scratch-cleanup]', (e as Error).message); } }, ONE_DAY_MS);
}
