param(
  [int]$Port = 8000,
  [string]$HostAddress = "127.0.0.1",
  [switch]$NoBrowser
)
$ErrorActionPreference = "Stop"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$BaseDir = Split-Path (Split-Path (Split-Path $ScriptDir -Parent) -Parent) -Parent
$Server = Join-Path $ScriptDir "dashboard_server.py"
$DashboardUrl = "http://$HostAddress`:$Port/Adapters/UI/LiveDashboard/AgentOS_Dashboard.html"

function Find-Python {
  # Prioritize the bundled portable Python runtime included in the workspace first.
  # This bypasses the broken Windows App Store python execution alias.
  $portable = Join-Path $BaseDir "Tools\Python\python.exe"
  if (Test-Path $portable) { return $portable }
  foreach ($candidate in @("python", "py", "python3")) {
    $cmd = Get-Command $candidate -ErrorAction SilentlyContinue
    if ($cmd) { return $cmd.Source }
  }
  throw "No Python launcher found. Install Python or use the embedded AgentOS Python adapter when available."
}

function Test-PortOpen {
  param([string]$HostName, [int]$PortNumber)
  $tcp = New-Object System.Net.Sockets.TcpClient
  try {
    $connection = $tcp.BeginConnect($HostName, $PortNumber, $null, $null)
    $success = $connection.AsyncWaitHandle.WaitOne(700, $false)
    if ($success) { $tcp.EndConnect($connection) }
    return $success
  } catch { return $false }
  finally { $tcp.Close() }
}

function Test-DashboardAlive {
  param([string]$HostName, [int]$PortNumber, [int]$TimeoutSeconds = 4)
  try {
    $status = Invoke-RestMethod -Uri "http://${HostName}:${PortNumber}/api/status" -TimeoutSec $TimeoutSeconds
    return ($null -ne $status.status)
  } catch {
    return $false
  }
}

$python = Find-Python
Write-Host "Starting AgentOS dashboard bridge on http://$HostAddress`:$Port/"
Write-Host "Dashboard: $DashboardUrl"

# Use /api/status (instant, no subprocess calls) instead of /api/openai-codex/status
# (which spawns codex CLI and can take >2s, causing false-positive "stale" detection).
$dashboardAlive = Test-DashboardAlive -HostName $HostAddress -PortNumber $Port -TimeoutSeconds 4

if ($dashboardAlive) {
  Write-Host "Dashboard bridge already running on port $Port." -ForegroundColor Green
} elseif (Test-PortOpen -HostName $HostAddress -PortNumber $Port) {
  # Port is occupied but /api/status failed — something else is on this port.
  Write-Host "Port $Port is occupied by a non-dashboard process. Attempting to free it..." -ForegroundColor Yellow
  $listeners = Get-NetTCPConnection -LocalAddress $HostAddress -LocalPort $Port -State Listen -ErrorAction SilentlyContinue
  foreach ($listener in $listeners) {
    try { Stop-Process -Id $listener.OwningProcess -Force -ErrorAction SilentlyContinue } catch {}
  }
  Start-Sleep -Milliseconds 1000

  Start-Process -FilePath $python -ArgumentList "`"$Server`" --host $HostAddress --port $Port" -WindowStyle Hidden -WorkingDirectory $BaseDir
  $ready = $false
  for ($i = 0; $i -lt 30; $i++) {
    Start-Sleep -Milliseconds 250
    if (Test-DashboardAlive -HostName $HostAddress -PortNumber $Port -TimeoutSeconds 1) { $ready = $true; break }
  }
  if (-not $ready) { throw "Dashboard bridge did not start on $HostAddress`:$Port." }
  Write-Host "AgentOS Dashboard bridge is active." -ForegroundColor Green
} else {
  # Port is free — fresh start.
  Start-Process -FilePath $python -ArgumentList "`"$Server`" --host $HostAddress --port $Port" -WindowStyle Hidden -WorkingDirectory $BaseDir
  $ready = $false
  for ($i = 0; $i -lt 30; $i++) {
    Start-Sleep -Milliseconds 250
    if (Test-DashboardAlive -HostName $HostAddress -PortNumber $Port -TimeoutSeconds 1) { $ready = $true; break }
  }
  if (-not $ready) { throw "Dashboard bridge did not start on $HostAddress`:$Port." }
  Write-Host "AgentOS Dashboard bridge is active." -ForegroundColor Green
}

if (-not $NoBrowser) {
  Start-Process $DashboardUrl
}

Write-Host "Leave this window alone; the bridge runs in the background." -ForegroundColor DarkGray