<#
.SYNOPSIS
    リセット空振り不具合の二分探索用に、過去のコミットの M88.exe をまとめて作る。

.DESCRIPTION
    git worktree を使って各コミットを別フォルダに展開してビルドし、
    出来上がった M88.exe を「地点ごとのフォルダ」に集める。

    ★現在の作業ツリーには一切触らない。
      git checkout もブランチ切り替えもしないので、コミットしていない変更が
      あっても安全。ビルドが終わった worktree はその都度削除する。

    出力先の各フォルダは独立した実行環境になる。
    M88.ini は exe と同じ場所に作られるので、フォルダごとに設定が分かれる
    （＝毎回まっさらな状態で比較できる）。

.PARAMETER OutRoot
    出力先のルート。リポジトリの外を指定すること（既定: ..\M88-bisect）

.PARAMETER RomDir
    ROM ファイルの置き場所。指定すると各フォルダに自動でコピーする。
    省略した場合は自分でコピーすること。

.PARAMETER Only
    地点のラベル(A〜H)を指定すると、その地点だけをビルドする。
    例: -Only A,D,E,F

.PARAMETER KeepWorktree
    ビルド後に worktree を消さない（ソースを見比べたいとき用）

.EXAMPLE
    powershell -NoProfile -ExecutionPolicy Bypass -File tools\bisect-build.ps1 -Only A
    powershell -NoProfile -ExecutionPolicy Bypass -File tools\bisect-build.ps1 -Only A,D,E,F -RomDir D:\PC88\rom
    powershell -NoProfile -ExecutionPolicy Bypass -File tools\bisect-build.ps1
#>
[CmdletBinding()]
param(
    [string]$OutRoot = '',
    [string]$RomDir = '',
    [string[]]$Only = @(),
    [switch]$KeepWorktree
)

$ErrorActionPreference = 'Stop'

$Root = Split-Path -Parent $PSScriptRoot
if (-not $OutRoot) {
    $OutRoot = Join-Path (Split-Path -Parent $Root) 'M88-bisect'
}

# ---------------------------------------------------------------------------
#  二分探索の地点
#   docs/03.6-phase3.6-fix.md §4 と対応させること
# ---------------------------------------------------------------------------
$points = @(
    @{ Label = 'A'; Sha = 'cf8a4fe'; Desc = 'Phase 0 完了 (コード改変ゼロ = 実質 upstream)' },
    @{ Label = 'B'; Sha = '3319769'; Desc = 'Phase 1 完了 (ホイールスクロール)' },
    @{ Label = 'C'; Sha = '8859abf'; Desc = 'Phase 2 完了 (デバッグウインドウ)' },
    @{ Label = 'D'; Sha = '82168e8'; Desc = 'Phase 2.5 完了 (FileIO排他解除 / ステータスバー既定ON)' },
    @{ Label = 'E'; Sha = 'd88971d'; Desc = 'Phase 2.6 完了 (画面倍率・全画面・描画層作り替え)' },
    @{ Label = 'F'; Sha = '69a809f'; Desc = 'Phase 3 完了 (D3D11 / CRTフィルタ)' },
    @{ Label = 'G'; Sha = '38f9bfe'; Desc = 'Phase 3.5a 完了 (メニュー / 設定 / About)' },
    @{ Label = 'H'; Sha = '9483628'; Desc = 'Phase 3.5b 完了 (= main)' }
)

if ($Only.Count -gt 0) {
    $points = $points | Where-Object { $Only -contains $_.Label }
    if (-not $points) {
        Write-Host "ERROR: -Only に指定したラベルが見つかりません。A〜H で指定してください。" -ForegroundColor Red
        exit 2
    }
}

