# Build script for ekDNSHelper
# Builds the executables using the go1.20 toolchain
#
# USAGE:
#   .\build.ps1                     # Standard build for current platform (Windows amd64)
#   .\build.ps1 -Release            # Build for all platforms (no debug symbols)
#   .\build.ps1 -Clean              # Clean build (removes old files first)
#   .\build.ps1 -CrossCompile       # Build for all platforms
#   .\build.ps1 -Package            # Create release packages (ZIP / tar.gz)
#   .\build.ps1 -Release -Package   # Full release: optimized build + packages
#
# OUTPUT:
#   - Default build:     build\ekdns.exe
#   - Cross-compiled:    build\ekdns-<os>-<arch>[.exe]
#   - Release packages:  releases\ekdns-<version>-<os>-<arch>.zip / .tar.gz

param(
    [string]$OutputDir = "build",
    [string]$OutputName = "ekdns",
    [switch]$Release,
    [switch]$Clean,
    [switch]$CrossCompile,
    [switch]$Package
)

$ErrorActionPreference = "Stop"

# Go binary — use go1.20 toolchain
$GoCmd = "go1.20"

# Get version information from git or use defaults
$gitHash = "unknown"
$gitTag = "dev"

$prevErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = "Continue"

try {
    $gitHashResult = git rev-parse --short HEAD 2>&1
    if ($LASTEXITCODE -eq 0 -and $gitHashResult -and $gitHashResult -notmatch "fatal|error") {
        $gitHash = $gitHashResult.Trim()
    }

    $gitTagResult = git describe --tags --always --dirty 2>&1
    if ($LASTEXITCODE -eq 0 -and $gitTagResult -and $gitTagResult -notmatch "fatal|error") {
        $gitTag = $gitTagResult.Trim()
    }
} catch {
    # Git not available or not a git repository — use defaults
}

$ErrorActionPreference = $prevErrorActionPreference

$buildTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"

Write-Host "============================================" -ForegroundColor Cyan
Write-Host "  ekDNSHelper Build" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "  Version: $gitTag" -ForegroundColor Gray
Write-Host "  Commit:  $gitHash" -ForegroundColor Gray
Write-Host "  Time:    $buildTime" -ForegroundColor Gray
Write-Host ""

# Clean output directory if requested
if ($Clean) {
    Write-Host "Cleaning output directory..." -ForegroundColor Yellow
    if (Test-Path $OutputDir) {
        Remove-Item -Path $OutputDir -Recurse -Force
    }
    Write-Host "Cleaning Go caches..." -ForegroundColor Yellow
    & $GoCmd clean -cache -testcache 2>$null
}

# Ensure output directory exists
if (-not (Test-Path $OutputDir)) {
    New-Item -ItemType Directory -Path $OutputDir | Out-Null
    Write-Host "Created output directory: $OutputDir" -ForegroundColor Green
}

# Build flags — always inject version and copyright year; release builds also strip debug symbols.
$buildYear = (Get-Date).Year
$injectedFlags = "-X main.version=$gitTag -X main.copyrightYear=$buildYear"
if ($Release) {
    $ldflags = "-s -w $injectedFlags"
    Write-Host "Building RELEASE version (optimized, no debug symbols)..." -ForegroundColor Green
} else {
    $ldflags = $injectedFlags
    Write-Host "Building DEBUG version (with debug symbols)..." -ForegroundColor Yellow
}

# Disable CGO for static binaries
$env:CGO_ENABLED = "0"

$platforms = @(
    @{ GOOS = "windows"; GOARCH = "386";   Suffix = ".exe" },
    @{ GOOS = "windows"; GOARCH = "amd64"; Suffix = ".exe" },
    @{ GOOS = "linux";   GOARCH = "amd64"; Suffix = ""     },
    @{ GOOS = "linux";   GOARCH = "arm64"; Suffix = ""     },
    @{ GOOS = "darwin";  GOARCH = "amd64"; Suffix = ""     },
    @{ GOOS = "darwin";  GOARCH = "arm64"; Suffix = ""     }
)

function Build-Binary {
    param(
        [string]$GOOS,
        [string]$GOARCH,
        [string]$OutputPath
    )

    $env:GOOS   = $GOOS
    $env:GOARCH = $GOARCH

    if ($ldflags) {
        & $GoCmd build -ldflags $ldflags -o $OutputPath .
    } else {
        & $GoCmd build -o $OutputPath .
    }

    return $LASTEXITCODE
}

try {
    if ($CrossCompile -or $Release) {
        Write-Host "Cross-compiling for all platforms..." -ForegroundColor Cyan
        Write-Host ""

        foreach ($platform in $platforms) {
            $outputFile = "$OutputName-$($platform.GOOS)-$($platform.GOARCH)$($platform.Suffix)"
            $outputPath = Join-Path $OutputDir $outputFile

            Write-Host "  Building $outputFile..." -ForegroundColor Gray

            $result = Build-Binary -GOOS $platform.GOOS -GOARCH $platform.GOARCH -OutputPath $outputPath

            if ($result -eq 0) {
                $fileSizeMB = [math]::Round((Get-Item $outputPath).Length / 1MB, 2)
                Write-Host "    [OK] $fileSizeMB MB" -ForegroundColor Green
            } else {
                Write-Host "    [FAILED]" -ForegroundColor Red
                exit $result
            }
        }

        Write-Host ""
        Write-Host "Cross-compilation complete!" -ForegroundColor Green

    } else {
        $outputPath = Join-Path $OutputDir "$OutputName.exe"

        Write-Host "Compiling for Windows (amd64)..." -ForegroundColor Cyan

        $result = Build-Binary -GOOS "windows" -GOARCH "amd64" -OutputPath $outputPath

        if ($result -eq 0) {
            $fileSizeMB = [math]::Round((Get-Item $outputPath).Length / 1MB, 2)
            Write-Host "Build successful!" -ForegroundColor Green
            Write-Host "  Output: $outputPath" -ForegroundColor Gray
            Write-Host "  Size:   $fileSizeMB MB" -ForegroundColor Gray
        } else {
            Write-Host "Build failed with exit code: $result" -ForegroundColor Red
            exit $result
        }
    }
} catch {
    Write-Host "Build error: $_" -ForegroundColor Red
    exit 1
}

