[CmdletBinding()]
param()

$ErrorActionPreference = "Stop"
$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$pythonPath = Join-Path $projectRoot ".venv\Scripts\python.exe"
$buildRoot = Join-Path $projectRoot "build"
$distRoot = Join-Path $projectRoot "dist"
$releaseRoot = Join-Path $projectRoot "release"
$version = "1.0.0"
$packageName = "MusicGridStudio_v${version}_Windows_x64"
$packageDirectory = Join-Path $releaseRoot $packageName
$zipPath = Join-Path $releaseRoot ($packageName + ".zip")

if (-not (Test-Path -LiteralPath $pythonPath)) {
    throw "Run setup_musicgridstudio.bat before building the Windows package."
}

foreach ($target in @($buildRoot, $distRoot)) {
    $fullTarget = [System.IO.Path]::GetFullPath($target)
    if (-not $fullTarget.StartsWith($projectRoot + "\", [System.StringComparison]::OrdinalIgnoreCase)) {
        throw "Refusing to clean a path outside the project: $fullTarget"
    }
    if (Test-Path -LiteralPath $fullTarget) {
        Remove-Item -LiteralPath $fullTarget -Recurse -Force
    }
}
New-Item -ItemType Directory -Path $releaseRoot -Force | Out-Null
foreach ($target in @($packageDirectory, $zipPath)) {
    $fullTarget = [System.IO.Path]::GetFullPath($target)
    if (-not $fullTarget.StartsWith($releaseRoot + "\", [System.StringComparison]::OrdinalIgnoreCase)) {
        throw "Refusing to clean a path outside the release directory: $fullTarget"
    }
    if (Test-Path -LiteralPath $fullTarget) {
        Remove-Item -LiteralPath $fullTarget -Recurse -Force
    }
}

& $pythonPath -m PyInstaller `
    --noconfirm `
    --clean `
    --workpath $buildRoot `
    --distpath $distRoot `
    (Join-Path $PSScriptRoot "MusicGridStudio.spec")
if ($LASTEXITCODE -ne 0) {
    throw "PyInstaller failed with exit code $LASTEXITCODE."
}

$builtDirectory = Join-Path $distRoot "MusicGridStudio"
if (-not (Test-Path -LiteralPath (Join-Path $builtDirectory "MusicGridStudio.exe"))) {
    throw "The expected MusicGridStudio.exe was not generated."
}
$builtUpdater = Join-Path $distRoot "MusicGridStudioUpdater.exe"
if (-not (Test-Path -LiteralPath $builtUpdater)) {
    throw "The expected MusicGridStudioUpdater.exe was not generated."
}

New-Item -ItemType Directory -Path $packageDirectory -Force | Out-Null
Copy-Item -Path (Join-Path $builtDirectory "*") -Destination $packageDirectory -Recurse
Copy-Item -LiteralPath $builtUpdater -Destination $packageDirectory
Copy-Item -LiteralPath (Join-Path $projectRoot "DISTRIBUTION_INFO.txt") -Destination $packageDirectory
Copy-Item -LiteralPath (Join-Path $projectRoot "THIRD_PARTY_NOTICES.txt") -Destination $packageDirectory
Copy-Item -LiteralPath (Join-Path $projectRoot "README.md") -Destination $packageDirectory
$installManifest = [ordered]@{
    schema = 1
    product = "MusicGridStudio"
    version = $version
    architecture = "windows-x64"
    publisher = "LeLien Consulting"
    update_schema = 1
}
$installManifest |
    ConvertTo-Json |
    Set-Content -LiteralPath (Join-Path $packageDirectory "install_manifest.json") -Encoding UTF8

$sourceDirectory = Join-Path $packageDirectory "source"
$sourcePackageDirectory = Join-Path $sourceDirectory "musicgridstudio"
New-Item -ItemType Directory -Path $sourcePackageDirectory -Force | Out-Null
Copy-Item -Path (Join-Path $projectRoot "musicgridstudio\*.py") -Destination $sourcePackageDirectory
foreach ($sourceFile in @(
    "app.py",
    "requirements.txt",
    "build-requirements.txt",
    "README.md",
    "DISTRIBUTION_INFO.txt",
    "THIRD_PARTY_NOTICES.txt"
)) {
    Copy-Item -LiteralPath (Join-Path $projectRoot $sourceFile) -Destination $sourceDirectory
}
$sourcePackagingDirectory = Join-Path $sourceDirectory "packaging"
New-Item -ItemType Directory -Path $sourcePackagingDirectory -Force | Out-Null
Copy-Item -Path (Join-Path $PSScriptRoot "*") -Destination $sourcePackagingDirectory -Recurse
$sourceAssetsDirectory = Join-Path $sourceDirectory "assets"
New-Item -ItemType Directory -Path $sourceAssetsDirectory -Force | Out-Null
Copy-Item -Path (Join-Path $projectRoot "assets\*") -Destination $sourceAssetsDirectory

$sitePackages = (& $pythonPath -c "import sysconfig; print(sysconfig.get_paths()['purelib'])").Trim()
$licenseRoot = Join-Path $packageDirectory "licenses"
New-Item -ItemType Directory -Path $licenseRoot -Force | Out-Null
$licensePackages = @(
    "cffi",
    "mutagen",
    "numpy",
    "pycparser",
    "pyside6",
    "pyside6_addons",
    "pyside6_essentials",
    "shiboken6",
    "sounddevice",
    "soundfile"
)
foreach ($licensePackage in $licensePackages) {
    $distInfo = Get-ChildItem -LiteralPath $sitePackages -Directory |
        Where-Object { $_.Name -like ($licensePackage + "-*.dist-info") } |
        Select-Object -First 1
    if ($null -eq $distInfo) {
        throw "License metadata was not found for $licensePackage."
    }
    $licenseTarget = Join-Path $licenseRoot $licensePackage
    New-Item -ItemType Directory -Path $licenseTarget -Force | Out-Null
    $licenseDirectory = Join-Path $distInfo.FullName "licenses"
    if (Test-Path -LiteralPath $licenseDirectory) {
        Copy-Item -Path (Join-Path $licenseDirectory "*") -Destination $licenseTarget -Recurse
    }
    Get-ChildItem -LiteralPath $distInfo.FullName -File |
        Where-Object { $_.Name -match '^(LICENSE|COPYING|NOTICE)' } |
        Copy-Item -Destination $licenseTarget
}

$pythonBase = (& $pythonPath -c "import sys; print(sys.base_prefix)").Trim()
Copy-Item -LiteralPath (Join-Path $pythonBase "LICENSE.txt") -Destination (Join-Path $licenseRoot "PYTHON_LICENSE.txt")
Copy-Item -LiteralPath (Join-Path $sitePackages "_soundfile_data\COPYING") -Destination (Join-Path $licenseRoot "LIBSNDFILE_COPYING.txt")
Copy-Item -LiteralPath (Join-Path $sitePackages "_sounddevice_data\portaudio-binaries\README.md") -Destination (Join-Path $licenseRoot "PORTAUDIO_README.md")

Compress-Archive -LiteralPath $packageDirectory -DestinationPath $zipPath -CompressionLevel Optimal
Write-Host "Created: $zipPath"