# ---------------------------------------------------------------------------
#  事前チェック
# ---------------------------------------------------------------------------
Push-Location $Root
try {
    & git rev-parse --is-inside-work-tree > $null
    if ($LASTEXITCODE -ne 0) {
        Write-Host "ERROR: git リポジトリではありません: $Root" -ForegroundColor Red
        exit 2
    }

    if ($RomDir) {
        if (-not (Test-Path $RomDir)) {
            Write-Host "ERROR: -RomDir が見つかりません: $RomDir" -ForegroundColor Red
            exit 2
        }
        $romfiles = Get-ChildItem -Path $RomDir -Filter *.ROM -File
        if ($romfiles.Count -eq 0) {
            Write-Host "WARNING: $RomDir に *.ROM がありません" -ForegroundColor Yellow
        }
    }

    if (-not (Test-Path $OutRoot)) {
        New-Item -ItemType Directory -Path $OutRoot -Force | Out-Null
    }

    Write-Host ''
    Write-Host "リポジトリ : $Root"
    Write-Host "出力先     : $OutRoot"
    Write-Host "対象       : $(($points | ForEach-Object { $_.Label }) -join ', ')"
    Write-Host ''

    $results = @()

    foreach ($p in $points) {
        $label = $p.Label
        $sha = $p.Sha
        $wt = Join-Path $OutRoot "_wt_$label"
        $dest = Join-Path $OutRoot "$label`_$sha"

        Write-Host ''
        Write-Host "=== [$label] $sha  $($p.Desc) ===" -ForegroundColor Cyan

        # 前回の残骸を掃除
        if (Test-Path $wt) {
            & git worktree remove --force $wt 2>$null
            if (Test-Path $wt) { Remove-Item -Recurse -Force $wt }
        }

        # worktree を作る（現在の作業ツリーには触らない）
        & git worktree add --detach $wt $sha
        if ($LASTEXITCODE -ne 0) {
            Write-Host "ERROR: git worktree add に失敗しました ($sha)" -ForegroundColor Red
            $results += [pscustomobject]@{ Label = $label; Sha = $sha; Status = 'worktree失敗' }
            continue
        }

        # ビルド（その時点の tools\build.ps1 を使う）
        $buildps1 = Join-Path $wt 'tools\build.ps1'
        if (-not (Test-Path $buildps1)) {
            Write-Host "ERROR: $buildps1 がありません" -ForegroundColor Red
            $results += [pscustomobject]@{ Label = $label; Sha = $sha; Status = 'build.ps1なし' }
            if (-not $KeepWorktree) { & git worktree remove --force $wt }
            continue
        }

        & powershell -NoProfile -ExecutionPolicy Bypass -File $buildps1 -Config Release -Rebuild
        $buildcode = $LASTEXITCODE

        $exe = Join-Path $wt 'x64\Release\M88.exe'
        if ($buildcode -ne 0 -or -not (Test-Path $exe)) {
            Write-Host "ERROR: ビルド失敗 (exit $buildcode)" -ForegroundColor Red
            $results += [pscustomobject]@{ Label = $label; Sha = $sha; Status = "ビルド失敗($buildcode)" }
            if (-not $KeepWorktree) { & git worktree remove --force $wt }
            continue
        }

        # 成果物を集める
        if (Test-Path $dest) { Remove-Item -Recurse -Force $dest }
        New-Item -ItemType Directory -Path $dest -Force | Out-Null
        Copy-Item $exe (Join-Path $dest 'M88.exe') -Force

        # シェーダ（Phase 3 以降のみ存在。exe と同じ場所の shaders\ を見に行く）
        $shaders = Join-Path $wt 'x64\Release\shaders'
        if (Test-Path $shaders) {
            Copy-Item $shaders (Join-Path $dest 'shaders') -Recurse -Force
        }

        # ROM
        if ($RomDir) {
            Copy-Item (Join-Path $RomDir '*.ROM') $dest -Force -ErrorAction SilentlyContinue
            Copy-Item (Join-Path $RomDir '*.rom') $dest -Force -ErrorAction SilentlyContinue
        }

        # 目印
        "$label  $sha`r`n$($p.Desc)`r`n" | Out-File (Join-Path $dest '_WHICH.txt') -Encoding utf8

        Write-Host "OK: $dest" -ForegroundColor Green
        $results += [pscustomobject]@{ Label = $label; Sha = $sha; Status = 'OK' }

        if (-not $KeepWorktree) {
            & git worktree remove --force $wt
            if (Test-Path $wt) { Remove-Item -Recurse -Force $wt }
        }
    }

    & git worktree prune

    Write-Host ''
    Write-Host '=== 結果 ===' -ForegroundColor Cyan
    $results | Format-Table -AutoSize
    Write-Host ''
    Write-Host "出力先: $OutRoot"
    Write-Host '各フォルダの M88.exe を「問題が起きるディスク」で試してください。'
    Write-Host '手順は毎回同じにすること (ディスクで起動 -> 1回目のリセット)。'
}
finally {
    Pop-Location
}
