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

$contractsReadmePath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\contracts\README.md"
$openapiPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\contracts\openapi.yaml"
$prismUsagePath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\contracts\prism-usage.md"
$frontendArchitecturePath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\design\frontend-architecture.md"
$apiMapPath = Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\context\API_MAP.md"

$contractsReadme = Get-FileContentOrNull -Path $contractsReadmePath
$openapi = Get-FileContentOrNull -Path $openapiPath
$prismUsage = Get-FileContentOrNull -Path $prismUsagePath
$frontendArchitecture = Get-FileContentOrNull -Path $frontendArchitecturePath
$apiMap = Get-FileContentOrNull -Path $apiMapPath

if ($null -eq $contractsReadme) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/contracts/README.md" -Section "file" -Message "缺少 contract guide。"
}
else {
  if (-not (Test-ContainsAll -Content $contractsReadme -Terms @("请求入口统一通过 generated client", "分页字段默认统一为 `page/pageSize`", "响应结构必须统一", "错误模型必须显式定义", "前端类型优先从 contract 生成"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/contracts/README.md" -Section "contract-rules" -Message "contract guide 缺少第八章要求的统一请求入口、分页字段、响应包装、错误模型或类型生成规则。"
  }
}

if ($null -eq $openapi) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/contracts/openapi.yaml" -Section "file" -Message "缺少 OpenAPI 模板。"
}
else {
  if (-not (Test-ContainsAll -Content $openapi -Terms @("name: page", "name: pageSize", "ErrorResponse", "code:", "message:"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/contracts/openapi.yaml" -Section "api-shape" -Message "OpenAPI 模板缺少分页参数或统一错误结构样例。"
  }
}

if ($null -eq $prismUsage) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/contracts/prism-usage.md" -Section "file" -Message "缺少 Prism 用法模板。"
}
else {
  if (-not (Test-ContainsAll -Content $prismUsage -Terms @("request 参数名是否和 contract 一致", "response 包装层是否和 contract 一致", "错误响应是否都能命中", "generated client"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/contracts/prism-usage.md" -Section "validation-checks" -Message "Prism 用法模板还没有覆盖第八章的接口联调检查点。"
  }
}

if ($null -eq $frontendArchitecture) {
  $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/design/frontend-architecture.md" -Section "file" -Message "缺少 frontend-architecture 模板。"
}
else {
  if (-not (Test-ContainsAll -Content $frontendArchitecture -Terms @("UI 字段必须能追溯到 contract", "页面或组件中不得直接手写 `fetch/axios/baseURL/token/error`", "前端不得再手写一套重复 request/response schema"))) {
    $issues += New-Issue -Severity "error" -File "docs/codex-harness-engineering/templates/design/frontend-architecture.md" -Section "frontend-contract-boundary" -Message "frontend-architecture 模板缺少 contract 追溯或禁止手写请求逻辑的约束。"
  }
}

if ($null -eq $apiMap) {
  $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/context/API_MAP.md" -Section "file" -Message "缺少 API_MAP 模板。"
}
else {
  if (-not (Test-ContainsAll -Content $apiMap -Terms @("统一请求入口", "分页字段约定", "统一响应包装", "错误模型", "contract 位置"))) {
    $issues += New-Issue -Severity "warning" -File "docs/codex-harness-engineering/templates/context/API_MAP.md" -Section "api-convention-fields" -Message "API_MAP 模板缺少统一请求入口、分页字段、响应包装或错误模型字段。"
  }
}

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

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

exit $exitCode
