param(
  [string]$ProjectRoot = "",
  [switch]$AsJson,
  [switch]$AllowWarningsOnly
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

if ([string]::IsNullOrWhiteSpace($ProjectRoot)) {
  $ProjectRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot "..\..\..\.."))
}

function New-Issue {
  param(
    [string]$Severity,
    [string]$File,
    [string]$Section,
    [string]$Message
  )

  [PSCustomObject]@{
    severity = $Severity
    file = $File
    section = $Section
    message = $Message
  }
}

function Get-FileContentOrNull {
  param([string]$Path)

  if (-not (Test-Path -LiteralPath $Path)) {
    return $null
  }

  Get-Content -LiteralPath $Path -Raw
}

function Test-ContainsAll {
  param(
    [string]$Content,
    [string[]]$Terms
  )

  foreach ($term in $Terms) {
    if ($Content -notmatch [regex]::Escape($term)) {
      return $false
    }
  }

  return $true
}

$issues = @()

$acceptanceCriteriaPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\ACCEPTANCE_CRITERIA.md"
$acceptanceExamplesPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\ACCEPTANCE_EXAMPLES.md"
$traceabilityPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\TRACEABILITY_MATRIX.md"
$testStrategyPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\TEST_STRATEGY.md"
$nlCasesPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\NATURAL_LANGUAGE_TEST_CASES.md"
$verifyMatrixPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\verify-matrix.md"
$failureTriagePath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\failure-triage.md"
$regressionPlanPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\REGRESSION_PLAN.md"
$currentTaskPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\context\CURRENT_TASK.md"

$acceptanceCriteria = Get-FileContentOrNull -Path $acceptanceCriteriaPath
$acceptanceExamples = Get-FileContentOrNull -Path $acceptanceExamplesPath
$traceability = Get-FileContentOrNull -Path $traceabilityPath
$testStrategy = Get-FileContentOrNull -Path $testStrategyPath
$nlCases = Get-FileContentOrNull -Path $nlCasesPath
$verifyMatrix = Get-FileContentOrNull -Path $verifyMatrixPath
$failureTriage = Get-FileContentOrNull -Path $failureTriagePath
$regressionPlan = Get-FileContentOrNull -Path $regressionPlanPath
$currentTask = Get-FileContentOrNull -Path $currentTaskPath

