param(
  [string]$ObsVersion = "31.1.1",
  [string]$BridgeVersion = "0.1.0-experimental.5",
  [string]$CacheRoot = "$env:LOCALAPPDATA\LumiCompanionBuild"
)

$ErrorActionPreference = "Stop"
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
$nativeRoot = Join-Path $repoRoot "companion\native\obs-bridge"
$componentRoot = Join-Path $repoRoot "companion\src\Lumi.Companion.App\components\obs-bridge"
$obsRoot = Join-Path $CacheRoot "obs-$ObsVersion"
$runtimeArchive = Join-Path $obsRoot "obs-windows.zip"
$sourceArchive = Join-Path $obsRoot "obs-source.zip"
$runtimeRoot = Join-Path $obsRoot "runtime"
$sourceParent = Join-Path $obsRoot "source"
$sourceRoot = Join-Path $sourceParent "obs-studio-$ObsVersion"
$importRoot = Join-Path $obsRoot "imports"
$buildRoot = Join-Path $obsRoot "bridge-build"

$runtimeUrl = "https://github.com/obsproject/obs-studio/releases/download/$ObsVersion/OBS-Studio-$ObsVersion-Windows-x64.zip"
$sourceUrl = "https://github.com/obsproject/obs-studio/archive/refs/tags/$ObsVersion.zip"
$runtimeSha256 = "9d8dceb77acd8af04af23f877061f63c9bef78ca73d2093d0ccba1bb9104173f"
$sourceSha256 = "2c8427c10b55ac6d68008df2e9a3e82f4647aaad18f105e30d4713c2de678ccf"

function Get-VerifiedArchive([string]$Url, [string]$Path, [string]$ExpectedSha256) {
  if (!(Test-Path $Path) -or (Get-FileHash $Path -Algorithm SHA256).Hash.ToLowerInvariant() -ne $ExpectedSha256) {
    New-Item -ItemType Directory -Force -Path (Split-Path $Path) | Out-Null
    $partial = "$Path.partial"
    Remove-Item $partial -Force -ErrorAction SilentlyContinue
    Invoke-WebRequest -Uri $Url -OutFile $partial
    if ((Get-FileHash $partial -Algorithm SHA256).Hash.ToLowerInvariant() -ne $ExpectedSha256) {
      Remove-Item $partial -Force -ErrorAction SilentlyContinue
      throw "Checksum mismatch while downloading $Url"
    }
    Move-Item $partial $Path -Force
  }
}

function New-ImportLibrary([string]$Dll, [string]$Name, [string]$Dumpbin, [string]$LibExe) {
  $definition = Join-Path $importRoot "$Name.def"
  $dumpOutputPath = Join-Path $importRoot "$Name.exports.txt"
  $dump = Start-Process -FilePath $Dumpbin -ArgumentList @("/nologo", "/exports", "`"$Dll`"") -RedirectStandardOutput $dumpOutputPath -NoNewWindow -Wait -PassThru
  if ($dump.ExitCode) { throw "Could not inspect exports for $Name." }
  $dumpOutput = Get-Content $dumpOutputPath
  $exports = @($dumpOutput | ForEach-Object {
    if ($_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+(\S+)') { $Matches[1] }
  })
  @("LIBRARY $Name", "EXPORTS") + ($exports | ForEach-Object { "  $_" }) | Set-Content -Encoding Ascii $definition
  & $LibExe /nologo /machine:x64 "/def:$definition" "/out:$(Join-Path $importRoot "$Name.lib")"
  if ($LASTEXITCODE) { throw "Could not create the $Name import library." }
}

Get-VerifiedArchive $runtimeUrl $runtimeArchive $runtimeSha256
Get-VerifiedArchive $sourceUrl $sourceArchive $sourceSha256
if (!(Test-Path (Join-Path $runtimeRoot "bin\64bit\obs.dll"))) {
  Remove-Item $runtimeRoot -Recurse -Force -ErrorAction SilentlyContinue
  Expand-Archive $runtimeArchive $runtimeRoot
}
if (!(Test-Path (Join-Path $sourceRoot "libobs\obs-module.h"))) {
  Remove-Item $sourceParent -Recurse -Force -ErrorAction SilentlyContinue
  Expand-Archive $sourceArchive $sourceParent
}

$vswhere = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\Installer\vswhere.exe"
$vsRoot = if (Test-Path $vswhere) { & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath }
if (!$vsRoot) { $vsRoot = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\2022\BuildTools" }
if (!(Test-Path $vsRoot)) { throw "Visual Studio 2022 C++ Build Tools are required." }
$vcTools = Get-ChildItem (Join-Path $vsRoot "VC\Tools\MSVC") -Directory | Sort-Object { [version]$_.Name } | Select-Object -Last 1
$toolRoot = Join-Path $vcTools.FullName "bin\Hostx64\x64"
$dumpbin = Join-Path $toolRoot "dumpbin.exe"
$lib = Join-Path $toolRoot "lib.exe"
$cmakeCommand = Get-Command cmake.exe -ErrorAction SilentlyContinue
$cmake = if ($cmakeCommand) { $cmakeCommand.Source } else {
  Get-ChildItem (Join-Path $env:APPDATA "Python") -Filter cmake.exe -File -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
}
if (!$cmake) { throw "CMake 3.28 or newer is required." }

New-Item -ItemType Directory -Force -Path $importRoot | Out-Null
New-ImportLibrary (Join-Path $runtimeRoot "bin\64bit\obs.dll") "obs" $dumpbin $lib
New-ImportLibrary (Join-Path $runtimeRoot "bin\64bit\obs-frontend-api.dll") "obs-frontend-api" $dumpbin $lib

$configureArguments = @("-S", "`"$nativeRoot`"", "-B", "`"$buildRoot`"", "-G", "`"Visual Studio 17 2022`"", "-A", "x64", "`"-DOBS_SOURCE_DIR=$sourceRoot`"", "`"-DOBS_IMPORT_DIR=$importRoot`"", "`"-DLUMI_BRIDGE_VERSION=$BridgeVersion`"")
$configured = Start-Process -FilePath $cmake -ArgumentList $configureArguments -NoNewWindow -Wait -PassThru
if ($configured.ExitCode) { throw "OBS bridge configuration failed." }
$built = Start-Process -FilePath $cmake -ArgumentList @("--build", "`"$buildRoot`"", "--config", "Release") -NoNewWindow -Wait -PassThru
if ($built.ExitCode) { throw "OBS bridge build failed." }

New-Item -ItemType Directory -Force -Path $componentRoot | Out-Null
$bridgeDll = Join-Path $buildRoot "Release\lumi-obs-bridge.dll"
Copy-Item $bridgeDll (Join-Path $componentRoot "lumi-obs-bridge.dll") -Force
Copy-Item (Join-Path $nativeRoot "data\locale\en-US.ini") (Join-Path $componentRoot "en-US.ini") -Force
$manifest = [ordered]@{
  version = $BridgeVersion
  sha256 = (Get-FileHash $bridgeDll -Algorithm SHA256).Hash.ToLowerInvariant()
  obs_minimum_version = "31.0.0"
}
$manifestJson = $manifest | ConvertTo-Json
[IO.File]::WriteAllText((Join-Path $componentRoot "manifest.json"), $manifestJson, [Text.UTF8Encoding]::new($false))
Write-Host "Built OBS bridge $BridgeVersion at $componentRoot"
