<#
.SYNOPSIS
    M88 を x64 でビルドする。Claude Code から呼ばれることを想定している。

.DESCRIPTION
    vswhere で Visual Studio の MSBuild を探索し、x64 構成でビルドする。
    ビルドログは build\logs\ に保存し、標準出力にはエラー・警告の要約だけを出す。

    ★コンパイラ・リンカのメッセージは VSLANG=1033 で英語に固定している。
      日本語(CP932)のまま出力されると、UTF-8 前提のツールから読んだときに
      文字化けしてエラー内容が読めなくなるため。
      （C1083 / C2065 / LNK2019 などの C++ ツールセットのメッセージが対象。
        MSB**** の MSBuild 自身のメッセージは環境によって日本語のまま出ることがある）

.PARAMETER Config
    Release / Debug / Both （既定: Release）

.PARAMETER Rebuild
    /t:Rebuild でフルビルドする

.PARAMETER Clean
    /t:Clean のみ実行して終了する

.PARAMETER TailLines
    エラー時に表示するログ末尾の行数（既定: 40）

.EXAMPLE
    powershell -NoProfile -ExecutionPolicy Bypass -File tools\build.ps1
    powershell -NoProfile -ExecutionPolicy Bypass -File tools\build.ps1 -Config Both
    powershell -NoProfile -ExecutionPolicy Bypass -File tools\build.ps1 -Rebuild

.OUTPUTS
    終了コード 0 = 全構成成功 / 1 = ビルド失敗 / 2 = 環境の問題（MSBuild が無い等）
#>
[CmdletBinding()]
param(
    [ValidateSet('Release', 'Debug', 'Both')]
    [string]$Config = 'Release',

    [switch]$Rebuild,
    [switch]$Clean,
    [int]$TailLines = 40
)

$ErrorActionPreference = 'Stop'

# コンパイラ・リンカのメッセージを英語に固定（文字化け防止）
$env:VSLANG = 1033

$Root = Split-Path -Parent $PSScriptRoot
Push-Location $Root

function Write-Section($text) {
    Write-Host ''
    Write-Host "=== $text ===" -ForegroundColor Cyan
}

