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

$ErrorActionPreference = 'Stop'

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

$UProjectPath = Join-Path $ProjectRoot 'UnrealHyperTwist\UnrealHyperTwist.uproject'
$AuthoringStateRoot = Join-Path $ProjectRoot 'UnrealHyperTwist\Saved\HyperTwistMapAuthoring'
$ClassicMapPath = Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Maps\L_HyperTwist_ClassicTraining.umap'
$FollowAlongMapPath = Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Maps\L_HyperTwist_FollowAlongTraining.umap'
$ExpectedMaterialPaths = @(
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\M_HT_ClassicCubeFaceMaster.uasset'),
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\MI_HT_ClassicCube_Up.uasset'),
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\MI_HT_ClassicCube_Down.uasset'),
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\MI_HT_ClassicCube_Front.uasset'),
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\MI_HT_ClassicCube_Back.uasset'),
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\MI_HT_ClassicCube_Left.uasset'),
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\MI_HT_ClassicCube_Right.uasset'),
    (Join-Path $ProjectRoot 'UnrealHyperTwist\Content\HyperTwistTraining\Materials\MI_HT_ClassicCube_Internal.uasset')
)

if (-not (Test-Path $UnrealEditorCmdPath))
{
    throw "UnrealEditor-Cmd.exe was not found at '$UnrealEditorCmdPath'."
}

if (-not (Test-Path $UProjectPath))
{
    throw "UnrealHyperTwist project file was not found at '$UProjectPath'."
}

if (-not (Test-Path $PythonScriptPath))
{
    throw "Classic-cube map authoring script was not found at '$PythonScriptPath'."
}

[System.IO.Directory]::CreateDirectory($AuthoringStateRoot) | Out-Null

$NormalizedPythonScriptPath = $PythonScriptPath -replace '\\', '/'
$AuthoredTargets = @(
    @{
        Label = 'classic'
        ExpectedMapPath = $ClassicMapPath
    },
    @{
        Label = 'followalong'
        ExpectedMapPath = $FollowAlongMapPath
    }
)

foreach ($Target in $AuthoredTargets)
{
    $MarkerPath = Join-Path $AuthoringStateRoot "$($Target.Label)-complete.json"
    $BackupPath = Join-Path $AuthoringStateRoot "$($Target.Label)-pre-authoring.umap"
    $HadOriginalMap = Test-Path $Target.ExpectedMapPath
    $AuthoringSucceeded = $false

    Remove-Item $MarkerPath, $BackupPath -Force -ErrorAction SilentlyContinue
    if ($HadOriginalMap)
    {
        Copy-Item $Target.ExpectedMapPath $BackupPath -Force
    }

    try
    {
        $env:HYPERTWIST_CLASSIC_CUBE_MAP_KIND = $Target.Label
        $env:HYPERTWIST_CLASSIC_CUBE_AUTHORING_MARKER = $MarkerPath
        $AuthoringStartedAtUtc = [DateTime]::UtcNow
        $BackendArguments = if ($RenderBackend -eq 'nullrhi')
        {
            @('-nullrhi')
        }
        else
        {
            @('-d3d11', '-RenderOffscreen')
        }
        Write-Host "Authoring HyperTwist classic cube training map target '$($Target.Label)' through UnrealEditor-Cmd ($RenderBackend)..."
        & $UnrealEditorCmdPath `
            $UProjectPath `
            "-ExecutePythonScript=$NormalizedPythonScriptPath" `
            -unattended `
            -nop4 `
            @BackendArguments `
            -nosound `
            -nosplash `
            -stdout `
            -FullStdOutLogOutput `
            -log

        $EditorExitCode = $LASTEXITCODE
        $FreshMapExists = (Test-Path $Target.ExpectedMapPath) -and (
            (Get-Item $Target.ExpectedMapPath).LastWriteTimeUtc -ge $AuthoringStartedAtUtc.AddSeconds(-2)
        )
        $CompletionMarkerIsValid = $false
        if (Test-Path $MarkerPath)
        {
            try
            {
                $CompletionMarker = Get-Content $MarkerPath -Raw | ConvertFrom-Json
                $CompletionMarkerIsValid = `
                    $CompletionMarker.schemaVersion -eq 1 -and `
                    $CompletionMarker.stage -eq 'complete' -and `
                    $CompletionMarker.target -eq $Target.Label -and `
                    $CompletionMarker.mapAssetPath -eq (
                        "/Game/HyperTwistTraining/Maps/" + [System.IO.Path]::GetFileNameWithoutExtension($Target.ExpectedMapPath)
                    ) -and `
                    @($CompletionMarker.actorLabels).Count -ge 7
            }
            catch
            {
                Write-Warning "Ignoring malformed authoring completion marker '$MarkerPath': $($_.Exception.Message)"
            }
        }

        if (-not $FreshMapExists -or -not $CompletionMarkerIsValid)
        {
            throw "Classic-cube map authoring did not produce a fresh, fully validated '$($Target.Label)' map (editor exit code $EditorExitCode)."
        }

        if ($EditorExitCode -ne 0)
        {
            Write-Warning "UnrealEditor-Cmd exited with code $EditorExitCode after the complete map marker was durably written. The validated authored map is retained."
        }

        $AuthoringSucceeded = $true
    }
    finally
    {
        Remove-Item Env:\HYPERTWIST_CLASSIC_CUBE_MAP_KIND -ErrorAction SilentlyContinue
        Remove-Item Env:\HYPERTWIST_CLASSIC_CUBE_AUTHORING_MARKER -ErrorAction SilentlyContinue

        if (-not $AuthoringSucceeded)
        {
            if ($HadOriginalMap -and (Test-Path $BackupPath))
            {
                Copy-Item $BackupPath $Target.ExpectedMapPath -Force
                Write-Warning "Restored the pre-authoring map after an incomplete '$($Target.Label)' authoring run."
            }
            elseif (Test-Path $Target.ExpectedMapPath)
            {
                Remove-Item $Target.ExpectedMapPath -Force
            }
        }

        Remove-Item $BackupPath -Force -ErrorAction SilentlyContinue
    }
}

foreach ($ExpectedMapPath in @($ClassicMapPath, $FollowAlongMapPath))
{
    if (-not (Test-Path $ExpectedMapPath))
    {
        throw "Expected authored map was not found at '$ExpectedMapPath'."
    }
}

foreach ($ExpectedMaterialPath in $ExpectedMaterialPaths)
{
    if (-not (Test-Path $ExpectedMaterialPath))
    {
        throw "Expected classic-cube material asset was not found at '$ExpectedMaterialPath'."
    }
}

Write-Host 'Classic-cube authored maps verified.'
