#!/usr/bin/env pwsh
<#
.SYNOPSIS
    Check that all action enums have corresponding CLI commands registered.

.DESCRIPTION
    Auto-discovers action enums from ToolActions.cs and verifies each has a CLI command
    registered in Program.cs. Fails if any enums are missing CLI commands.

.EXAMPLE
    .\scripts\check-cli-coverage.ps1

.NOTES
    Added to pre-commit to prevent CLI parity gaps (like DataModelRelAction missing).
#>

param(
    [switch]$Verbose
)

$ErrorActionPreference = "Stop"
$rootDir = Split-Path -Parent $PSScriptRoot

Write-Host "CLI Command Coverage Check" -ForegroundColor Cyan
Write-Host "==============================" -ForegroundColor Cyan
Write-Host ""

$toolActionsPath = Join-Path $rootDir "src\ExcelMcp.Core\Models\Actions\ToolActions.cs"
$programPath = Join-Path $rootDir "src\ExcelMcp.CLI\Program.cs"

if (-not (Test-Path $toolActionsPath)) {
    Write-Host "ToolActions.cs not found: $toolActionsPath" -ForegroundColor Red
    exit 1
}

if (-not (Test-Path $programPath)) {
    Write-Host "Program.cs not found: $programPath" -ForegroundColor Red
    exit 1
}

# Discover all action enums from ToolActions.cs
$toolActionsContent = Get-Content $toolActionsPath -Raw
$enumPattern = "public\s+enum\s+(\w+Action)\s*\{"
$enumMatches = [regex]::Matches($toolActionsContent, $enumPattern)

$allEnums = @()
foreach ($match in $enumMatches) {
    $allEnums += $match.Groups[1].Value
}

Write-Host "Found $($allEnums.Count) action enums in ToolActions.cs" -ForegroundColor Gray

# Map enum names to expected CLI command names
# Pattern: PowerQueryAction -> powerquery, DataModelRelAction -> datamodelrel
function Get-ExpectedCliCommand {
    param([string]$EnumName)

    # Remove 'Action' suffix and convert to lowercase
    $baseName = $EnumName -replace 'Action$', ''
    return $baseName.ToLowerInvariant()
}

# Sub-tool enums that share CLI commands with parent tools (no separate CLI command needed)
$subToolEnums = @{
    # Range sub-tools share 'range' command
    "RangeEditAction" = "range"
    "RangeFormatAction" = "range"
    "RangeLinkAction" = "range"

    # Worksheet sub-tools share 'sheet' command
    "WorksheetStyleAction" = "sheet"

    # PivotTable sub-tools share 'pivottable' command
    "PivotTableFieldAction" = "pivottable"
    "PivotTableCalcAction" = "pivottable"
    "SlicerAction" = "pivottable"  # Slicer is exposed via pivottable and table commands

    # Table sub-tools share 'table' command
    "TableColumnAction" = "table"
}

# Special naming exceptions (enum name doesn't match CLI command name)
$namingExceptions = @{
    "WorksheetAction" = "sheet"
    "ConditionalFormatAction" = "conditionalformat"
}

# MCP-specific enums that have no CLI equivalent (handled differently in CLI)
$mcpOnlyEnums = @(
    "FileAction"  # CLI uses session subcommands (session create/open/close/save) instead
)


# Read Program.cs and find registered commands
$programContent = Get-Content $programPath -Raw

# Extract registered CLI commands: config.AddCommand<*Command>("commandname")
$commandPattern = 'config\.AddCommand<\w+Command>\("(\w+)"\)'
$commandMatches = [regex]::Matches($programContent, $commandPattern)

$registeredCommands = @()
foreach ($match in $commandMatches) {
    $registeredCommands += $match.Groups[1].Value.ToLowerInvariant()
}

Write-Host "Found $($registeredCommands.Count) CLI commands registered in Program.cs" -ForegroundColor Gray
Write-Host ""

# Check each enum has a CLI command
$missingCommands = @()
$coveredEnums = @()

foreach ($enum in $allEnums) {
    # Skip MCP-only enums (no CLI equivalent by design)
    if ($mcpOnlyEnums -contains $enum) {
        if ($Verbose) {
            Write-Host "$enum -> (MCP-only, no CLI equivalent)" -ForegroundColor Gray
        }
        continue
    }

    # Check if this is a sub-tool enum
    if ($subToolEnums.ContainsKey($enum)) {
        $expectedCommand = $subToolEnums[$enum]
        if ($registeredCommands -contains $expectedCommand) {
            $coveredEnums += $enum
            if ($Verbose) {
                Write-Host "$enum -> $expectedCommand (sub-tool)" -ForegroundColor Green
            }
        } else {
            $missingCommands += @{ Enum = $enum; Expected = $expectedCommand; Reason = "sub-tool parent missing" }
        }
        continue
    }

    # Check naming exceptions
    if ($namingExceptions.ContainsKey($enum)) {
        $expectedCommand = $namingExceptions[$enum]
    } else {
        $expectedCommand = Get-ExpectedCliCommand -EnumName $enum
    }

    if ($registeredCommands -contains $expectedCommand) {
        $coveredEnums += $enum
        if ($Verbose) {
            Write-Host "$enum -> $expectedCommand" -ForegroundColor Green
        }
    } else {
        $missingCommands += @{ Enum = $enum; Expected = $expectedCommand; Reason = "no CLI command" }
    }
}

# Report results
if ($missingCommands.Count -gt 0) {
    Write-Host "MISSING CLI COMMANDS DETECTED!" -ForegroundColor Red
    Write-Host ""

    foreach ($missing in $missingCommands) {
        Write-Host "   $($missing.Enum) -> expected CLI command: '$($missing.Expected)'" -ForegroundColor Yellow
    }

    Write-Host ""
    Write-Host "Action Required:" -ForegroundColor Yellow
    Write-Host "  1. Create Command class: src/ExcelMcp.CLI/Commands/<Name>Command.cs" -ForegroundColor Yellow
    Write-Host "  2. Register in Program.cs: config.AddCommand<*Command>(""name"")" -ForegroundColor Yellow
    Write-Host "  3. Or add to subToolEnums/namingExceptions in this script if intentional" -ForegroundColor Yellow
    Write-Host ""

    exit 1
}

Write-Host "All $($allEnums.Count) action enums have CLI commands!" -ForegroundColor Green
Write-Host "   Covered: $($coveredEnums.Count) (including $($subToolEnums.Count) sub-tool enums)" -ForegroundColor Gray
exit 0
