#Requires -Modules Pester
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: MIT

BeforeAll {
    $script:ScriptPath = (Resolve-Path (Join-Path $PSScriptRoot '../../evals/Build-AgentInventory.ps1')).Path

    function script:New-AgentFile {
        param(
            [Parameter(Mandatory)] [string]$Root,
            [Parameter(Mandatory)] [string]$RelativePath,
            [hashtable]$Frontmatter = @{}
        )

        $full = Join-Path $Root $RelativePath
        $dir  = Split-Path -Parent $full
        if (-not (Test-Path -LiteralPath $dir -PathType Container)) {
            New-Item -ItemType Directory -Path $dir -Force | Out-Null
        }
        $lines = @('---')
        $lines += "name: $([System.IO.Path]::GetFileName($RelativePath) -replace '\.agent\.md$','')"
        $lines += "description: Fixture agent for Build-AgentInventory tests."
        foreach ($key in $Frontmatter.Keys) { $lines += "${key}: $($Frontmatter[$key])" }
        $lines += '---'
        $lines += ''
        $lines += '# Body'
        Set-Content -LiteralPath $full -Value ($lines -join "`n") -Encoding UTF8
    }

    function script:New-MinimalRepo {
        param([Parameter(Mandatory)] [string]$Root)

        # 2 parent agents in standard locations
        New-AgentFile -Root $Root -RelativePath '.github/agents/hve-core/task-planner.agent.md' -Frontmatter @{
            'eval-class' = 'code-author'
            'cost_tier'  = 'medium'
        }
        New-AgentFile -Root $Root -RelativePath '.github/agents/ado/ado-backlog-manager.agent.md'

        # Subagents marked with user-invocable: false MUST be excluded regardless of path.
        New-AgentFile -Root $Root -RelativePath '.github/agents/hve-core/subagents/researcher-subagent.agent.md' -Frontmatter @{
            'user-invocable' = 'false'
        }
        New-AgentFile -Root $Root -RelativePath '.github/agents/security/subagents/codebase-profiler.agent.md' -Frontmatter @{
            'user-invocable' = 'false'
        }
        New-AgentFile -Root $Root -RelativePath '.github/agents/security/subagents/finding-deep-verifier.agent.md' -Frontmatter @{
            'user-invocable' = 'false'
        }
        New-AgentFile -Root $Root -RelativePath '.github/agents/security/subagents/report-generator.agent.md' -Frontmatter @{
            'user-invocable' = 'false'
        }
        New-AgentFile -Root $Root -RelativePath '.github/agents/security/subagents/skill-assessor.agent.md' -Frontmatter @{
            'user-invocable' = 'false'
        }
    }
}

