[CmdletBinding()]
param(
    [string]$PublishDirectory = (Join-Path $PSScriptRoot '..\artifacts\native-smoke-publish')
)

$ErrorActionPreference = 'Stop'

$repositoryRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '..')).Path
$publishPath = [IO.Path]::GetFullPath(
    $(if ([IO.Path]::IsPathRooted($PublishDirectory)) {
        $PublishDirectory
    }
    else {
        Join-Path $repositoryRoot $PublishDirectory
    }))

dotnet publish (Join-Path $repositoryRoot 'src\Eis.Web\Eis.Web.csproj') `
    --configuration Release `
    --output $publishPath `
    --no-restore
if ($LASTEXITCODE -ne 0) {
    throw 'ASP.NET Core 发布失败。'
}

$tempBase = [IO.Path]::GetFullPath([IO.Path]::GetTempPath())
$testRoot = Join-Path $tempBase ('eis-native-smoke-' + [Guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $testRoot | Out-Null

$listener = [Net.Sockets.TcpListener]::new([Net.IPAddress]::Loopback, 0)
$listener.Start()
$port = ([Net.IPEndPoint]$listener.LocalEndpoint).Port
$listener.Stop()

$baseUrl = "http://127.0.0.1:$port"
$stdoutPath = Join-Path $testRoot 'stdout.log'
$stderrPath = Join-Path $testRoot 'stderr.log'
$databasePath = Join-Path $testRoot 'eis.sqlite'
$process = $null

try {
    $process = Start-Process `
        -FilePath 'dotnet' `
        -ArgumentList (Join-Path $publishPath 'Eis.Web.dll') `
        -WorkingDirectory $publishPath `
        -Environment @{
            ASPNETCORE_ENVIRONMENT = 'Development'
            ASPNETCORE_URLS = $baseUrl
            DATABASE_CLIENT = 'sqlite'
            SQLITE_PATH = $databasePath
            INITIAL_ADMIN_USERNAME = 'admin'
            INITIAL_ADMIN_PASSWORD = 'NativeSmoke123456'
            INITIAL_ADMIN_DISPLAY_NAME = '原生冒烟管理员'
            REDIS_URL = ''
            REDIS_SESSION_URL = ''
        } `
        -RedirectStandardOutput $stdoutPath `
        -RedirectStandardError $stderrPath `
        -WindowStyle Hidden `
        -PassThru

    $ready = $false
    for ($attempt = 0; $attempt -lt 60; $attempt++) {
        if ($process.HasExited) {
            break
        }
        try {
            $live = Invoke-RestMethod -Uri "$baseUrl/health/live" -TimeoutSec 2
            $ready = $true
            break
        }
        catch {
            Start-Sleep -Milliseconds 250
        }
    }

    if (-not $ready) {
        $stdout = Get-Content -Raw $stdoutPath -ErrorAction SilentlyContinue
        $stderr = Get-Content -Raw $stderrPath -ErrorAction SilentlyContinue
        throw "ASP.NET Core 发布产物未就绪。`nstdout: $stdout`nstderr: $stderr"
    }

    $migration = Invoke-RestMethod -Uri "$baseUrl/health/migration" -TimeoutSec 5
    $homeResponse = Invoke-WebRequest -Uri "$baseUrl/" -TimeoutSec 5
    $applicationScript = Invoke-WebRequest -Uri "$baseUrl/js/app.js" -TimeoutSec 10
    $clientApiModule = Invoke-WebRequest -Uri "$baseUrl/js/client/api.js" -TimeoutSec 10
    $regionDataModule = Invoke-WebRequest -Uri "$baseUrl/js/data/china-regions.js" -TimeoutSec 10
    $ckeditor = Invoke-WebRequest -Uri "$baseUrl/vendor/ckeditor5/ckeditor5.js" -TimeoutSec 10
    $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
    $loginBody = @{
        username = 'admin'
        password = 'NativeSmoke123456'
    } | ConvertTo-Json -Compress
    $login = Invoke-RestMethod `
        -Uri "$baseUrl/api/auth/login" `
        -Method Post `
        -ContentType 'application/json' `
        -Body $loginBody `
        -WebSession $session `
        -TimeoutSec 5
    $currentUser = Invoke-RestMethod `
        -Uri "$baseUrl/api/auth/me" `
        -WebSession $session `
        -TimeoutSec 5
    $missing = Invoke-WebRequest `
        -Uri "$baseUrl/api/removed-legacy-route" `
        -SkipHttpErrorCheck `
        -TimeoutSec 5

    if ($live.status -ne 'healthy' -or
        $migration.legacyApiRemoved -ne $true -or
        $homeResponse.StatusCode -ne 200 -or
        $homeResponse.Content -notmatch '/js/app\.js' -or
        $applicationScript.RawContentLength -lt 100000 -or
        $applicationScript.Content -notmatch "from './client/api\.js'" -or
        $clientApiModule.RawContentLength -lt 1000 -or
        $regionDataModule.RawContentLength -lt 100000 -or
        $ckeditor.RawContentLength -lt 100000 -or
        $login.user.role -ne 'admin' -or
        $login.user.adminLevel -ne 'super' -or
        $currentUser.user.username -ne 'admin' -or
        $missing.StatusCode -ne 404) {
        throw '原生宿主冒烟断言失败。'
    }

    [pscustomobject]@{
        Process = $process.ProcessName
        Live = $live.status
        LegacyRemoved = $migration.legacyApiRemoved
        HomeStatus = $homeResponse.StatusCode
        FrontendBytes = $applicationScript.RawContentLength
        CkeditorBytes = $ckeditor.RawContentLength
        LoginRole = $login.user.role
        CurrentUser = $currentUser.user.username
        UnknownApiStatus = $missing.StatusCode
        DatabaseTarget = $databasePath
    } | Format-List
}
finally {
    if ($null -ne $process -and -not $process.HasExited) {
        Stop-Process -Id $process.Id -Force
        $process.WaitForExit()
    }

    $resolvedTestRoot = [IO.Path]::GetFullPath($testRoot)
    if ($resolvedTestRoot.StartsWith($tempBase, [StringComparison]::OrdinalIgnoreCase) -and
        (Test-Path -LiteralPath $resolvedTestRoot)) {
        Remove-Item -LiteralPath $resolvedTestRoot -Recurse -Force
    }
}
