param(
    [string[]]$WatchPaths = @(
        "plugins/1c/agent",
        "core/deploy/docker/1c-agent/compose.yaml",
        "scripts/deploy_onec_agent_test.ps1",
        "scripts/smoke_onec_agent_api.py"
    ),
    [int]$PollSeconds = 5,
    [int]$DebounceSeconds = 2,
    [int]$MaxCycles = 0,
    [switch]$WithTurnCheck,
    [switch]$NoBuild,
    [int]$HealthTimeoutSec = 60,
    [int]$SmokeTimeoutSec = 5
)

$ErrorActionPreference = "Stop"
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoRoot = Split-Path -Parent $scriptDir
$deployScript = Join-Path $scriptDir "deploy_onec_agent_test.ps1"

function Resolve-WatchPath {
    param([string]$Path)
    if ([System.IO.Path]::IsPathRooted($Path)) {
        return $Path
    }
    return Join-Path $repoRoot $Path
}

function Get-Signature {
    param([string[]]$Paths)

    $entries = @()

    foreach ($path in $Paths) {
        $path = Resolve-WatchPath ($path.Trim())
        if (-not (Test-Path -LiteralPath $path)) {
            Write-Host "[warn] path not found: $path"
            continue
        }

        $item = Get-Item -LiteralPath $path
        if ($item.PSIsContainer) {
            $items = Get-ChildItem -LiteralPath $path -Recurse -File -Force |
                Where-Object {
                    $parts = $_.FullName -split "[\\/]"
                    $parts -notcontains ".git" -and
                    $parts -notcontains "__pycache__" -and
                    $parts -notcontains ".pytest_cache" -and
                    $parts -notcontains ".ruff_cache" -and
                    $parts -notcontains ".venv"
                } |
                ForEach-Object {
                    "$($_.FullName)|$($_.Length)|$($_.LastWriteTimeUtc.Ticks)"
                }
            $entries += $items
        } else {
            $parts = $item.FullName -split "[\\/]"
            if (
                $parts -notcontains ".git" -and
                $parts -notcontains "__pycache__" -and
                $parts -notcontains ".pytest_cache" -and
                $parts -notcontains ".ruff_cache" -and
                $parts -notcontains ".venv"
            ) {
                $entries += "$($item.FullName)|$($item.Length)|$($item.LastWriteTimeUtc.Ticks)"
            }
        }
    }

    return @($entries | Sort-Object -Unique)
}

function Invoke-Deploy {
    param()

    $deployArgs = @(
        "-NoProfile",
        "-ExecutionPolicy", "Bypass",
        "-File", $deployScript,
        "-HealthTimeoutSec", $HealthTimeoutSec,
        "-SmokeTimeoutSec", $SmokeTimeoutSec
    )

    if ($WithTurnCheck) {
        $deployArgs += "-WithTurnCheck"
    }
    if ($NoBuild) {
        $deployArgs += "-NoBuild"
    }

    Write-Host "[run] deploy: $deployScript"
    & powershell @deployArgs
    if ($LASTEXITCODE -ne 0) {
        throw "onec-agent deploy script exited with code $LASTEXITCODE"
    }
}

Write-Host "[watch] onec-agent hot-deploy watcher started"
Write-Host "[watch] paths: $($WatchPaths -join ', ')"
Write-Host "[watch] poll=${PollSeconds}s, debounce=${DebounceSeconds}s, no-build=$NoBuild"

$prev = Get-Signature -Paths $WatchPaths
$lastChange = Get-Date

try {
    Invoke-Deploy

    $cycles = 0
    while ($MaxCycles -eq 0 -or $cycles -lt $MaxCycles) {
        Start-Sleep -Seconds $PollSeconds
        $cycles += 1
        $curr = Get-Signature -Paths $WatchPaths
    if ((Compare-Object -ReferenceObject $prev -DifferenceObject $curr -SyncWindow 0).Count -eq 0) {
        continue
    }

        if ((((Get-Date) - $lastChange).TotalSeconds) -lt $DebounceSeconds) {
            continue
        }

        $lastChange = Get-Date
        Write-Host "[watch] change detected, redeploying onec-agent..."
        Invoke-Deploy
        $prev = $curr
    }
} catch {
    Write-Error $_
    throw
}
