[CmdletBinding()]
param(
    [ValidateSet('Codex','CodeBuddy','WorkBuddy','Cursor','ClaudeDesktop','VSCode')]
    [string[]]$Client = @('Codex','CodeBuddy','WorkBuddy','Cursor','ClaudeDesktop'),
    [string]$InstallDir = "$env:LOCALAPPDATA\Zhiyisoft\MMLParser\MCP",
    [string]$OfficialSkillRoot = ''
)

$ErrorActionPreference = 'Stop'
$ServerFile = (Get-ChildItem -LiteralPath $PSScriptRoot -Filter '*_MCP_Server_V1.3.8.exe' -File | Select-Object -First 1).Name
$ExpectedSha256 = 'F79B4B59A7BC068F72C37F3364A8FC2E8F87F9CE5FC799F9FCDA8100EFFB3625'
$ServerFile = if ($ServerFile) { $ServerFile } else { 'MMLParser_MCP_Server_V1.3.8.exe' }
$SourceExe = Join-Path $PSScriptRoot $ServerFile
$TargetExe = Join-Path $InstallDir $ServerFile

function Resolve-OfficialSkillRoot {
    $CodexDir = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $HOME '.codex' }
    $Candidates = @(
        $OfficialSkillRoot,
        (Join-Path $CodexDir 'skills\mml-parser-zhiyisoft'),
        (Join-Path $HOME '.workbuddy\skills\mml-parser-zhiyisoft'),
        (Join-Path $HOME '.codebuddy\skills\mml-parser-zhiyisoft'),
        (Join-Path $HOME '.cursor\skills\mml-parser-zhiyisoft')
    ) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
    foreach ($Candidate in $Candidates) {
        $Required = @(
            'SKILL.md',
            'agents\openai.yaml',
            'assets\mml_logo.png',
            'references\protocol.md'
        )
        if (($Required | Where-Object { -not (Test-Path -LiteralPath (Join-Path $Candidate $_) -PathType Leaf) }).Count -eq 0) {
            return (Resolve-Path -LiteralPath $Candidate).Path
        }
    }
    throw 'Official Skill installation was not found. Install it first or pass -OfficialSkillRoot.'
}

$ResolvedSkillRoot = Resolve-OfficialSkillRoot

if (-not (Test-Path -LiteralPath $SourceExe -PathType Leaf)) {
    throw "The package is missing the MCP Server executable: $ServerFile"
}
$ActualSha256 = (Get-FileHash -LiteralPath $SourceExe -Algorithm SHA256).Hash.ToUpperInvariant()
if ($ActualSha256 -ne $ExpectedSha256) {
    throw "MCP Server SHA-256 mismatch. Expected $ExpectedSha256, actual $ActualSha256"
}
if ([System.IO.File]::ReadAllBytes($SourceExe)[0] -ne 0x4D -or [System.IO.File]::ReadAllBytes($SourceExe)[1] -ne 0x5A) {
    throw 'The MCP Server is not a valid Windows PE executable.'
}

New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
$TargetIsCurrent = $false
if (Test-Path -LiteralPath $TargetExe -PathType Leaf) {
    $TargetIsCurrent = ((Get-FileHash -LiteralPath $TargetExe -Algorithm SHA256).Hash.ToUpperInvariant() -eq $ExpectedSha256)
}
if (-not $TargetIsCurrent) {
    Copy-Item -LiteralPath $SourceExe -Destination $TargetExe -Force
}

$SelfTest = & $TargetExe --self-test --official-skill-root $ResolvedSkillRoot | ConvertFrom-Json
if (-not $SelfTest.ok -or -not $SelfTest.official_skill_verified -or $SelfTest.server -ne 'mml-parser-zhiyisoft' -or $SelfTest.version -ne '1.3.8') {
    throw 'The installed MCP Server failed its self-test.'
}

