param(
    [ValidateSet("Debug", "Release")]
    [string]$Configuration = "Release",

    [string]$Server = "",

    [string]$Device = "viewer-001",

    [string]$Target = "host-001",

    [string]$Token = "dev-token",

    [string]$TokenFile = "",

    [string]$DeviceTokenFile = "",

    [string]$ClientConfig = "",

    [ValidateSet("disabled", "optional", "required")]
    [string]$TransportEncryption = "disabled",

    [string]$TransportSecret = "",

    [string]$TransportSecretFile = "",

    [string]$SendFile = "",

    [switch]$TestMode
)

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

function New-SyncVisionViewerClientArguments {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Device,

        [Parameter(Mandatory = $true)]
        [string]$Target,

        [string]$Token = "dev-token",

        [string]$TokenFile = "",

        [string]$DeviceTokenFile = "",

        [string]$ClientConfig = "",

        [ValidateSet("disabled", "optional", "required")]
        [string]$TransportEncryption = "disabled",

        [string]$TransportSecret = "",

        [string]$TransportSecretFile = "",

        [string]$Server = "",

        [string]$SendFile = ""
    )

    $arguments = @("--mode", "viewer", "--device", $Device, "--target", $Target)
    if (-not [string]::IsNullOrWhiteSpace($ClientConfig)) {
        $arguments += @("--config", $ClientConfig)
    }
    elseif (-not [string]::IsNullOrWhiteSpace($TokenFile)) {
        $arguments += @("--token-file", $TokenFile)
    }
    else {
        $arguments += @("--token", $Token)
    }
    if (-not [string]::IsNullOrWhiteSpace($DeviceTokenFile)) {
        $arguments += @("--device-token-file", $DeviceTokenFile)
    }
    if ($TransportEncryption -ne "disabled" -or $PSBoundParameters.ContainsKey("TransportEncryption")) {
        $arguments += @("--transport-encryption", $TransportEncryption)
    }
    if (-not [string]::IsNullOrWhiteSpace($TransportSecret)) {
        $arguments += @("--transport-secret", $TransportSecret)
    }
    if (-not [string]::IsNullOrWhiteSpace($TransportSecretFile)) {
        $arguments += @("--transport-secret-file", $TransportSecretFile)
    }
    if ($Server) {
        $arguments += @("--server", $Server)
    }
    if ($SendFile) {
        $arguments += @("--send-file", $SendFile)
    }

    return $arguments
}

if ($TestMode) {
    return
}

if (-not [string]::IsNullOrWhiteSpace($TokenFile) -and $PSBoundParameters.ContainsKey("Token")) {
    throw "Pass either -Token or -TokenFile, not both."
}
if (-not [string]::IsNullOrWhiteSpace($ClientConfig) -and
    (-not [string]::IsNullOrWhiteSpace($TokenFile) -or $PSBoundParameters.ContainsKey("Token"))) {
    throw "Pass either -ClientConfig or token options, not both."
}
if (-not [string]::IsNullOrWhiteSpace($TransportSecret) -and -not [string]::IsNullOrWhiteSpace($TransportSecretFile)) {
    throw "Pass either -TransportSecret or -TransportSecretFile, not both."
}
if (-not [string]::IsNullOrWhiteSpace($DeviceTokenFile) -and -not (Test-Path -LiteralPath $DeviceTokenFile -PathType Leaf)) {
    throw "Device token file was not found: $DeviceTokenFile"
}
if (-not [string]::IsNullOrWhiteSpace($TransportSecretFile)) {
    if (-not (Test-Path -LiteralPath $TransportSecretFile -PathType Leaf)) {
        throw "TransportSecretFile was not found: $TransportSecretFile"
    }
    $TransportSecretFile = (Resolve-Path -LiteralPath $TransportSecretFile).Path
    if ([string]::IsNullOrWhiteSpace(([IO.File]::ReadAllText($TransportSecretFile)).Trim())) {
        throw "TransportSecretFile cannot be empty: $TransportSecretFile"
    }
}

$repoRoot = Split-Path -Parent $PSScriptRoot
$runtimeDir = Join-Path $repoRoot "build\x64\$Configuration"
$privateClientExe = Join-Path $runtimeDir "private-runtime\SyncVisionClient.exe"
$clientExe = if (Test-Path -LiteralPath $privateClientExe -PathType Leaf) {
    $privateClientExe
}
else {
    Join-Path $runtimeDir "SyncVisionClient.exe"
}

if (-not (Test-Path -LiteralPath $clientExe)) {
    throw "SyncVisionClient.exe was not found at $clientExe. Run scripts\build.ps1 -Configuration $Configuration first."
}

$clientArgumentParameters = @{
    Device = $Device
    Target = $Target
    Token = $Token
    TokenFile = $TokenFile
    DeviceTokenFile = $DeviceTokenFile
    ClientConfig = $ClientConfig
    Server = $Server
    SendFile = $SendFile
}
if ($PSBoundParameters.ContainsKey("TransportEncryption")) {
    $clientArgumentParameters.TransportEncryption = $TransportEncryption
}
if ($PSBoundParameters.ContainsKey("TransportSecret")) {
    $clientArgumentParameters.TransportSecret = $TransportSecret
}
if ($PSBoundParameters.ContainsKey("TransportSecretFile")) {
    $clientArgumentParameters.TransportSecretFile = $TransportSecretFile
}

$arguments = New-SyncVisionViewerClientArguments @clientArgumentParameters

$serverText = if ($ClientConfig) { "client config $ClientConfig" } elseif ($Server) { $Server } else { "LAN discovery, fallback 127.0.0.1:38580" }
Write-Host "Starting SyncVisionClient.exe viewer device=$Device target=$Target server=$serverText"
& $clientExe @arguments

if ($null -ne $LASTEXITCODE) {
    exit $LASTEXITCODE
}
