import process from 'node:process'
import { readConfig } from '../core/config.ts'
import { logger } from '../core/logger.ts'
import { runPrune } from './store/prune.ts'

const ONE_DAY_MS = 24 * 3_600_000
const RETENTION_DAYS_DEFAULT = 30

let timer: ReturnType<typeof setInterval> | null = null

/**
 * Background maintenance loop: prunes captured traces older than the
 * configured retention so the trace DB doesn't grow unbounded as capture
 * accumulates.
 *
 * Retention is `retentionDays` in ~/.thomas/config.json (default 30); set
 * it to 0 to disable pruning. THOMAS_RETENTION_DAYS overrides it.
 * Vacuum is opt-in via THOMAS_PRUNE_VACUUM=1 (slow, pauses writes).
 */
export async function startMaintenanceLoop(): Promise<void> {
  if (timer) return
  const retentionDays = await resolveRetentionDays()
  if (retentionDays <= 0) {
    logger.info('maintenance: auto-prune disabled (retentionDays = 0)')
    return
  }

  const tick = async () => {
    try {
      const cutoff = Date.now() - retentionDays * ONE_DAY_MS
      const vacuum = process.env.THOMAS_PRUNE_VACUUM === '1'
      const result = await runPrune(cutoff, { vacuum })
      if (result.deletedActions > 0) {
        const mb = (result.estimatedBytes / 1024 / 1024).toFixed(1)
        const archived =
          result.archivedDays.length > 0
            ? `, archived ${result.archivedDays.length} day-file(s)`
            : ''
        logger.info(
          `maintenance: auto-pruned ${result.deletedActions} actions / ${result.deletedRuns} runs / ${result.deletedThreads} threads (~${mb}MB reclaimable${result.vacuumed ? ', vacuumed' : ''}${archived})`,
        )
      } else {
        logger.debug('maintenance: nothing to prune')
      }
    } catch (err) {
      logger.warn(`maintenance: prune failed: ${(err as Error).message}`)
    }
  }

  // First run after 10 minutes so we don't compete with daemon startup;
  // then once a day.
  setTimeout(() => void tick(), 10 * 60_000).unref()
  timer = setInterval(() => void tick(), ONE_DAY_MS)
  timer.unref()
  logger.info(`maintenance: auto-prune every 24h, retention ${retentionDays}d`)
}

export function stopMaintenanceLoop(): void {
  if (timer) {
    clearInterval(timer)
    timer = null
  }
}

// Retention comes from config.json (retentionDays, default 30). The
// THOMAS_RETENTION_DAYS env var still overrides it as a power-user / CI
// escape hatch.
async function resolveRetentionDays(): Promise<number> {
  const env = process.env.THOMAS_RETENTION_DAYS
  if (env != null && env !== '') return parseRetention(env)
  const { retentionDays } = await readConfig()
  return Number.isFinite(retentionDays) && retentionDays >= 0
    ? retentionDays
    : RETENTION_DAYS_DEFAULT
}

function parseRetention(raw: string | undefined): number {
  if (raw == null || raw === '') return RETENTION_DAYS_DEFAULT
  const n = Number.parseInt(raw, 10)
  if (!Number.isFinite(n) || n < 0) return RETENTION_DAYS_DEFAULT
  return n
}
