/**
 * DiffCache — in-memory TTL cache for git diff results.
 *
 * Keyed by `phaseId:headHash` (or `phaseId:headHash:filePath` for per-file diffs).
 * TTL defaults to 5 minutes, configurable via REVIEW_DIFF_CACHE_TTL_MS env var.
 * Prefix-based invalidation clears all entries for a phase when a new commit lands.
 */

import type { FileStatEntry } from '../git/types.js';

interface CacheEntry<T> {
  value: T;
  expiresAt: number;
}

export class DiffCache<T> {
  private store = new Map<string, CacheEntry<T>>();
  private ttlMs: number;

  constructor(ttlMs: number) {
    this.ttlMs = ttlMs;
  }

  get(key: string): T | undefined {
    const entry = this.store.get(key);
    if (!entry) return undefined;
    if (Date.now() > entry.expiresAt) {
      this.store.delete(key);
      return undefined;
    }
    return entry.value;
  }

  set(key: string, value: T): void {
    this.store.set(key, { value, expiresAt: Date.now() + this.ttlMs });
  }

  invalidateByPrefix(prefix: string): void {
    for (const key of this.store.keys()) {
      if (key.startsWith(prefix)) this.store.delete(key);
    }
  }
}

// ---------------------------------------------------------------------------
// Response shapes (mirror the return types of getPhaseReviewDiff / getFileDiff)
// ---------------------------------------------------------------------------

export interface PhaseMetaResponse {
  phaseName: string;
  sourceBranch: string;
  targetBranch: string;
  files: FileStatEntry[];
  totalAdditions: number;
  totalDeletions: number;
}

export interface FileDiffResponse {
  binary: boolean;
  rawDiff: string;
}

// ---------------------------------------------------------------------------
// Singleton instances — TTL is read once at module load time
// ---------------------------------------------------------------------------

const TTL = parseInt(process.env.REVIEW_DIFF_CACHE_TTL_MS ?? '300000', 10);

export const phaseMetaCache = new DiffCache<PhaseMetaResponse>(TTL);
export const fileDiffCache = new DiffCache<FileDiffResponse>(TTL);
