import type { PrekeyStore } from './store.js';
import { logger } from './logger.js';

/**
 * Background task that periodically purges stale identities from the store.
 *
 * "Stale" = no activity (register, fetch bundle, replenish, delete) for
 * more than `staleDays` days. The threshold and interval are configurable
 * via env vars:
 *   SHADE_STALE_DAYS              (default 30)
 *   SHADE_CLEANUP_INTERVAL_HOURS  (default 24)
 */
export class StaleCleanupTask {
  private timer: ReturnType<typeof setInterval> | null = null;
  private running = false;
  private readonly staleMs: number;
  private readonly intervalMs: number;

  constructor(
    private readonly store: PrekeyStore,
    options: { staleDays?: number; intervalHours?: number } = {},
  ) {
    const staleDays = options.staleDays
      ?? Number(process.env.SHADE_STALE_DAYS ?? 30);
    const intervalHours = options.intervalHours
      ?? Number(process.env.SHADE_CLEANUP_INTERVAL_HOURS ?? 24);
    this.staleMs = staleDays * 24 * 60 * 60 * 1000;
    this.intervalMs = intervalHours * 60 * 60 * 1000;
  }

  start(): void {
    if (this.running) return;
    this.running = true;
    // Run once immediately (so operators see it in the logs at startup)
    this.runOnce().catch((err) => {
      logger.error('Initial stale cleanup failed', { error: String(err) });
    });
    this.timer = setInterval(() => {
      this.runOnce().catch((err) => {
        logger.error('Stale cleanup failed', { error: String(err) });
      });
    }, this.intervalMs);
  }

  stop(): void {
    this.running = false;
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
  }

  /** Run a single cleanup cycle. Exposed for tests and manual triggers. */
  async runOnce(): Promise<number> {
    const count = await this.store.purgeStaleIdentities(this.staleMs);
    if (count > 0) {
      logger.info('Stale cleanup purged identities', {
        count,
        staleDays: this.staleMs / (24 * 60 * 60 * 1000),
      });
    } else {
      logger.debug('Stale cleanup: nothing to purge');
    }
    return count;
  }

  get isRunning(): boolean {
    return this.running;
  }
}
