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

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
}

function Resolve-FirstExistingPath {
  param([string[]]$Candidates)

  foreach ($candidate in $Candidates) {
    if (Test-Path -LiteralPath $candidate) {
      return $candidate
    }
  }

  return $null
}

$issues = @()

$repoMapPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "docs\ai\repo-map.md"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\context\repo-map.md")
)
$architectureBriefPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot "docs\ai\architecture-brief.md"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\context\architecture-brief.md")
)
$constitutionPath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot ".codex\rules\constitution.md"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\config\rules\constitution.md")
)
$architectureRulePath = Resolve-FirstExistingPath -Candidates @(
  (Join-Path $ProjectRoot ".codex\rules\architecture.md"),
  (Join-Path $ProjectRoot "docs\codex-harness-engineering\templates\config\rules\architecture.md")
)
$featureTemplatePath = Join-Path $ProjectRoot "tools\harness\templates\feature-task-reference.json"
$projectTaskTemplatePath = Join-Path $ProjectRoot "tools\harness\templates\project-task-template.json"
$implementPromptPath = Join-Path $ProjectRoot ".codex\prompts\implement-one-task.md"
$stage1PromptPath = Join-Path $ProjectRoot ".codex\prompts\review-stage1-spec.md"
$stage2PromptPath = Join-Path $ProjectRoot ".codex\prompts\review-stage2-quality.md"

$repoMap = Get-FileContentOrNull -Path $repoMapPath
if ($null -eq $repoMap -or -not (Test-ContainsAll -Content $repoMap -Terms @("architecture-brief.md", "风险入口", "禁改区"))) {
  $issues += New-Issue -Severity "error" -File "docs/ai/repo-map.md" -Section "navigation" -Message "repo-map 缺少架构导航入口或风险入口。"
}

$architectureBrief = Get-FileContentOrNull -Path $architectureBriefPath
if ($null -eq $architectureBrief -or -not (Test-ContainsAll -Content $architectureBrief -Terms @("系统边界", "分层职责", "真相源", "关键约束"))) {
  $issues += New-Issue -Severity "error" -File "docs/ai/architecture-brief.md" -Section "architecture-summary" -Message "architecture-brief 缺少系统边界、分层职责、真相源或关键约束。"
}

$constitution = Get-FileContentOrNull -Path $constitutionPath
if ($null -eq $constitution -or -not (Test-ContainsAll -Content $constitution -Terms @("模块化、契约和可替换性", "Git 与交付治理"))) {
  $issues += New-Issue -Severity "error" -File ".codex/rules/constitution.md" -Section "rules" -Message "constitution 缺少跨项目架构或 Git 治理原则。"
}

$architectureRule = Get-FileContentOrNull -Path $architectureRulePath
if ($null -eq $architectureRule -or -not (Test-ContainsAll -Content $architectureRule -Terms @("owned_paths", "forbidden_paths", "allowed_dependencies", "service/domain/repository"))) {
  $issues += New-Issue -Severity "error" -File ".codex/rules/architecture.md" -Section "rules" -Message "architecture 规则缺少路径所有权、依赖控制或分层边界约束。"
}

$featureTemplate = Get-FileContentOrNull -Path $featureTemplatePath
if ($null -eq $featureTemplate -or -not (Test-ContainsAll -Content $featureTemplate -Terms @('"owned_paths"', '"forbidden_paths"', '"allowed_dependencies"', '"forbidden_implementations"'))) {
  $issues += New-Issue -Severity "error" -File "tools/harness/templates/feature-task-reference.json" -Section "task-fields" -Message "feature-task-reference 缺少架构边界字段。"
}

$projectTaskTemplate = Get-FileContentOrNull -Path $projectTaskTemplatePath
if ($null -eq $projectTaskTemplate -or -not (Test-ContainsAll -Content $projectTaskTemplate -Terms @('"owned_paths"', '"forbidden_paths"', '"allowed_dependencies"'))) {
  $issues += New-Issue -Severity "error" -File "tools/harness/templates/project-task-template.json" -Section "task-fields" -Message "project-task-template 缺少路径或依赖边界字段。"
}

$implementPrompt = Get-FileContentOrNull -Path $implementPromptPath
if ($null -eq $implementPrompt -or -not (Test-ContainsAll -Content $implementPrompt -Terms @("owned_paths", "forbidden_paths", "allowed_dependencies", "service/domain/repository", "输出 BLOCKED"))) {
  $issues += New-Issue -Severity "error" -File ".codex/prompts/implement-one-task.md" -Section "prompt" -Message "implement prompt 缺少架构边界约束。"
}

$stage1Prompt = Get-FileContentOrNull -Path $stage1PromptPath
if ($null -eq $stage1Prompt -or -not (Test-ContainsAll -Content $stage1Prompt -Terms @("owned_paths", "forbidden_paths", "allowed_dependencies", "architecture_gap", "dependency_violation"))) {
  $issues += New-Issue -Severity "error" -File ".codex/prompts/review-stage1-spec.md" -Section "prompt" -Message "Stage 1 prompt 缺少架构边界检查。"
}

$stage2Prompt = Get-FileContentOrNull -Path $stage2PromptPath
if ($null -eq $stage2Prompt -or -not (Test-ContainsAll -Content $stage2Prompt -Terms @("无关 diff", "重复抽象", "边界破坏", "未批准依赖变更"))) {
  $issues += New-Issue -Severity "error" -File ".codex/prompts/review-stage2-quality.md" -Section "prompt" -Message "Stage 2 prompt 缺少边界破坏或依赖变更检查。"
}

$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) { 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 "Architecture boundary lint passed."
  exit 0
}

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

exit $exitCode
