param(
    [Parameter(Mandatory=$true)][string]$OutputFile,
    [ValidateSet('Debug','Release')][string]$Configuration='Release',
    [string]$BuildDir='D:/0A_VST_Development/build',
    [ValidateSet('Baseline','Candidate','Profile')][string]$Role='Baseline',
    [switch]$ProductionOptimized
)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'CPUReportIO.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
if(-not [IO.Path]::IsPathRooted($OutputFile)){throw 'OutputFile must be absolute'}
if(Test-Path -LiteralPath $OutputFile){throw 'Metadata already exists'}
$cpu=Get-CimInstance Win32_Processor
$os=Get-CimInstance Win32_OperatingSystem
$computer=Get-CimInstance Win32_ComputerSystem
$vs= & 'C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe' -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json | ConvertFrom-Json
if($vs.installationPath -ne 'C:\Program Files\Microsoft Visual Studio\18\Community'){throw 'Unexpected Visual Studio instance'}
Add-Type -TypeDefinition @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public static class DeepPluckCpuTopology {
    [DllImport("kernel32.dll", SetLastError=true)]
    static extern bool GetSystemCpuSetInformation(IntPtr p, uint n, out uint required, IntPtr process, uint flags);
    public static int[][] Read() {
        uint bytes;
        GetSystemCpuSetInformation(IntPtr.Zero, 0, out bytes, IntPtr.Zero, 0);
        if(bytes==0) throw new InvalidOperationException("CPU set information unavailable");
        IntPtr p=Marshal.AllocHGlobal((int)bytes);
        try {
            if(!GetSystemCpuSetInformation(p,bytes,out bytes,IntPtr.Zero,0)) throw new InvalidOperationException("CPU topology read failed");
            var rows=new List<int[]>();
            for(int offset=0;offset<(int)bytes;) {
                var item=IntPtr.Add(p,offset); int size=Marshal.ReadInt32(item);
                if(size<20 || offset+size>bytes) throw new InvalidOperationException("Invalid CPU set structure");
                if(Marshal.ReadInt32(item,4)==0) rows.Add(new int[] {
                    Marshal.ReadInt32(item,8), Marshal.ReadInt16(item,12),
                    Marshal.ReadByte(item,14), Marshal.ReadByte(item,15),
                    Marshal.ReadByte(item,18), Marshal.ReadByte(item,19)
                });
                offset+=size;
            }
            return rows.ToArray();
        } finally { Marshal.FreeHGlobal(p); }
    }
}
'@
$topology=@([DeepPluckCpuTopology]::Read() | ForEach-Object {
    [ordered]@{cpuSetId=$_[0];group=$_[1];logicalIndex=$_[2];coreIndex=$_[3];efficiencyClass=$_[4];flags=$_[5]}
})
$power=(powercfg /getactivescheme | Out-String).Trim()
$environment=[ordered]@{
    osCaption=$os.Caption;osVersion=$os.Version;osBuild=$os.BuildNumber;osArchitecture=$os.OSArchitecture
    cpuName=$cpu.Name;physicalCores=$cpu.NumberOfCores;logicalCores=$cpu.NumberOfLogicalProcessors
    cpuSets=$topology;memoryBytes=$computer.TotalPhysicalMemory;powerScheme=$power
    visualStudio=$vs.installationVersion;visualStudioPath=$vs.installationPath
    msvc='19.51.36256';vcTools='14.51.36231';windowsSdk='10.0.26100.0';cmake='4.4.3';juce='9.0.1'
    target='x64';language='C++20';processPriority='Normal';affinity='unrestricted, scheduler default'
    fpPolicy='original JUCE/CMake Release flags; no fast-math/PGO/LTO/ISA change'
    profiling=($Role -eq 'Profile');debugger=$false;audioHardwareUsed=$false
}
function Get-TextHash([string]$Text){
    $algorithm=[Security.Cryptography.SHA256]::Create()
    try{([BitConverter]::ToString($algorithm.ComputeHash([Text.Encoding]::UTF8.GetBytes($Text)))).Replace('-','').ToLowerInvariant()}
    finally{$algorithm.Dispose()}
}
Push-Location -LiteralPath $repo
try{
    $sourceFiles=@(git ls-files Source Tests CMakeLists.txt AGENTS.md Docs/Sound)
    $sourceFiles+=@(rg --files Tests)
    $sourceFiles+=$MyInvocation.MyCommand.Path.Substring($repo.Length+1).Replace('\','/')
    $source=@($sourceFiles | Sort-Object -Unique | ForEach-Object {
        $file=Get-Item -LiteralPath (Join-Path $repo $_)
        [ordered]@{path=$_.Replace('\','/');bytes=$file.Length;sha256=(Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256).Hash.ToLowerInvariant()}
    })
    [xml]$project=Get-Content -LiteralPath (Join-Path $BuildDir 'DeepPluck.vcxproj') -Raw
    $compile=@($project.Project.ItemDefinitionGroup | Where-Object {$_.Condition -like "*'$Configuration|x64'*"})
    if($compile.Count -ne 1){throw 'Cannot resolve actual configuration compiler settings'}
    $metadata=[ordered]@{
        schema='DeepPluck-CPU-Provenance-Rev1';createdUtc=[DateTime]::UtcNow.ToString('o')
        head=(git rev-parse HEAD);branch=(git branch --show-current);dirtyStatus=@(git status --porcelain=v1)
        source=$source;source_sha256=(Get-TextHash ($source | ConvertTo-Json -Depth 8 -Compress))
        environment=$environment;environment_sha256=(Get-TextHash ($environment | ConvertTo-Json -Depth 8 -Compress))
        configuration=$Configuration;buildDir=[IO.Path]::GetFullPath($BuildDir)
        compilerSettingsXml=$compile[0].OuterXml
        cmakeCacheSha256=(Get-FileHash -LiteralPath (Join-Path $BuildDir 'CMakeCache.txt')).Hash
        reference25='4b4d0e5867799f66b9e3db95eb70cad195b57d33'
        requestedManifest='DeepPluck-CPU-0.11.5-Rev1';productionOptimized=[bool]$ProductionOptimized;role=$Role
    }
    $metadata | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $OutputFile -Encoding utf8
} finally {Pop-Location}
Write-Host "Captured benchmark provenance: $OutputFile"
