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 = @()

$securitySpecPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\spec\11-security-design.md"
$currentTaskPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\context\CURRENT_TASK.md"
$verifyMatrixPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\verify-matrix.md"
$evidenceProtocolPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\testing\EVIDENCE_PROTOCOL.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"

$securitySpec = Get-FileContentOrNull -Path $securitySpecPath
$currentTask = Get-FileContentOrNull -Path $currentTaskPath
$verifyMatrix = Get-FileContentOrNull -Path $verifyMatrixPath
$evidenceProtocol = Get-FileContentOrNull -Path $evidenceProtocolPath
$testStrategy = Get-FileContentOrNull -Path $testStrategyPath
$nlCases = Get-FileContentOrNull -Path $nlCasesPath

if ($null -eq $securitySpec) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/spec/11-security-design.md" -Section "file" -Message "缺少安全设计模板。"
}
else {
  if (-not (Test-ContainsAll -Content $securitySpec -Terms @("后端权限校验入口", "输入校验范围", "敏感信息返回、日志、trace、审计中的脱敏策略", "风控 / 风控策略", "## 安全控制清单", "权限校验", "输入校验", "敏感信息脱敏", "防刷 / 风控"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/spec/11-security-design.md" -Section "security-controls" -Message "安全设计模板缺少第12章要求的权限、输入校验、脱敏或风控控制项。"
  }
}

if ($null -eq $currentTask) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/context/CURRENT_TASK.md" -Section "file" -Message "缺少 CURRENT_TASK 模板。"
}
else {
  if (-not (Test-ContainsAll -Content $currentTask -Terms @("权限校验边界", "输入校验边界", "敏感信息脱敏策略", "风控 / 限流策略"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/context/CURRENT_TASK.md" -Section "security-fields" -Message "CURRENT_TASK 模板缺少第12章要求的安全决策字段。"
  }
}

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 "security-checks" -Message "验证矩阵模板缺少第12章要求的权限、输入校验、脱敏或风控检查。"
  }
}

if ($null -eq $evidenceProtocol) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/EVIDENCE_PROTOCOL.md" -Section "file" -Message "缺少证据协议模板。"
}
else {
  if (-not (Test-ContainsAll -Content $evidenceProtocol -Terms @("validation_failure_sample", "redaction_check", "rate_limit_observation"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/EVIDENCE_PROTOCOL.md" -Section "security-evidence" -Message "证据协议模板还没有覆盖第12章所需的安全证据类型。"
  }
}

if ($null -eq $testStrategy) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/TEST_STRATEGY.md" -Section "file" -Message "缺少测试策略模板。"
}
else {
  if (-not (Test-ContainsAll -Content $testStrategy -Terms @("权限、状态机、异步链路、外部系统、金额库存、文件处理和安全需求必须按风险路径加量", "权限失败只断言 `403`，没有验证目标数据未变化、响应未泄露和缓存未污染"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/TEST_STRATEGY.md" -Section "security-coverage" -Message "测试策略模板还没有完整覆盖第12章要求的安全测试口径。"
  }
}

if ($null -eq $nlCases) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/NATURAL_LANGUAGE_TEST_CASES.md" -Section "file" -Message "缺少自然语言测试用例模板。"
}
else {
  if (-not (Test-ContainsAll -Content $nlCases -Terms @("| 安全 / 高风险需求 | 6 起 |", "敏感信息不泄露", "权限拒绝无副作用"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/testing/NATURAL_LANGUAGE_TEST_CASES.md" -Section "security-cases" -Message "自然语言测试用例模板还没有完整映射第12章高风险安全用例。"
  }
}

$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 "Security lint passed."
  exit 0
}

if ($errors.Count -gt 0) {
  Write-Output "Security 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 "Security lint passed with warnings."
  }
  foreach ($issue in $warnings) {
    Write-Output ("- [WARNING] {0} :: {1} :: {2}" -f $issue.file, $issue.section, $issue.message)
  }
}

exit $exitCode