Write-Host ""
Write-Host "Build complete!" -ForegroundColor Green
Write-Host ""
Write-Host "Usage:" -ForegroundColor Cyan
Write-Host "  .\$OutputDir\$OutputName.exe --help" -ForegroundColor White
Write-Host "  .\$OutputDir\$OutputName.exe add <hostname> <ip>" -ForegroundColor White

# Create release packages if requested
if ($Package) {
    Write-Host ""
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host "  Creating Release Packages" -ForegroundColor Cyan
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host ""

    $releasesDir = "releases"
    if (-not (Test-Path $releasesDir)) {
        New-Item -ItemType Directory -Path $releasesDir | Out-Null
        Write-Host "Created releases directory: $releasesDir" -ForegroundColor Green
    }

    foreach ($platform in $platforms) {
        $platformName = "$($platform.GOOS)-$($platform.GOARCH)"
        $packageName  = "$OutputName-$gitTag-$platformName"
        $packageDir   = Join-Path $releasesDir $packageName

        $isWindowsPlatform = $platform.GOOS -eq "windows"
        if ($isWindowsPlatform) {
            $archivePath = "$packageDir.zip"
            $exeName     = "$OutputName.exe"
        } else {
            $archivePath = "$packageDir.tar.gz"
            $exeName     = $OutputName
        }

        Write-Host "Creating package for $platformName..." -ForegroundColor Cyan

        if (Test-Path $packageDir) {
            Remove-Item -Path $packageDir -Recurse -Force
        }
        if (Test-Path $archivePath) {
            try {
                Remove-Item -Path $archivePath -Force -ErrorAction Stop
            } catch {
                Write-Host "  Warning: Could not remove old package (file may be in use)" -ForegroundColor Yellow
                continue
            }
        }

        New-Item -ItemType Directory -Path $packageDir | Out-Null

        # Copy the binary
        $binaryFile = "$OutputName-$platformName$($platform.Suffix)"
        $binaryPath = Join-Path $OutputDir $binaryFile
        if (-not (Test-Path $binaryPath)) {
            Write-Host "  Error: Binary not found at $binaryPath. Run build first." -ForegroundColor Red
            continue
        }
        Copy-Item -Path $binaryPath -Destination (Join-Path $packageDir $exeName)

        # Copy README if present
        if (Test-Path "README.md") {
            Copy-Item -Path "README.md" -Destination (Join-Path $packageDir "README.md")
        }

        # VERSION.txt
        @"
ekDNSHelper Version Information
===============================

Version:    $gitTag
Git Commit: $gitHash
Build Time: $buildTime
Platform:   $platformName

Run '$exeName --help' for usage information.
"@ | Out-File -FilePath (Join-Path $packageDir "VERSION.txt") -Encoding UTF8

        # CHECKSUMS.txt
        $exeHash = (Get-FileHash -Path (Join-Path $packageDir $exeName) -Algorithm SHA256).Hash
        @"
ekDNSHelper Release Checksums
Version: $gitTag
Build: $gitHash
Platform: $platformName

SHA256 Checksums:
-----------------
$exeName
  $exeHash

To verify (PowerShell):
  `$hash = (Get-FileHash -Path $exeName -Algorithm SHA256).Hash
  if (`$hash -eq "$exeHash") { Write-Host "Verified!" -ForegroundColor Green }

To verify (Linux/macOS):
  echo "$exeHash  $exeName" | sha256sum -c -
"@ | Out-File -FilePath (Join-Path $packageDir "CHECKSUMS.txt") -Encoding UTF8

        # Create archive
        try {
            if ($isWindowsPlatform) {
                Compress-Archive -Path "$packageDir\*" -DestinationPath $archivePath -CompressionLevel Optimal -Force
            } else {
                Push-Location $releasesDir
                try {
                    tar -czf "$packageName.tar.gz" -C . $packageName 2>$null
                    if ($LASTEXITCODE -ne 0) {
                        Write-Host "  Warning: tar not available, using ZIP format" -ForegroundColor Yellow
                        $archivePath = "$packageDir.zip"
                        Compress-Archive -Path "$packageDir\*" -DestinationPath $archivePath -CompressionLevel Optimal -Force
                    }
                } finally {
                    Pop-Location
                }
            }

            $archiveSizeMB = [math]::Round((Get-Item $archivePath).Length / 1MB, 2)
            Remove-Item -Path $packageDir -Recurse -Force
            Write-Host "  [OK] $archivePath ($archiveSizeMB MB)" -ForegroundColor Green

        } catch {
            Write-Host "  Error creating package: $_" -ForegroundColor Red
            if (Test-Path $packageDir) { Remove-Item -Path $packageDir -Recurse -Force }
        }
    }

    Write-Host ""
    Write-Host "Release packaging complete!" -ForegroundColor Green
    Write-Host ""
    Write-Host "Package contents:" -ForegroundColor Cyan
    Write-Host "  - ekdns executable" -ForegroundColor Gray
    Write-Host "  - README.md (if present)" -ForegroundColor Gray
    Write-Host "  - VERSION.txt" -ForegroundColor Gray
    Write-Host "  - CHECKSUMS.txt (integrity verification)" -ForegroundColor Gray
}
