# misc/build_helper.ps1 - Unified Build Utility Script
param(
    [string]$Action,
    [string]$CFG,
    [string]$TargetJuliet = "0",
    [string]$TargetGame = "0",
    [string]$TargetRomeo = "0",
    [string]$TargetShader = "0"
)

if (-not (Test-Path "Intermediate")) {
    New-Item -ItemType Directory -Path "Intermediate" | Out-Null
}

switch ($Action) {
    "StartBuild" {
        [System.IO.File]::WriteAllText("Intermediate\build_start.tmp", [System.DateTime]::Now.Ticks.ToString())
    }

    "FinishBuild" {
        $elapsedStr = "00:00:00.000"
        if (Test-Path "Intermediate\build_start.tmp") {
            $startStr = Get-Content "Intermediate\build_start.tmp" -ErrorAction SilentlyContinue
            if ($startStr) {
                $startTicks = [long]$startStr
                $elapsed = New-Object System.TimeSpan ([System.DateTime]::Now.Ticks - $startTicks)
                $elapsedStr = "{0:D2}:{1:D2}:{2:D2}.{3:D3}" -f $elapsed.Hours, $elapsed.Minutes, $elapsed.Seconds, $elapsed.Milliseconds
            }
            Remove-Item "Intermediate\build_start.tmp" -ErrorAction SilentlyContinue
        }
        Write-Host "Total Duration : $elapsedStr"
        Write-Host "Output Binaries:"
        if (Test-Path "Intermediate\built_outputs.tmp") {
            $files = Get-Content "Intermediate\built_outputs.tmp" -ErrorAction SilentlyContinue | Where-Object { Test-Path $_ }
            if ($files) {
                foreach ($f in $files) {
                    $item = Get-Item $f
                    $size = "{0:N2} MB" -f ($item.Length / 1MB)
                    $relPath = $item.FullName.Replace((Get-Location).Path + "\", "")
                    Write-Host "  - $relPath ($size)"
                }
            } else {
                Write-Host "  - None built in this session (all requested targets up-to-date)"
            }
            Remove-Item "Intermediate\built_outputs.tmp" -ErrorAction SilentlyContinue
        } else {
            Write-Host "  - None built in this session (all requested targets up-to-date)"
        }
    }

    "StartUnity" {
        # Compute SHA256 hashes of all existing Unity files before FASTBuild runs
        $hashes = @{}
        Get-ChildItem -Path "Intermediate" -Recurse -Filter "*_Unity*.cpp" -ErrorAction SilentlyContinue | ForEach-Object {
            $hash = (Get-FileHash -Path $_.FullName -Algorithm SHA256).Hash
            $hashes[$_.FullName] = $hash
        }
        $hashes | ConvertTo-Json | Set-Content -Path "Intermediate\unity_hashes.tmp" -ErrorAction SilentlyContinue
    }

    "EvaluateConfig" {
        # 1. Strip '#pragma message' from generated Unity files if present
        Get-ChildItem -Path "Intermediate" -Recurse -Filter "*_Unity*.cpp" -ErrorAction SilentlyContinue | ForEach-Object {
            $filePath = $_.FullName
            $lines = [System.IO.File]::ReadAllLines($filePath)
            $filtered = $lines | Where-Object { $_ -notlike '*#pragma message*' }
            if ($lines.Count -ne $filtered.Count) {
                [System.IO.File]::WriteAllLines($filePath, $filtered)
            }
        }

        # 2. Compare Unity hashes to detect Unity structure changes
        $oldHashes = @{}
        if (Test-Path "Intermediate\unity_hashes.tmp") {
            try {
                $json = Get-Content "Intermediate\unity_hashes.tmp" -Raw -ErrorAction SilentlyContinue
                if ($json) {
                    $obj = $json | ConvertFrom-Json
                    foreach ($prop in $obj.PSObject.Properties) {
                        $oldHashes[$prop.Name] = $prop.Value
                    }
                }
            } catch {}
            Remove-Item "Intermediate\unity_hashes.tmp" -ErrorAction SilentlyContinue
        }

        $unityChanged = "0"
        $currentFiles = Get-ChildItem -Path "Intermediate" -Recurse -Filter "*_Unity*.cpp" -ErrorAction SilentlyContinue
        if (-not $currentFiles) {
            $unityChanged = "1"
        } else {
            foreach ($file in $currentFiles) {
                $path = $file.FullName
                $newHash = (Get-FileHash -Path $path -Algorithm SHA256).Hash
                if (-not $oldHashes.ContainsKey($path) -or $oldHashes[$path] -ne $newHash) {
                    $unityChanged = "1"
                    break
                }
            }
        }

        # Helper function to check if target binary/obj is missing or older than source files in dirs
        function Test-NeedRebuild([string]$targetFile, [string[]]$dirs) {
            if (-not (Test-Path $targetFile)) { return "1" }
            if ($unityChanged -eq "1") { return "1" }
            $targetTime = (Get-Item $targetFile).LastWriteTime
            foreach ($d in $dirs) {
                if (Test-Path $d) {
                    $newer = Get-ChildItem -Path $d -Recurse -File -ErrorAction SilentlyContinue | Where-Object {
                        ($_.Extension -eq '.cpp' -or $_.Extension -eq '.h' -or $_.Extension -eq '.hpp' -or $_.Extension -eq '.inl') -and $_.LastWriteTime -gt $targetTime
                    }
                    if ($newer) { return "1" }
                }
            }
            return "0"
        }

        $julietObj = "Intermediate\x64-$CFG\Juliet_Unity1.obj"
        $imguiObj  = "Intermediate\x64-$CFG\ImGui_Unity1.obj"
        $gameDll   = "bin\x64-$CFG\Game.dll"
        $julietApp = "bin\x64-$CFG\JulietApp.exe"
        $romeoExe  = "bin\x64-$CFG\Romeo.exe"
        $shaderExe = "bin\x64-$CFG\JulietShaderCompiler.exe"

        $julietNeed = Test-NeedRebuild $julietObj @("Juliet")
        $imguiNeed  = Test-NeedRebuild $imguiObj  @("External/imgui")

        $gameNeed = "0"
        if ($TargetJuliet -eq "1" -or $TargetGame -eq "1") {
            $gameNeed = Test-NeedRebuild $gameDll @("Juliet", "Game", "External/imgui")
            if ($julietNeed -eq "1") { $gameNeed = "1" }
        }

        $julietAppNeed = "0"
        if ($TargetJuliet -eq "1") {
            $julietAppNeed = Test-NeedRebuild $julietApp @("JulietApp", "Game", "Juliet", "External/imgui")
            if ($gameNeed -eq "1") { $julietAppNeed = "1" }
        }

        $romeoNeed = "0"
        if ($TargetRomeo -eq "1") {
            $romeoNeed = Test-NeedRebuild $romeoExe @("Romeo", "Juliet", "External/imgui")
            if ($julietNeed -eq "1") { $romeoNeed = "1" }
        }

        $shaderNeed = "0"
        if ($TargetShader -eq "1" -and (Test-Path "Intermediate\JulietShaderCompiler\*.cpp")) {
            $shaderNeed = Test-NeedRebuild $shaderExe @("JulietShaderCompiler", "Juliet", "External/imgui")
            if ($julietNeed -eq "1") { $shaderNeed = "1" }
        }

        $lines = @(
            "FASTBUILD_UNITY_CHANGED=$unityChanged",
            "JULIET_NEED_COMPILE=$julietNeed",
            "IMGUI_NEED_COMPILE=$imguiNeed",
            "GAME_NEED_COMPILE=$gameNeed",
            "JULIETAPP_NEED_COMPILE=$julietAppNeed",
            "ROMEO_NEED_COMPILE=$romeoNeed",
            "SHADER_NEED_COMPILE=$shaderNeed"
        )
        $lines | Set-Content -Path "Intermediate\config_status.tmp"
    }
}
