#requires -Version 7.0
<#
.SYNOPSIS
Сборка MCP-сервера для dev-цикла: с диагностикой блокировки bin живыми сессиями.

.DESCRIPTION
Три режима, по возрастанию стоимости:

  -Check   компиляция мимо bin (сервер можно не останавливать) — «оно вообще собирается?»
  (по умолчанию) полная сборка в bin + юнит-тесты — новый бинарь для теневого запуска
  -NoTest  то же без юнит-тестов

Каталог bin занят, пока хотя бы одна сессия MCP запущена ПРЯМО из него (см. .mcp.json).
С tools/dev/launch-dev-mcp.ps1 сервер работает из теневой копии, и bin свободен всегда.

.EXAMPLE
pwsh -NoProfile -File tools/dev/rebuild-mcp.ps1 -Check
.EXAMPLE
pwsh -NoProfile -File tools/dev/rebuild-mcp.ps1
#>
[CmdletBinding()]
param(
    [switch] $Check,
    [switch] $NoTest
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$repo = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$binDir = Join-Path $repo 'src\Kompas.Mcp.Host\bin\x64\Release\net8.0-windows'

function Get-BlockingProcess {
    param([Parameter(Mandatory)] [string] $Directory)

    $target = $Directory.TrimEnd('\').ToLowerInvariant()
    $found = @()
    foreach ($p in (Get-Process -Name 'kompas-mcp' -ErrorAction SilentlyContinue)) {
        try {
            if (-not $p.Path) { continue }
            if ((Split-Path -Parent $p.Path).TrimEnd('\').ToLowerInvariant() -eq $target) { $found += $p }
        }
        catch {
            # .Path недоступен (чужой пользователь / процесс уже умер) — считать такой
            # процесс блокирующим нельзя, но и молчать нехорошо: сборка ниже всё равно
            # покажет настоящего держателя файла в тексте MSB3027.
            Write-Verbose "не удалось прочитать путь процесса $($p.Id): $($_.Exception.Message)"
        }
    }
    return $found
}

if ($Check) {
    # Стабильный (не случайный) каталог — чтобы работала инкрементальная сборка.
    # Перенаправляем ТОЛЬКО BaseOutputPath: если увести ещё и BaseIntermediateOutputPath,
    # старый obj\ в дереве остаётся видимым для glob'а и даёт CS0579 «Повторяющийся
    # атрибут» на сгенерированном AssemblyInfo. Обратная сторона — obj\ остаётся общим
    # с обычной сборкой, поэтому два параллельных прогона топчут инкрементальный кэш
    # друг друга (безопасно, но лишняя перекомпиляция).
    $stamp = [System.BitConverter]::ToString(
        [System.Security.Cryptography.SHA256]::HashData(
            [System.Text.Encoding]::UTF8.GetBytes($repo.ToLowerInvariant()))[0..3]).Replace('-', '')
    $out = Join-Path ([System.IO.Path]::GetTempPath()) "kompas-mcp-check\$stamp\"

    Write-Host "Проверка компиляции (bin не трогаем, выход → $out)" -ForegroundColor Cyan
    dotnet build -c Release -p:BaseOutputPath=$out
    exit $LASTEXITCODE
}

# @() обязательно: единственный найденный процесс вернулся бы скаляром, и .Count под
# Set-StrictMode падает — та же ловушка, что в лаунчере с Get-ChildItem.
$blocking = @(Get-BlockingProcess -Directory $binDir)
if ($blocking.Count -gt 0) {
    Write-Host 'Сборка невозможна: bin занят живыми сессиями MCP.' -ForegroundColor Red
    foreach ($p in $blocking) {
        Write-Host ("  PID {0}, запущен {1}" -f $p.Id, $p.StartTime.ToString('HH:mm:ss'))
    }
    Write-Host ''
    Write-Host 'Варианты:' -ForegroundColor Yellow
    Write-Host '  1. Перевести .mcp.json на tools/dev/launch-dev-mcp.ps1 (теневой запуск) — тогда'
    Write-Host '     bin свободен всегда, и эта ситуация больше не повторится.'
    Write-Host '  2. Закрыть все сессии Claude Code с этим MCP и повторить.'
    Write-Host '  3. Разовая проверка компиляции без остановки сервера: -Check'
    exit 2
}

Write-Host 'Сборка (Release)…' -ForegroundColor Cyan
dotnet build -c Release
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

if (-not $NoTest) {
    Write-Host 'Юнит-тесты…' -ForegroundColor Cyan
    dotnet test --filter 'Category=Unit' --nologo
    if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}

Import-Module (Join-Path $PSScriptRoot 'KompasMcpDev.psm1') -Force
$fp = Get-KompasMcpBuildFingerprint -Directory $binDir

Write-Host ''
Write-Host "Готово. Отпечаток сборки: $fp" -ForegroundColor Green
Write-Host 'Сервер подхватит её при следующем запуске процесса MCP:'
Write-Host '  /mcp → переподключить kompas (если клиент умеет), иначе — перезапуск сессии.'
Write-Host 'После переподключения: kompas_status покажет живое соединение; эскизы по id теряются.'