function Set-JsonMcpServer {
    param([Parameter(Mandatory)][string]$Path)
    $Parent = Split-Path -Parent $Path
    New-Item -ItemType Directory -Path $Parent -Force | Out-Null
    if (Test-Path -LiteralPath $Path) {
        Copy-Item -LiteralPath $Path -Destination "$Path.backup-$(Get-Date -Format 'yyyyMMddHHmmss')" -Force
        $Raw = Get-Content -LiteralPath $Path -Raw -Encoding UTF8
        $Config = if ([string]::IsNullOrWhiteSpace($Raw)) { [pscustomobject]@{} } else { $Raw | ConvertFrom-Json }
    } else {
        $Config = [pscustomobject]@{}
    }
    if (-not $Config.PSObject.Properties['mcpServers']) {
        $Config | Add-Member -NotePropertyName mcpServers -NotePropertyValue ([pscustomobject]@{})
    }
    $Entry = [pscustomobject]@{ type = 'stdio'; command = $TargetExe; args = @('--stdio','--official-skill-root',$ResolvedSkillRoot); timeout = 120000 }
    if ($Config.mcpServers.PSObject.Properties['mml-parser-zhiyisoft']) {
        $Config.mcpServers.'mml-parser-zhiyisoft' = $Entry
    } else {
        $Config.mcpServers | Add-Member -NotePropertyName 'mml-parser-zhiyisoft' -NotePropertyValue $Entry
    }
    $Config | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $Path -Encoding UTF8
}

if ($Client -contains 'Codex') {
    $CodexDir = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $HOME '.codex' }
    New-Item -ItemType Directory -Path $CodexDir -Force | Out-Null
    $CodexConfig = Join-Path $CodexDir 'config.toml'
    if (Test-Path -LiteralPath $CodexConfig) {
        Copy-Item -LiteralPath $CodexConfig -Destination "$CodexConfig.backup-$(Get-Date -Format 'yyyyMMddHHmmss')" -Force
    }
    $Toml = if (Test-Path -LiteralPath $CodexConfig) { Get-Content -LiteralPath $CodexConfig -Raw -Encoding UTF8 } else { '' }
    $Block = @"
[mcp_servers.mml_parser_zhiyisoft]
command = '$($TargetExe.Replace("'", "''"))'
args = ['--stdio', '--official-skill-root', '$($ResolvedSkillRoot.Replace("'", "''"))']
startup_timeout_sec = 30
tool_timeout_sec = 120
default_tools_approval_mode = 'prompt'
"@
    $Pattern = '(?ms)^\[mcp_servers\.mml_parser_zhiyisoft\]\s*.*?(?=^\[|\z)'
    $Toml = if ([regex]::IsMatch($Toml, $Pattern)) { [regex]::Replace($Toml, $Pattern, $Block.Trim() + "`r`n") } else { $Toml.TrimEnd() + "`r`n`r`n" + $Block.Trim() + "`r`n" }
    Set-Content -LiteralPath $CodexConfig -Value $Toml -Encoding UTF8
}
if ($Client -contains 'WorkBuddy') {
    Set-JsonMcpServer (Join-Path $HOME '.workbuddy\mcp.json')
}
if ($Client -contains 'CodeBuddy') {
    Set-JsonMcpServer (Join-Path $HOME '.codebuddy\mcp.json')
}
if ($Client -contains 'Cursor') {
    Set-JsonMcpServer (Join-Path $HOME '.cursor\mcp.json')
}
if ($Client -contains 'ClaudeDesktop') {
    Set-JsonMcpServer (Join-Path $env:APPDATA 'Claude\claude_desktop_config.json')
}
if ($Client -contains 'VSCode') {
    $Code = Get-Command code -ErrorAction SilentlyContinue
    if (-not $Code) { throw 'VS Code command not found. Use configs\vscode.mcp.json instead.' }
    $Definition = [pscustomobject]@{ name = 'mml-parser-zhiyisoft'; type = 'stdio'; command = $TargetExe; args = @('--stdio','--official-skill-root',$ResolvedSkillRoot) } | ConvertTo-Json -Compress
    & $Code.Source --add-mcp $Definition
    if ($LASTEXITCODE -ne 0) { throw 'Failed to update the VS Code MCP configuration.' }
}

Write-Host "Installed: $TargetExe" -ForegroundColor Green
Write-Host "Verified official Skill: $ResolvedSkillRoot" -ForegroundColor Green
Write-Host "Configured clients: $($Client -join ', ')"
Write-Host 'Restart each client and verify that nine mml_* tools are available.'
