param(
  [switch]$FrontendOnly,
  [switch]$BackendOnly,
  [switch]$AdminOnly,
  [switch]$McpOnly,
  [switch]$WithMcp
)

$ErrorActionPreference = "Stop"

$repoRoot = Split-Path -Parent $MyInvocation.MyCommand.Path

if (@($FrontendOnly, $BackendOnly, $AdminOnly, $McpOnly).Where({ $_ }).Count -gt 1) {
  throw "Use only one of -FrontendOnly, -BackendOnly, -AdminOnly, or -McpOnly."
}

function Stop-RepoShells {
  param(
    [string[]]$CommandPatterns
  )

  $shells = Get-CimInstance Win32_Process | Where-Object {
    $commandLine = $_.CommandLine
    ($_.Name -in @("powershell.exe", "pwsh.exe")) -and
    $_.CommandLine -and
    $commandLine.Contains($repoRoot) -and
    ($CommandPatterns | Where-Object { $commandLine.Contains($_) }).Count -gt 0
  }

  foreach ($shell in $shells) {
    try {
      Stop-Process -Id $shell.ProcessId -Force -ErrorAction Stop
      Write-Host "[stop] Closed matching shell (PID $($shell.ProcessId))." -ForegroundColor Yellow
    }
    catch {
      Write-Warning "[stop] Failed to close matching shell (PID $($shell.ProcessId)): $($_.Exception.Message)"
    }
  }
}

function Stop-PortOwner {
  param(
    [int]$Port,
    [string]$Label
  )

  $connections = Get-NetTCPConnection -LocalPort $Port -ErrorAction SilentlyContinue |
    Select-Object -ExpandProperty OwningProcess -Unique

  if (-not $connections) {
    Write-Host "[stop] No process is listening on port $Port ($Label)." -ForegroundColor DarkGray
    return
  }

  foreach ($processId in $connections) {
    if ($processId -le 0 -or $processId -eq $PID) {
      continue
    }

    try {
      Stop-Process -Id $processId -Force -ErrorAction Stop
      Write-Host "[stop] Stopped $Label on port $Port (PID $processId)." -ForegroundColor Yellow
    }
    catch {
      Write-Warning "[stop] Failed to stop $Label on port $Port (PID $processId): $($_.Exception.Message)"
    }
  }
}

function Stop-Frontend {
  Stop-RepoShells -CommandPatterns @("start-frontend.ps1", "dev.ps1", "-Only frontend")
  Stop-PortOwner -Port 4321 -Label "frontend"
}

function Stop-Backend {
  Stop-RepoShells -CommandPatterns @("start-backend.ps1", "dev.ps1", "-Only backend")
  Stop-PortOwner -Port 5150 -Label "backend"
}

function Stop-Admin {
  Stop-RepoShells -CommandPatterns @("start-admin.ps1", "dev.ps1", "-Only admin")
  Stop-PortOwner -Port 4322 -Label "admin"
}

function Stop-Mcp {
  Stop-RepoShells -CommandPatterns @("start-mcp.ps1", "dev.ps1", "-Only mcp")
  Stop-PortOwner -Port 5151 -Label "MCP"
}

if ($FrontendOnly) {
  Stop-Frontend
  exit 0
}

if ($BackendOnly) {
  Stop-Backend
  exit 0
}

if ($AdminOnly) {
  Stop-Admin
  exit 0
}

if ($McpOnly) {
  Stop-Mcp
  exit 0
}

Write-Host "[stop] Stopping frontend, admin, and backend services..." -ForegroundColor Cyan
Stop-Frontend
Stop-Admin
Stop-Backend

if ($WithMcp) {
  Stop-Mcp
}

Write-Host "[stop] Requested services have been stopped." -ForegroundColor Green
