param(
  [string]$Distro = "Ubuntu",
  [string]$InstallRoot = "$env:LOCALAPPDATA\ResearchPadAgent",
  [switch]$SkipWslInstall,
  [switch]$NoStart
)

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

$CodeServerVersion = "4.96.4"
$TaskName = "ResearchPadAgent"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path

function Write-Step($Message) {
  Write-Host ""
  Write-Host "==> $Message" -ForegroundColor Cyan
}

function Write-Ok($Message) {
  Write-Host "OK  $Message" -ForegroundColor Green
}

function Write-Warn($Message) {
  Write-Host "WARN $Message" -ForegroundColor Yellow
}

function Resolve-PayloadRoot {
  $packagePayload = Join-Path $ScriptDir "payload"
  if (Test-Path $packagePayload) { return (Resolve-Path $packagePayload).Path }

  $repoRoot = (Resolve-Path (Join-Path $ScriptDir "..\..")).Path
  if (Test-Path (Join-Path $repoRoot "scripts\proxy-httpproxy.js")) { return $repoRoot }

  throw "Cannot find ResearchPad Agent payload. Expected payload next to install.ps1 or repo root two levels up."
}

function Convert-ToWslPath([string]$Path) {
  $full = [System.IO.Path]::GetFullPath($Path)
  $drive = $full.Substring(0, 1).ToLowerInvariant()
  $rest = $full.Substring(2).Replace("\", "/")
  return "/mnt/$drive$rest"
}

function Find-Node {
  $cmd = Get-Command node.exe -ErrorAction SilentlyContinue
  if ($cmd) { return $cmd.Source }
  return $null
}

function Ensure-Node {
  $node = Find-Node
  if ($node) {
    Write-Ok "Node.js: $node"
    return $node
  }

  Write-Warn "Node.js not found. Trying winget install OpenJS.NodeJS.LTS..."
  $winget = Get-Command winget.exe -ErrorAction SilentlyContinue
  if (-not $winget) {
    throw "Node.js is required. Install Node.js LTS first, then rerun this installer."
  }

  & winget install --id OpenJS.NodeJS.LTS -e --silent --accept-source-agreements --accept-package-agreements
  $node = Find-Node
  if (-not $node) {
    throw "Node.js installation finished but node.exe is still not available in PATH. Reopen PowerShell and rerun install.ps1."
  }
  Write-Ok "Node.js installed: $node"
  return $node
}

function Ensure-Wsl([string]$Name) {
  $wsl = Get-Command wsl.exe -ErrorAction SilentlyContinue
  if (-not $wsl) {
    throw "WSL is not available. Enable WSL2 in Windows features, reboot, then rerun install.ps1."
  }

  $distros = @()
  try {
    $distros = (& wsl.exe -l -q 2>$null) | ForEach-Object { ($_ -replace "`0", "").Trim() } | Where-Object { $_ }
  } catch {
    $distros = @()
  }

  if ($distros -contains $Name) {
    Write-Ok "WSL distro: $Name"
    return
  }

  if ($SkipWslInstall) {
    throw "WSL distro '$Name' is not installed."
  }

  Write-Warn "WSL distro '$Name' not found. Starting WSL install."
  & wsl.exe --install -d $Name
  throw "WSL installation was started. Finish the Ubuntu first-run setup, reboot if Windows asks, then rerun install.ps1."
}

function Export-PemBlock([string]$Label, [byte[]]$Bytes) {
  $base64 = [Convert]::ToBase64String($Bytes)
  $lines = for ($i = 0; $i -lt $base64.Length; $i += 64) {
    $base64.Substring($i, [Math]::Min(64, $base64.Length - $i))
  }
  return "-----BEGIN $Label-----`n$($lines -join "`n")`n-----END $Label-----`n"
}

function Ensure-TlsCertificate {
  $tlsDir = Join-Path $env:USERPROFILE ".researchpad-agent\tls"
  $certPem = Join-Path $tlsDir "cert.pem"
  $keyPem = Join-Path $tlsDir "key.pem"
  New-Item -ItemType Directory -Force -Path $tlsDir | Out-Null

  if ((Test-Path $certPem) -and (Test-Path $keyPem)) {
    Write-Ok "TLS certificate exists: $tlsDir"
    return
  }

  Write-Step "Create and trust local HTTPS certificate"
  $cert = New-SelfSignedCertificate `
    -DnsName "local.researchpad.org", "agent.researchpad.org", "localhost" `
    -CertStoreLocation "Cert:\CurrentUser\My" `
    -KeyAlgorithm RSA `
    -KeyLength 2048 `
    -HashAlgorithm SHA256 `
    -KeyExportPolicy Exportable `
    -NotAfter (Get-Date).AddYears(10) `
    -TextExtension @("2.5.29.17={text}dns=local.researchpad.org&dns=agent.researchpad.org&dns=localhost&ipaddress=127.0.0.1")

  $certBytes = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
  Set-Content -Path $certPem -Value (Export-PemBlock "CERTIFICATE" $certBytes) -Encoding ascii

  $rsa = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
  if (-not $rsa) { throw "Failed to export private key from generated certificate." }
  $keyBytes = $rsa.ExportPkcs8PrivateKey()
  Set-Content -Path $keyPem -Value (Export-PemBlock "PRIVATE KEY" $keyBytes) -Encoding ascii

  $cerPath = Join-Path $tlsDir "cert.cer"
  Export-Certificate -Cert $cert -FilePath $cerPath | Out-Null
  Import-Certificate -FilePath $cerPath -CertStoreLocation "Cert:\CurrentUser\Root" | Out-Null
  Write-Ok "TLS certificate created and trusted for current user"
}

function Copy-IfExists([string]$Source, [string]$Destination) {
  if (Test-Path $Source) {
    New-Item -ItemType Directory -Force -Path (Split-Path -Parent $Destination) | Out-Null
    Copy-Item -Force -Path $Source -Destination $Destination
  }
}

function Install-WindowsPayload([string]$PayloadRoot) {
  Write-Step "Install Windows-side files"
  New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
  New-Item -ItemType Directory -Force -Path (Join-Path $InstallRoot "logs") | Out-Null
  New-Item -ItemType Directory -Force -Path (Join-Path $InstallRoot "extensions") | Out-Null
  New-Item -ItemType Directory -Force -Path (Join-Path $InstallRoot "build\defaults") | Out-Null
  New-Item -ItemType Directory -Force -Path (Join-Path $InstallRoot "wsl") | Out-Null

  Copy-IfExists (Join-Path $PayloadRoot "scripts\proxy-httpproxy.js") (Join-Path $InstallRoot "proxy-httpproxy.js")
  Copy-IfExists (Join-Path $PayloadRoot "scripts\set-access-key.js") (Join-Path $InstallRoot "set-access-key.js")
  Copy-IfExists (Join-Path $PayloadRoot "scripts\apply-runtime-fixes.js") (Join-Path $InstallRoot "apply-runtime-fixes.js")
  Copy-IfExists (Join-Path $PayloadRoot "build\defaults\settings.json") (Join-Path $InstallRoot "build\defaults\settings.json")
  Copy-IfExists (Join-Path $PayloadRoot "build\defaults\roo-code-settings.json") (Join-Path $InstallRoot "build\defaults\roo-code-settings.json")

  Copy-IfExists (Join-Path $ScriptDir "start-agent.ps1") (Join-Path $InstallRoot "start-agent.ps1")
  Copy-IfExists (Join-Path $ScriptDir "stop-agent.ps1") (Join-Path $InstallRoot "stop-agent.ps1")
  Copy-IfExists (Join-Path $ScriptDir "README-Windows.md") (Join-Path $InstallRoot "README-Windows.md")
  Copy-IfExists (Join-Path $ScriptDir "wsl\install-wsl-agent.sh") (Join-Path $InstallRoot "wsl\install-wsl-agent.sh")
  Copy-IfExists (Join-Path $ScriptDir "wsl\start-wsl-agent.sh") (Join-Path $InstallRoot "wsl\start-wsl-agent.sh")

  $rooVsix = Get-ChildItem -Path (Join-Path $PayloadRoot "extensions\bundled-vsix") -Filter "roo-code-*.vsix" -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1
  if ($rooVsix) { Copy-Item -Force $rooVsix.FullName (Join-Path $InstallRoot "extensions\$($rooVsix.Name)") }

  $zhVsix = Get-ChildItem -Path (Join-Path $PayloadRoot "extensions\bundled-vsix") -Filter "chinese-language-pack-*.vsix" -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1
  if ($zhVsix) { Copy-Item -Force $zhVsix.FullName (Join-Path $InstallRoot "extensions\$($zhVsix.Name)") }

  $rpVsix = Get-ChildItem -Path (Join-Path $PayloadRoot "extensions\researchpad-agent-extension") -Filter "researchpad-agent-extension-*.vsix" -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1
  if ($rpVsix) { Copy-Item -Force $rpVsix.FullName (Join-Path $InstallRoot "extensions\$($rpVsix.Name)") }

  Write-Ok "Windows payload installed: $InstallRoot"
}

function Install-NodeDependencies([string]$NodePath) {
  Write-Step "Install Windows proxy dependency"
  $npm = Join-Path (Split-Path -Parent $NodePath) "npm.cmd"
  if (-not (Test-Path $npm)) {
    $npmCmd = Get-Command npm.cmd -ErrorAction SilentlyContinue
    if ($npmCmd) { $npm = $npmCmd.Source }
  }
  if (-not (Test-Path $npm)) { throw "npm.cmd not found." }

  Push-Location $InstallRoot
  try {
    if (-not (Test-Path (Join-Path $InstallRoot "package.json"))) {
      Set-Content -Path (Join-Path $InstallRoot "package.json") -Encoding utf8 -Value '{"private":true,"dependencies":{"http-proxy":"^1.18.1"}}'
    }
    & $npm install --silent
  } finally {
    Pop-Location
  }
  Write-Ok "http-proxy installed"
}

function Install-WslBackend {
  Write-Step "Install WSL backend"
  $installScript = Join-Path $InstallRoot "wsl\install-wsl-agent.sh"
  if (-not (Test-Path $installScript)) { throw "Missing WSL install script: $installScript" }
  $installScriptWsl = Convert-ToWslPath $installScript
  $installRootWsl = Convert-ToWslPath $InstallRoot
  & wsl.exe -d $Distro -- bash "$installScriptWsl" "$installRootWsl" "$CodeServerVersion"
  if ($LASTEXITCODE -ne 0) { throw "WSL backend install failed." }
  Write-Ok "WSL backend installed"
}

function Register-StartupTask {
  Write-Step "Register login startup task"
  $startScript = Join-Path $InstallRoot "start-agent.ps1"
  $argument = "-NoProfile -ExecutionPolicy Bypass -File `"$startScript`" -Distro `"$Distro`""
  $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument $argument
  $trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
  $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DisallowStartIfOnBatteries:$false -ExecutionTimeLimit (New-TimeSpan -Hours 0)
  Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Settings $settings -Description "Start ResearchPad Agent local services" -Force | Out-Null
  Write-Ok "Scheduled task registered: $TaskName"
}

Write-Host "ResearchPad Agent Windows installer preview" -ForegroundColor White
Write-Host "Install root: $InstallRoot"

$payloadRoot = Resolve-PayloadRoot
$node = Ensure-Node
Ensure-Wsl $Distro
Install-WindowsPayload $payloadRoot
Install-NodeDependencies $node
Ensure-TlsCertificate
Install-WslBackend
Register-StartupTask

if (-not $NoStart) {
  Write-Step "Start ResearchPad Agent"
  & powershell.exe -NoProfile -ExecutionPolicy Bypass -File (Join-Path $InstallRoot "start-agent.ps1") -Distro $Distro
}

Write-Host ""
Write-Host "ResearchPad Agent Windows preview install completed." -ForegroundColor Green
Write-Host "Open https://agent.researchpad.org/ and complete first pairing in the local IDE."
