/**
 * cli:compute-page-diff — compute-diff.ts
 *
 * The pure spec-diff core. Loads the previous snapshot, scans the current
 * pagespecs, and categorises each page. `toRegenerate = added ∪ modified` —
 * the disk-drift union is the orchestrator's job (see `disk-drift.ts`).
 */
import { scanPagespecs, loadSnapshot } from './scan-pagespecs.js'
import type { ComputePageDiffInput, ComputePageDiffReport, ModifiedPage } from './types.js'

export function computeDiff(input: ComputePageDiffInput): ComputePageDiffReport {
  const { snapshot, found } = loadSnapshot(input.moduleRoot)
  const scan = scanPagespecs(input.moduleRoot)

  const added: string[] = []
  const modified: ModifiedPage[] = []
  const unchanged: string[] = []
  const removed: string[] = []

  const currentKeys = new Set<string>()
  for (const { key, hash } of scan.pages) {
    currentKeys.add(key)
    const previousHash = snapshot.pages[key]
    if (previousHash === undefined) {
      added.push(key)
    } else if (previousHash !== hash) {
      modified.push({ key, previousHash, currentHash: hash })
    } else {
      unchanged.push(key)
    }
  }

  for (const key of Object.keys(snapshot.pages)) {
    if (!currentKeys.has(key)) removed.push(key)
  }

  const toRegenerate = [...added, ...modified.map((m) => m.key)].sort()

  return {
    moduleRoot: input.moduleRoot,
    snapshotFound: found,
    diff: {
      added: [...added].sort(),
      modified,
      removed: removed.sort(),
      unchanged: [...unchanged].sort(),
    },
    toRegenerate,
    warnings: scan.warnings,
  }
}