if ($null -eq $acceptanceCriteria) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/ACCEPTANCE_CRITERIA.md" -Section "file" -Message "缺少验收标准模板。"
}
else {
  if (-not (Test-ContainsAll -Content $acceptanceCriteria -Terms @("Requirement ID", "可观察的成功结果和失败结果", "负向 / 异常条件", "测试层级"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/ACCEPTANCE_CRITERIA.md" -Section "acceptance-shape" -Message "验收标准模板缺少第13章要求的可观察成功/失败结果或测试层级。"
  }
}

if ($null -eq $acceptanceExamples) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/ACCEPTANCE_EXAMPLES.md" -Section "file" -Message "缺少验收示例模板。"
}
else {
  if (-not (Test-ContainsAll -Content $acceptanceExamples -Terms @("正向示例", "负向示例", "证据目标"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/ACCEPTANCE_EXAMPLES.md" -Section "acceptance-examples" -Message "验收示例模板缺少第13章要求的正向、负向示例或证据目标。"
  }
}

if ($null -eq $traceability) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/TRACEABILITY_MATRIX.md" -Section "file" -Message "缺少追溯矩阵模板。"
}
else {
  if (-not (Test-ContainsAll -Content $traceability -Terms @("每条 P0/P1 需求都必须恰好出现一次", "至少一个测试层级和一个证据路径", "缺少 Oracle 或证据路径的 P0/P1 行不能进入实现"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/TRACEABILITY_MATRIX.md" -Section "traceability-rules" -Message "追溯矩阵模板缺少第13章要求的需求到测试和证据约束。"
  }
}

if ($null -eq $testStrategy) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/TEST_STRATEGY.md" -Section "file" -Message "缺少测试策略模板。"
}
else {
  if (-not (Test-ContainsAll -Content $testStrategy -Terms @("开发验证与验收验证分层", "TDD RED", "TDD GREEN / REFACTOR", "假测试拦截规则", "只断言 `200`、`truthy`", "只跑 happy path"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/TEST_STRATEGY.md" -Section "testing-policy" -Message "测试策略模板缺少第13章要求的 TDD、开发/验收验证分层或假测试拦截规则。"
  }
}

if ($null -eq $nlCases) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/NATURAL_LANGUAGE_TEST_CASES.md" -Section "file" -Message "缺少自然语言测试用例模板。"
}
else {
  if (-not (Test-ContainsAll -Content $nlCases -Terms @("P0 需求默认不少于 5 条", "P1 需求默认不少于 3 条", "TDD 候选", "不得只写一条端到端 happy path"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/NATURAL_LANGUAGE_TEST_CASES.md" -Section "nl-cases" -Message "自然语言测试用例模板缺少第13章要求的用例规模、TDD 候选或 happy path 约束。"
  }
}

if ($null -eq $verifyMatrix) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/verify-matrix.md" -Section "file" -Message "缺少验证矩阵模板。"
}
else {
  if (-not (Test-ContainsAll -Content $verifyMatrix -Terms @("开发验证", "用户验收链路", "失败态验收", "假测试检测", "发布候选验证"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/testing/verify-matrix.md" -Section "verify-gates" -Message "验证矩阵模板缺少第13章要求的开发验证、验收验证、失败态或假测试检查。"
  }
}

if ($null -eq $failureTriage) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/failure-triage.md" -Section "file" -Message "缺少 failure-triage 模板。"
}
else {
  if (-not (Test-ContainsAll -Content $failureTriage -Terms @("TEST_CODE_ISSUE", "PRODUCT_BUG", "REQUIREMENT_CHANGE", "ENV_OR_DATA_ISSUE", "FLAKY", "弱化断言掩盖产品问题"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/failure-triage.md" -Section "triage-policy" -Message "failure-triage 模板缺少第13章要求的失败分类或禁止弱化断言规则。"
  }
}

if ($null -eq $regressionPlan) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/REGRESSION_PLAN.md" -Section "file" -Message "缺少回归计划模板。"
}
else {
  if (-not (Test-ContainsAll -Content $regressionPlan -Terms @("受影响测试", "P0 回归集合", "发布证据"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/REGRESSION_PLAN.md" -Section "regression-shape" -Message "回归计划模板缺少第13章要求的受影响测试、P0 回归或发布证据字段。"
  }
}

if ($null -eq $currentTask) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/context/CURRENT_TASK.md" -Section "file" -Message "缺少 CURRENT_TASK 模板。"
}
else {
  if (-not (Test-ContainsAll -Content $currentTask -Terms @("本轮 development_validation", "本轮 acceptance_validation", "未运行测试 / 豁免及原因", "假测试风险提示"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/context/CURRENT_TASK.md" -Section "testing-fields" -Message "CURRENT_TASK 模板缺少第13章要求的开发验证、验收验证或未运行测试记录字段。"
  }
}

$errors = @($issues | Where-Object { $_.severity -eq "error" })
$warnings = @($issues | Where-Object { $_.severity -eq "warning" })
$exitCode = if ($errors.Count -gt 0) { 1 } elseif ($warnings.Count -gt 0 -and -not $AllowWarningsOnly) { 2 } else { 0 }

if ($AsJson) {
  [PSCustomObject]@{
    ok = ($exitCode -eq 0)
    errors = $errors
    warnings = $warnings
  } | ConvertTo-Json -Depth 6
  exit $exitCode
}

if ($errors.Count -eq 0 -and $warnings.Count -eq 0) {
  Write-Output "Testing lint passed."
  exit 0
}

if ($errors.Count -gt 0) {
  Write-Output "Testing lint failed."
  foreach ($issue in $errors) {
    Write-Output ("- [ERROR] {0} :: {1} :: {2}" -f $issue.file, $issue.section, $issue.message)
  }
}

if ($warnings.Count -gt 0) {
  if ($errors.Count -eq 0) {
    Write-Output "Testing lint passed with warnings."
  }
  foreach ($issue in $warnings) {
    Write-Output ("- [WARNING] {0} :: {1} :: {2}" -f $issue.file, $issue.section, $issue.message)
  }
}

exit $exitCode