try {
    # -------------------------------------------------------------------------
    # ソリューションファイルの決定
    #   Phase 0 の変換前は M88_2008.sln、変換後は M88.sln
    # -------------------------------------------------------------------------
    $sln = $null
    foreach ($cand in @('M88.sln', 'M88_2008.sln')) {
        if (Test-Path (Join-Path $Root $cand)) { $sln = $cand; break }
    }
    if (-not $sln) {
        Write-Host "ERROR: ソリューションファイルが見つかりません (M88.sln / M88_2008.sln)" -ForegroundColor Red
        exit 2
    }
    Write-Host "Solution : $sln"

    # -------------------------------------------------------------------------
    # MSBuild の探索
    # -------------------------------------------------------------------------
    # Join-Path は存在しないドライブを指定すると例外になるため、ここでは文字列連結にする
    # （Visual Studio 未インストール環境でも、例外ではなく終了コード 2 で返したい）
    $pf86 = ${env:ProgramFiles(x86)}
    if (-not $pf86) { $pf86 = 'C:\Program Files (x86)' }
    $vswhere = "$pf86\Microsoft Visual Studio\Installer\vswhere.exe"
    if (-not (Test-Path $vswhere)) {
        Write-Host "ERROR: vswhere.exe が見つかりません。Visual Studio がインストールされていない可能性があります。" -ForegroundColor Red
        Write-Host "  探した場所: $vswhere"
        exit 2
    }

    $vsPath = & $vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath
    if (-not $vsPath) {
        Write-Host "ERROR: MSBuild を含む Visual Studio が見つかりません。" -ForegroundColor Red
        Write-Host "  VS Installer で「C++ によるデスクトップ開発」ワークロードを入れてください。"
        exit 2
    }

    $msbuild = "$vsPath\MSBuild\Current\Bin\MSBuild.exe"
    if (-not (Test-Path $msbuild)) {
        Write-Host "ERROR: MSBuild.exe が見つかりません: $msbuild" -ForegroundColor Red
        exit 2
    }
    Write-Host "MSBuild  : $msbuild"

    # -------------------------------------------------------------------------
    # writetag.exe のビルド
    #   M88.vcxproj の PostBuildEvent (`writetag release\m88.exe`) が使う自前ツール。
    #   ソリューションにプロジェクトとして含まれておらず、ビルド時に PATH 上に
    #   存在することが前提のため、ここで一度だけコンパイルして PATH に追加する。
    # -------------------------------------------------------------------------
    $writetagSrc = Join-Path $Root 'writetag.cpp'
    $writetagDir = Join-Path $Root 'tools\bin'
    $writetagExe = Join-Path $writetagDir 'writetag.exe'

    if (Test-Path $writetagSrc) {
        $needBuild = (-not (Test-Path $writetagExe)) -or
            ((Get-Item $writetagSrc).LastWriteTime -gt (Get-Item $writetagExe).LastWriteTime)

        if ($needBuild) {
            Write-Section 'writetag.exe をビルド'
            if (-not (Test-Path $writetagDir)) { New-Item -ItemType Directory -Path $writetagDir -Force | Out-Null }

            $vcvars64 = "$vsPath\VC\Auxiliary\Build\vcvars64.bat"
            if (-not (Test-Path $vcvars64)) {
                Write-Host "ERROR: vcvars64.bat が見つかりません: $vcvars64" -ForegroundColor Red
                exit 2
            }

            $installerDir = "$pf86\Microsoft Visual Studio\Installer"
            $writetagObj = Join-Path $writetagDir 'writetag.obj'
            $cmdLine = "set `"PATH=%PATH%;$installerDir`" && call `"$vcvars64`" >nul && cl.exe /nologo /O2 `"$writetagSrc`" /Fe:`"$writetagExe`" /Fo:`"$writetagObj`""
            cmd.exe /c $cmdLine | Out-Null

            if (-not (Test-Path $writetagExe)) {
                Write-Host "ERROR: writetag.exe のビルドに失敗しました" -ForegroundColor Red
                exit 2
            }
            Write-Host "writetag.exe : $writetagExe"
        }

        $env:PATH = "$writetagDir;$env:PATH"
    }

    # -------------------------------------------------------------------------
    # ログ出力先
    # -------------------------------------------------------------------------
    $logDir = Join-Path $Root 'build\logs'
    if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }

    # -------------------------------------------------------------------------
    # ビルド対象の構成
    # -------------------------------------------------------------------------
    $configs = if ($Config -eq 'Both') { @('Release', 'Debug') } else { @($Config) }

    $target = 'Build'
    if ($Rebuild) { $target = 'Rebuild' }
    if ($Clean)   { $target = 'Clean' }

    $failed = @()
    $summary = @()

    foreach ($cfg in $configs) {
        Write-Section "$target  $cfg | x64"

        $log = Join-Path $logDir "msbuild-$cfg-x64.log"

        # ※ $args は PowerShell の自動変数なので使わないこと
        $msbuildArgs = @(
            $sln,
            "/t:$target",
            "/p:Configuration=$cfg",
            '/p:Platform=x64',
            '/m',
            '/nologo',
            '/v:minimal',
            "/flp:LogFile=$log;Verbosity=normal;Encoding=UTF-8"
        )

        & $msbuild @msbuildArgs
        $exit = $LASTEXITCODE

        # ---------------------------------------------------------------------
        # ログからエラー・警告を抽出
        # ---------------------------------------------------------------------
        $errCount = 0
        $warnCount = 0
        $errLines = @()

        if (Test-Path $log) {
            $errMatches = Select-String -Path $log -Pattern ':\s(error|fatal error)\s[A-Z]+[0-9]+' -AllMatches
            $warnMatches = Select-String -Path $log -Pattern ':\swarning\s[A-Z]+[0-9]+' -AllMatches

            # 同一行の重複（/m 並列ビルドで複数回出る）を除去
            $errLines = $errMatches | ForEach-Object { $_.Line.Trim() } | Select-Object -Unique
            $warnLines = $warnMatches | ForEach-Object { $_.Line.Trim() } | Select-Object -Unique

            $errCount = @($errLines).Count
            $warnCount = @($warnLines).Count
        }

        if ($exit -eq 0) {
            Write-Host "OK   $cfg|x64   warnings: $warnCount" -ForegroundColor Green
            $summary += "OK   $cfg|x64   warnings=$warnCount"
        }
        else {
            Write-Host "FAIL $cfg|x64   errors: $errCount  warnings: $warnCount" -ForegroundColor Red
            $failed += "$cfg|x64"
            $summary += "FAIL $cfg|x64   errors=$errCount warnings=$warnCount"

            if ($errCount -gt 0) {
                Write-Host ''
                Write-Host "--- errors ---" -ForegroundColor Red
                $errLines | Select-Object -First 30 | ForEach-Object { Write-Host "  $_" }
                if ($errCount -gt 30) {
                    Write-Host "  ... ほか $($errCount - 30) 件"
                }
            }
            else {
                # error パターンに引っかからない失敗（MSB のプロジェクト読み込み失敗など）
                Write-Host ''
                Write-Host "--- log tail ($TailLines lines) ---" -ForegroundColor Red
                Get-Content $log -Tail $TailLines | ForEach-Object { Write-Host "  $_" }
            }
            Write-Host ''
            Write-Host "  full log: $log"
        }
    }

    Write-Section 'SUMMARY'
    $summary | ForEach-Object { Write-Host "  $_" }

    if ($failed.Count -gt 0) {
        Write-Host ''
        Write-Host "BUILD FAILED: $($failed -join ', ')" -ForegroundColor Red
        exit 1
    }

    Write-Host ''
    Write-Host 'BUILD SUCCEEDED' -ForegroundColor Green

    if ($target -ne 'Clean') {
        foreach ($cfg in $configs) {
            $exe = Join-Path $Root "x64\$cfg\M88.exe"
            if (Test-Path $exe) {
                $fi = Get-Item $exe
                Write-Host ("  {0}  {1:N0} bytes  {2}" -f $exe, $fi.Length, $fi.LastWriteTime)
            }
            else {
                Write-Host "  WARNING: $exe が生成されていません" -ForegroundColor Yellow
            }
        }
    }

    exit 0
}
finally {
    Pop-Location
}
