// Tests for the preservation audit logic in SaeeolCompactionChunks.
// Verifies that file paths, commands, and error strings from the original
// conversation are detected and their presence in the summary is measured.

import { describe, expect, test } from "bun:test"

// Duplicate the audit logic for unit testing.
// In production this lives inside compaction-chunks.ts as a private function.
const PRESERVATION_PATTERNS = [
  /(?:\/[\w.-]+){2,}/g,
  /(?:\\[\w.-]+){2,}/g,
  /\b\w*error\w*[\s:]+[^\n]{5,80}/gi,
  /\b(?:npm|bun|pnpm|npx|git|docker)\s+\S+/g,
]

function extractEntities(text: string): Set<string> {
  const entities = new Set<string>()
  for (const pattern of PRESERVATION_PATTERNS) {
    const matches = text.match(pattern)
    if (matches) for (const m of matches) entities.add(m.trim())
  }
  return entities
}

function auditPreservation(original: string, summary: string) {
  const originalEntities = extractEntities(original)
  if (originalEntities.size === 0) return { total: 0, preserved: 0, missing: [] as string[] }
  const preserved: string[] = []
  const missing: string[] = []
  for (const entity of originalEntities) {
    if (summary.toLowerCase().includes(entity.toLowerCase().slice(0, 40))) {
      preserved.push(entity)
    } else {
      missing.push(entity)
    }
  }
  return { total: originalEntities.size, preserved: preserved.length, missing: missing.slice(0, 10) }
}

describe("compaction preservation audit", () => {
  test("detects Unix file paths from original", () => {
    const original = "I edited /src/components/App.tsx and /src/utils/helpers.ts"
    const entities = extractEntities(original)
    expect(entities.has("/src/components/App.tsx")).toBe(true)
    expect(entities.has("/src/utils/helpers.ts")).toBe(true)
  })

  test("detects Windows file paths from original", () => {
    const original = "Modified src\\components\\App.tsx and lib\\utils\\index.js"
    const entities = extractEntities(original)
    expect(entities.size).toBeGreaterThan(0)
  })

  test("detects commands from original", () => {
    const original = "Run npm install and git commit -m 'fix'"
    const entities = extractEntities(original)
    expect(entities.has("npm install")).toBe(true)
    expect(entities.has("git commit")).toBe(true)
  })

  test("detects error messages from original", () => {
    const original = "TypeError: Cannot read properties of undefined (reading 'map')"
    const entities = extractEntities(original)
    expect(entities.size).toBeGreaterThan(0)
  })

  test("reports preserved when summary contains the path", () => {
    const original = "Edited /src/components/App.tsx to fix the bug"
    const summary = "Fixed bug in /src/components/App.tsx"
    const result = auditPreservation(original, summary)
    expect(result.total).toBeGreaterThan(0)
    expect(result.preserved).toBe(result.total)
    expect(result.missing).toHaveLength(0)
  })

  test("reports missing when summary drops the path", () => {
    const original = "Edited /src/components/App.tsx and /src/utils/helpers.ts"
    const summary = "Fixed bug in the component"
    const result = auditPreservation(original, summary)
    expect(result.total).toBeGreaterThan(0)
    expect(result.preserved).toBe(0)
    expect(result.missing.length).toBeGreaterThan(0)
  })

  test("handles empty original gracefully", () => {
    const result = auditPreservation("", "some summary")
    expect(result.total).toBe(0)
    expect(result.preserved).toBe(0)
    expect(result.missing).toHaveLength(0)
  })

  test("handles empty summary gracefully", () => {
    const original = "Run npm install to fix /src/index.ts"
    const result = auditPreservation(original, "")
    expect(result.total).toBeGreaterThan(0)
    expect(result.preserved).toBe(0)
    expect(result.missing.length).toBeGreaterThan(0)
  })

  test("partial preservation is reported correctly", () => {
    const original = "npm install, bun test, and git push after editing /src/app.tsx"
    const summary = "Ran npm install, edited /src/app.tsx"
    const result = auditPreservation(original, summary)
    expect(result.total).toBeGreaterThan(1)
    expect(result.preserved).toBeGreaterThan(0)
    expect(result.preserved).toBeLessThan(result.total)
  })

  test("case-insensitive matching for paths", () => {
    const original = "Edited /src/Components/App.tsx"
    const summary = "Fixed bug in /src/components/app.tsx"
    const result = auditPreservation(original, summary)
    expect(result.preserved).toBeGreaterThan(0)
  })

  test("limits missing list to 10 entries", () => {
    const paths = Array.from({ length: 20 }, (_, i) => `/src/file${i}.ts`)
    const original = paths.join(", ")
    const result = auditPreservation(original, "nothing relevant")
    expect(result.missing.length).toBeLessThanOrEqual(10)
  })
})
