[CmdletBinding()]
param(
    [string]$ModelPath,
    [int]$ServiceStartupTimeoutSeconds = 90,
    [int]$TestTimeoutSeconds = 240
)

$ErrorActionPreference = 'Stop'

$scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoRoot = Split-Path -Parent $scriptDirectory
$startScriptPath = Join-Path $scriptDirectory 'start-navisworks.ps1'
$defaultsFilePath = Join-Path $scriptDirectory 'test-automation.defaults.json'
$testApiBaseUrl = 'http://127.0.0.1:18777'

function Resolve-DefaultModelPath {
    if (-not (Test-Path $defaultsFilePath)) {
        return $null
    }

    $defaults = Get-Content $defaultsFilePath -Raw | ConvertFrom-Json
    $defaultModelPath = [string]$defaults.defaultModelPath
    if ([string]::IsNullOrWhiteSpace($defaultModelPath)) {
        return $null
    }

    return [System.IO.Path]::GetFullPath($defaultModelPath)
}

function Wait-TestApiReady {
    param(
        [string]$BaseUrl,
        [int]$TimeoutSeconds
    )

    $deadline = (Get-Date).AddSeconds($TimeoutSeconds)
    $lastError = $null

    while ((Get-Date) -lt $deadline) {
        try {
            $pingResponse = Invoke-RestMethod -Uri ($BaseUrl + '/api/test/ping') -TimeoutSec 10
            if ($pingResponse.ok) {
                return
            }
        }
        catch {
            $lastError = $_.Exception.Message
        }

        Start-Sleep -Seconds 1
    }

    if ([string]::IsNullOrWhiteSpace($lastError)) {
        throw "测试 HTTP 服务未在 $TimeoutSeconds 秒内就绪。"
    }

    throw "测试 HTTP 服务未在 $TimeoutSeconds 秒内就绪。最后错误: $lastError"
}

function Wait-GroundRouteReady {
    param(
        [string]$BaseUrl,
        [int]$TimeoutSeconds
    )

    $deadline = (Get-Date).AddSeconds($TimeoutSeconds)
    $lastError = $null

    while ((Get-Date) -lt $deadline) {
        try {
            $routesResponse = Invoke-RestMethod -Uri ($BaseUrl + '/api/test/routes') -TimeoutSec 10
            if ($routesResponse.ok -and $routesResponse.data -and $routesResponse.data.totalRouteCount -gt 0) {
                $groundRoute = $routesResponse.data.suggestedAutoTestRoutes.ground
                if (-not [string]::IsNullOrWhiteSpace([string]$groundRoute)) {
                    return [string]$groundRoute
                }
            }
        }
        catch {
            $lastError = $_.Exception.Message
        }

        Start-Sleep -Seconds 1
    }

    if ([string]::IsNullOrWhiteSpace($lastError)) {
        throw "默认地面测试路径未在 $TimeoutSeconds 秒内就绪。"
    }

    throw "默认地面测试路径未在 $TimeoutSeconds 秒内就绪。最后错误: $lastError"
}

function Save-JsonResult {
    param(
        [object]$Payload
    )

    $logRoot = Join-Path $env:ProgramData 'Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\logs\test-automation'
    New-Item -ItemType Directory -Path $logRoot -Force | Out-Null

    $fileName = 'ground-virtual-collision-test-' + (Get-Date -Format 'yyyyMMdd-HHmmss') + '.json'
    $outputPath = Join-Path $logRoot $fileName
    $json = $Payload | ConvertTo-Json -Depth 16
    [System.IO.File]::WriteAllText($outputPath, $json, [System.Text.UTF8Encoding]::new($false))
    return $outputPath
}

if ([string]::IsNullOrWhiteSpace($ModelPath)) {
    $ModelPath = Resolve-DefaultModelPath
}

if (-not [string]::IsNullOrWhiteSpace($ModelPath)) {
    $ModelPath = [System.IO.Path]::GetFullPath($ModelPath)
    if (-not (Test-Path $ModelPath)) {
        throw "模型文件不存在: $ModelPath"
    }
}

Write-Host '启动 Navisworks...'
if ([string]::IsNullOrWhiteSpace($ModelPath)) {
    & $startScriptPath
}
else {
    & $startScriptPath $ModelPath
}

Write-Host '等待测试 HTTP 服务就绪...'
Wait-TestApiReady -BaseUrl $testApiBaseUrl -TimeoutSeconds $ServiceStartupTimeoutSeconds

Write-Host '等待默认地面测试路径就绪...'
$groundRouteName = Wait-GroundRouteReady -BaseUrl $testApiBaseUrl -TimeoutSeconds $ServiceStartupTimeoutSeconds

Write-Host ('切换到默认地面测试路径: {0}' -f $groundRouteName)
$selectRouteResponse = Invoke-RestMethod -Method Post -Uri ($testApiBaseUrl + '/api/test/select-default-route?pathType=Ground') -TimeoutSec 15
if (-not $selectRouteResponse.ok) {
    throw '切换默认地面测试路径失败。'
}

Write-Host '执行地面虚拟物体碰撞测试...'
$requestUrl = $testApiBaseUrl + "/api/test/run-ground-collision-test?useVirtualObject=true&timeoutSeconds=$TestTimeoutSeconds"
$testResult = Invoke-RestMethod -Method Post -Uri $requestUrl -TimeoutSec ($TestTimeoutSeconds + 30)

$outputFilePath = Save-JsonResult -Payload $testResult

Write-Host ('结果已保存: {0}' -f $outputFilePath)
if ($testResult.ok -and $testResult.data) {
    Write-Host ('路径: {0}' -f $testResult.data.route.name)
    Write-Host ('动画状态: {0}' -f $testResult.data.animation.currentState)
    Write-Host ('检测记录ID: {0}' -f $testResult.data.animation.detectionRecordId)
    if ($testResult.data.report) {
        Write-Host ('碰撞数: {0}' -f $testResult.data.report.totalCollisions)
        Write-Host ('截图数: {0}' -f $testResult.data.report.screenshotCount)
    }
}
