[CmdletBinding()]
param(
  [string]$NasAddress = '172.22.0.222',
  [int]$Port = 8790
)

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

# Windows PowerShell 5.1 does not necessarily autoload this assembly, unlike
# newer PowerShell editions. Load it before resolving HttpClientHandler.
Add-Type -AssemblyName System.Net.Http

if ($Port -lt 1 -or $Port -gt 65535) {
  throw "Port must be between 1 and 65535: $Port"
}

$null = [Net.IPAddress]::Parse($NasAddress)
$docker = (Get-Command docker -CommandType Application -ErrorAction Stop | Select-Object -First 1).Path
if ([string]::IsNullOrWhiteSpace($docker)) {
  throw 'Docker CLI executable could not be resolved.'
}

# The token is read inside the already-running connector installation. It is
# never written to disk by this script and never printed to the console.
$token = $null
$body = $null
$handler = $null
$client = $null
$content = $null
$response = $null
try {
  $token = (& $docker exec dc-amd-connector node -e "process.stdout.write(require('fs').readFileSync('/run/dc-amd-secrets/connector-access','utf8').trim())").Trim()
  if ($LASTEXITCODE -ne 0) {
    throw 'Unable to read the local connector access value. Check that dc-amd-connector is running.'
  }
  if ($token -notmatch '^[A-Za-z0-9_-]{48,256}$') {
    throw 'The local connector access value has an invalid format.'
  }

  $body = '{"connectorAccessToken":"' + $token + '"}'
  $handler = [System.Net.Http.HttpClientHandler]::new()
  # Pair only with the NAS LAN address. Do not use a Windows or VPN proxy for
  # this one-time local handoff.
  $handler.UseProxy = $false
  $client = [System.Net.Http.HttpClient]::new($handler)
  $client.Timeout = [TimeSpan]::FromSeconds(20)
  $content = [System.Net.Http.StringContent]::new($body, [System.Text.Encoding]::UTF8, 'application/json')
  $response = $client.PostAsync("http://$NasAddress`:$Port/api/pair", $content).GetAwaiter().GetResult()
  $responseBody = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult()

  if ([int]$response.StatusCode -ne 201) {
    throw "NAS pairing was rejected (HTTP $([int]$response.StatusCode))."
  }
  $result = $responseBody | ConvertFrom-Json
  if ($result.ok -ne $true -or $result.state -ne 'paired') {
    throw 'NAS pairing returned an unexpected result.'
  }

  Write-Host 'AMD connector paired with NAS. No secret value was displayed.'
}
finally {
  if ($response) { $response.Dispose() }
  if ($content) { $content.Dispose() }
  if ($client) { $client.Dispose() }
  if ($handler) { $handler.Dispose() }
  $body = $null
  $token = $null
  Remove-Variable -Name body -ErrorAction SilentlyContinue
  Remove-Variable -Name token -ErrorAction SilentlyContinue
}