Describe 'Build-AgentInventory.ps1' -Tag 'Unit' {
    BeforeEach {
        $script:TestRoot   = Join-Path $TestDrive ([Guid]::NewGuid().ToString())
        New-Item -ItemType Directory -Path $script:TestRoot -Force | Out-Null
        New-MinimalRepo -Root $script:TestRoot
        $script:OutputPath = Join-Path $script:TestRoot 'evals/agent-behavior/AGENTS.yml'
    }

    Context 'Discovery and frontmatter' {
        BeforeEach {
            & $script:ScriptPath -RepoRoot $script:TestRoot -OutputPath $script:OutputPath -GeneratedAt '2026-05-25T00:00:00Z' 6>$null | Out-Null
            $script:Yaml = [System.IO.File]::ReadAllText($script:OutputPath)
        }

        It 'Writes the inventory to the requested OutputPath' {
            Test-Path -LiteralPath $script:OutputPath | Should -BeTrue
        }

        It 'Emits the generator banner and pinned timestamp' {
            $script:Yaml | Should -Match '# Generated by scripts/evals/Build-AgentInventory\.ps1'
            $script:Yaml | Should -Match '(?m)^generated_at: 2026-05-25T00:00:00Z'
            $script:Yaml | Should -Match "(?m)^generator: 'scripts/evals/Build-AgentInventory\.ps1'"
        }

        It 'Includes both standard parent agents' {
            $script:Yaml | Should -Match '(?m)^\s+- slug: task-planner\s*$'
            $script:Yaml | Should -Match '(?m)^\s+- slug: ado-backlog-manager\s*$'
        }

        It 'Excludes every agent with user-invocable: false regardless of path' {
            $script:Yaml | Should -Not -Match '(?m)^\s+- slug: researcher-subagent\s*$'
            $script:Yaml | Should -Not -Match '(?m)^\s+- slug: codebase-profiler\s*$'
            $script:Yaml | Should -Not -Match '(?m)^\s+- slug: finding-deep-verifier\s*$'
            $script:Yaml | Should -Not -Match '(?m)^\s+- slug: report-generator\s*$'
            $script:Yaml | Should -Not -Match '(?m)^\s+- slug: skill-assessor\s*$'
        }

        It 'Renders frontmatter eval-class and cost_tier when present' {
            $script:Yaml | Should -Match "(?ms)^\s+- slug: task-planner\s*\n\s+path: '\.github/agents/hve-core/task-planner\.agent\.md'\s*\n\s+class: code-author\s*\n\s+cost_tier: medium"
        }

        It 'Defaults class to unknown and cost_tier to light when frontmatter is silent' {
            $script:Yaml | Should -Match "(?ms)^\s+- slug: ado-backlog-manager\s*\n\s+path: '\.github/agents/ado/ado-backlog-manager\.agent\.md'\s*\n\s+class: unknown\s*\n\s+cost_tier: light"
        }

        It 'Sorts entries by slug for deterministic diffs' {
            $slugs = [regex]::Matches($script:Yaml, '(?m)^\s+- slug:\s+(\S+)\s*$') | ForEach-Object { $_.Groups[1].Value }
            $slugs | Should -Be ($slugs | Sort-Object)
        }

        It 'Counts exactly the parent agents (those without user-invocable: false)' {
            $count = ([regex]::Matches($script:Yaml, '(?m)^\s+- slug:\s+')).Count
            $count | Should -Be 2
        }
    }

    Context 'Drift detection' {
        It 'Skips overwriting when the inventory is already up to date' {
            & $script:ScriptPath -RepoRoot $script:TestRoot -OutputPath $script:OutputPath -GeneratedAt '2026-05-25T00:00:00Z' 6>$null | Out-Null
            $firstWrite = (Get-Item -LiteralPath $script:OutputPath).LastWriteTimeUtc
            Start-Sleep -Milliseconds 50
            & $script:ScriptPath -RepoRoot $script:TestRoot -OutputPath $script:OutputPath -GeneratedAt '2099-01-01T00:00:00Z' 6>$null | Out-Null
            (Get-Item -LiteralPath $script:OutputPath).LastWriteTimeUtc | Should -Be $firstWrite
        }

        It 'Overwrites when -Force is supplied even without content drift' {
            & $script:ScriptPath -RepoRoot $script:TestRoot -OutputPath $script:OutputPath -GeneratedAt '2026-05-25T00:00:00Z' 6>$null | Out-Null
            $firstWrite = (Get-Item -LiteralPath $script:OutputPath).LastWriteTimeUtc
            Start-Sleep -Milliseconds 50
            & $script:ScriptPath -RepoRoot $script:TestRoot -OutputPath $script:OutputPath -GeneratedAt '2026-05-25T00:00:00Z' -Force 6>$null | Out-Null
            (Get-Item -LiteralPath $script:OutputPath).LastWriteTimeUtc | Should -BeGreaterThan $firstWrite
        }

        It 'Rewrites when frontmatter content changes' {
            & $script:ScriptPath -RepoRoot $script:TestRoot -OutputPath $script:OutputPath -GeneratedAt '2026-05-25T00:00:00Z' 6>$null | Out-Null
            $before = [System.IO.File]::ReadAllText($script:OutputPath)
            New-AgentFile -Root $script:TestRoot -RelativePath '.github/agents/ado/ado-backlog-manager.agent.md' -Frontmatter @{
                'eval-class' = 'workflow-router'
                'cost_tier'  = 'heavy'
            }
            & $script:ScriptPath -RepoRoot $script:TestRoot -OutputPath $script:OutputPath -GeneratedAt '2026-05-25T00:00:01Z' 6>$null | Out-Null
            $after = [System.IO.File]::ReadAllText($script:OutputPath)
            $after | Should -Not -Be $before
            $after | Should -Match 'class: workflow-router'
            $after | Should -Match 'cost_tier: heavy'
        }
    }
}
