param(
    [string]$ProjectRoot = 'C:\HyperTwist',
    [string]$UnrealEditorCmdPath = 'C:\Program Files\Epic Games\UE_5.7\Engine\Binaries\Win64\UnrealEditor-Cmd.exe',
    [string]$PythonScriptPath
)

$ErrorActionPreference = 'Stop'

if ([string]::IsNullOrWhiteSpace($PythonScriptPath))
{
    $PythonScriptPath = Join-Path $ProjectRoot 'scripts\hypertwist_author_virtual_4d_training_maps.py'
}

$UProjectPath = Join-Path $ProjectRoot 'UnrealHyperTwist\UnrealHyperTwist.uproject'
$ReceiptDirectory = Join-Path $ProjectRoot 'UnrealHyperTwist\Saved\HyperTwistMapAuthoring'
$ManifestPath = Join-Path $ProjectRoot 'docs\generated\virtual_4d_training_maps\virtual_4d_dedicated_map_manifest.json'
$Orders = @(2, 3, 4, 5, 6)

if (-not (Test-Path -LiteralPath $UnrealEditorCmdPath -PathType Leaf))
{
    throw "UnrealEditor-Cmd.exe was not found at '$UnrealEditorCmdPath'."
}
if (-not (Test-Path -LiteralPath $UProjectPath -PathType Leaf))
{
    throw "UnrealHyperTwist project file was not found at '$UProjectPath'."
}
if (-not (Test-Path -LiteralPath $PythonScriptPath -PathType Leaf))
{
    throw "Virtual 4D map authoring script was not found at '$PythonScriptPath'."
}

$NormalizedPythonScriptPath = $PythonScriptPath -replace '\\', '/'
foreach ($Order in $Orders)
{
    $MapName = "L_HyperTwist_MagicCube4D_${Order}x${Order}x${Order}x${Order}Training"
    $MapPath = Join-Path $ProjectRoot "UnrealHyperTwist\Content\HyperTwistTraining\Maps\$MapName.umap"
    $ReceiptPath = Join-Path $ReceiptDirectory "virtual_4d_${Order}x_complete.json"
    $ExpectedGameMode = if ($Order -eq 2)
    {
        '/Script/UnrealHyperTwist.HyperTwistMelindaProjectionGameMode'
    }
    else
    {
        "/Script/UnrealHyperTwist.HyperTwistVirtual${Order}${Order}${Order}${Order}ProjectionGameMode"
    }

    Remove-Item -LiteralPath $ReceiptPath -Force -ErrorAction SilentlyContinue
    $AuthoringStartedAtUtc = [DateTime]::UtcNow
    $env:HYPERTWIST_VIRTUAL_4D_ORDER = [string]$Order
    Write-Host "Authoring exact ${Order}x${Order}x${Order}x${Order} HyperTwist training map..."
    & $UnrealEditorCmdPath `
        $UProjectPath `
        "-ExecutePythonScript=$NormalizedPythonScriptPath" `
        -unattended `
        -nop4 `
        -nullrhi `
        -nosound `
        -nosplash `
        -stdout `
        -FullStdOutLogOutput `
        -log

    $AuthoringExitCode = $LASTEXITCODE
    $Receipt = $null
    if (Test-Path -LiteralPath $ReceiptPath -PathType Leaf)
    {
        $Receipt = Get-Content -LiteralPath $ReceiptPath -Raw | ConvertFrom-Json
    }
    $MapHash = if (Test-Path -LiteralPath $MapPath -PathType Leaf)
    {
        (Get-FileHash -LiteralPath $MapPath -Algorithm MD5).Hash.ToLowerInvariant()
    }
    else
    {
        ''
    }
    $ReceiptIsFresh = $Receipt -and `
        (Get-Item -LiteralPath $ReceiptPath).LastWriteTimeUtc -ge $AuthoringStartedAtUtc.AddSeconds(-2)
    $ReceiptIsValid = $ReceiptIsFresh -and `
        $Receipt.authoringComplete -eq $true -and `
        $Receipt.order -eq $Order -and `
        $Receipt.gameModeClassPath -eq $ExpectedGameMode -and `
        $Receipt.mapHashMd5 -eq $MapHash

    if (-not $ReceiptIsValid)
    {
        Remove-Item Env:\HYPERTWIST_VIRTUAL_4D_ORDER -ErrorAction SilentlyContinue
        if ($AuthoringExitCode -ne 0)
        {
            throw "Virtual 4D map authoring failed with exit code $AuthoringExitCode before a valid receipt was written for order $Order."
        }
        throw "Virtual 4D map authoring exited without a fresh hash-bound receipt for order $Order."
    }
    if ($AuthoringExitCode -ne 0)
    {
        Write-Warning "UnrealEditor-Cmd exited with code $AuthoringExitCode after order $Order completed and wrote a valid receipt. Accepting the known post-completion headless shutdown failure."
    }
}

Remove-Item Env:\HYPERTWIST_VIRTUAL_4D_ORDER -ErrorAction SilentlyContinue

if (-not (Test-Path -LiteralPath $ManifestPath -PathType Leaf))
{
    throw "Virtual 4D map manifest was not generated at '$ManifestPath'."
}

$Manifest = Get-Content -LiteralPath $ManifestPath -Raw | ConvertFrom-Json
$ManifestEntries = @($Manifest.entries)
if ($Manifest.schemaVersion -ne 'hypertwist/virtual-4d-dedicated-map-manifest/v1' `
    -or $ManifestEntries.Count -ne $Orders.Count)
{
    throw "Virtual 4D map manifest does not contain the complete 2x through 6x route set."
}

foreach ($Order in $Orders)
{
    $Entry = @($ManifestEntries | Where-Object { $_.order -eq $Order })
    if ($Entry.Count -ne 1)
    {
        throw "Virtual 4D map manifest does not contain exactly one entry for order $Order."
    }
    $MapPath = Join-Path $ProjectRoot $Entry[0].mapFileRelativePath
    if (-not (Test-Path -LiteralPath $MapPath -PathType Leaf))
    {
        throw "Authored virtual 4D map is missing at '$MapPath'."
    }
    $MapHash = (Get-FileHash -LiteralPath $MapPath -Algorithm MD5).Hash.ToLowerInvariant()
    if ($Entry[0].mapHashMd5 -ne $MapHash)
    {
        throw "Virtual 4D map manifest hash does not match order $Order."
    }
}

Write-Host 'Exact 2x through 6x virtual 4D maps and manifest verified.'
