Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

# Phase 2A reproducibility verifier
# Runs the pipeline twice and compares canonical production outputs only.
# out/audit/* is intentionally excluded because audit artifacts are regenerated.
# out/excel/*.xlsx is intentionally excluded because XLSX workbook metadata can change on save.
# Canonical reproducibility is verified through CSV, JSON, and TXT artifacts.

$Root = $PSScriptRoot
Set-Location $Root

$venvPython = Join-Path $Root ".venv\Scripts\python.exe"
if (Test-Path -LiteralPath $venvPython) {
    $pythonExe = $venvPython
} else {
    $pythonExe = "python"
}

function Invoke-Pipeline {
    Write-Host ""
    Write-Host "Running Phase 2A pipeline..." -ForegroundColor Cyan
    & $pythonExe "run_pipeline.py"
    if ($LASTEXITCODE -ne 0) {
        throw "run_pipeline.py failed with exit code $LASTEXITCODE"
    }
}

function Get-ProductionHashes {
    $outDir = Join-Path $Root "out"

    if (-not (Test-Path -LiteralPath $outDir)) {
        throw "Output folder not found: $outDir"
    }

    $files = @(
        Get-ChildItem -LiteralPath $outDir -Recurse -File |
            Where-Object {
                $_.FullName -notmatch "[\\/]out[\\/]audit[\\/]" -and
                $_.FullName -notmatch "[\\/]out[\\/]excel[\\/]" -and
                $_.Extension.ToLowerInvariant() -in @(".csv", ".json", ".txt")
            } |
            Sort-Object FullName
    )

    $hashes = @()

    foreach ($file in $files) {
        $relativePath = [System.IO.Path]::GetRelativePath($Root, $file.FullName)
        $hash = (Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256).Hash
        $hashes += [PSCustomObject]@{
            Path = $relativePath
            Hash = $hash
        }
    }

    return @($hashes)
}

function Convert-HashesToMap {
    param(
        [Parameter(Mandatory=$true)]
        [object[]]$Hashes
    )

    $map = @{}
    foreach ($item in @($Hashes)) {
        $map[$item.Path] = $item.Hash
    }
    return $map
}

function Compare-HashSets {
    param(
        [Parameter(Mandatory=$true)]
        [hashtable]$Before,

        [Parameter(Mandatory=$true)]
        [hashtable]$After
    )

    $failures = @()

    foreach ($path in @($Before.Keys | Sort-Object)) {
        if (-not $After.ContainsKey($path)) {
            $failures += "MISSING_AFTER: $path"
        } elseif ($Before[$path] -ne $After[$path]) {
            $failures += "HASH_CHANGED: $path"
        }
    }

    foreach ($path in @($After.Keys | Sort-Object)) {
        if (-not $Before.ContainsKey($path)) {
            $failures += "NEW_AFTER: $path"
        }
    }

    return @($failures)
}

try {
    Write-Host "Phase 2A deterministic reproducibility verification" -ForegroundColor Green
    Write-Host "Workspace: $Root"
    Write-Host "Canonical outputs checked: .csv, .json, .txt"
    Write-Host "Excluded outputs: out/audit/* and out/excel/*.xlsx"
    Write-Host ""

    Invoke-Pipeline
    $beforeHashes = @(Get-ProductionHashes)
    $before = Convert-HashesToMap -Hashes $beforeHashes

    if ($before.Count -eq 0) {
        throw "No canonical production outputs were found to hash. Check run_pipeline.py output folders."
    }

    Write-Host "[OK] First run completed. Canonical production files hashed: $($before.Count)" -ForegroundColor Green

    Invoke-Pipeline
    $afterHashes = @(Get-ProductionHashes)
    $after = Convert-HashesToMap -Hashes $afterHashes

    Write-Host "[OK] Second run completed. Canonical production files hashed: $($after.Count)" -ForegroundColor Green

    $failures = @(Compare-HashSets -Before $before -After $after)

    if ($failures.Count -gt 0) {
        Write-Host ""
        Write-Host "[FAIL] Reproducibility verification failed." -ForegroundColor Red
        foreach ($failure in $failures) {
            Write-Host " - $failure" -ForegroundColor Red
        }
        exit 1
    }

    Write-Host ""
    Write-Host "[OK] Reproducibility verification passed." -ForegroundColor Green
    Write-Host "[OK] Fresh rebuild succeeded, naming contract holds, and canonical production outputs are deterministic." -ForegroundColor Green
    exit 0
}
catch {
    Write-Host ""
    Write-Host "[ERROR] $($_.Exception.Message)" -ForegroundColor Red
    exit 1
}
