param(
  [string]$OutputDirectory = "dist\\video-haus-cpanel-dropin",
  [string]$ZipFilePath = "dist\\video-haus-cpanel-dropin.zip"
)

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

$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$resolvedOutputDirectory = Join-Path $projectRoot $OutputDirectory
$resolvedZipFilePath = Join-Path $projectRoot $ZipFilePath
$bundleTempDirectory = Join-Path $projectRoot ".tmp\\bundle-build"
$distDirectory = Join-Path $projectRoot "dist"

function Expand-GzipFile {
  param(
    [Parameter(Mandatory = $true)][string]$SourceGzipPath,
    [Parameter(Mandatory = $true)][string]$DestinationPath
  )

  $sourceStream = [System.IO.File]::OpenRead($SourceGzipPath)
  try {
    $destinationStream = [System.IO.File]::Create($DestinationPath)
    try {
      $gzipStream = New-Object System.IO.Compression.GzipStream(
        $sourceStream,
        [System.IO.Compression.CompressionMode]::Decompress
      )
      try {
        $gzipStream.CopyTo($destinationStream)
      } finally {
        $gzipStream.Dispose()
      }
    } finally {
      $destinationStream.Dispose()
    }
  } finally {
    $sourceStream.Dispose()
  }
}

function Get-LinuxFfmpegBinaryPath {
  param(
    [Parameter(Mandatory = $true)][string]$ProjectRoot,
    [Parameter(Mandatory = $true)][string]$TempDirectory
  )

  $linuxBinaryFromNodeModules = Join-Path $ProjectRoot "node_modules\\ffmpeg-static\\ffmpeg"
  if (Test-Path -LiteralPath $linuxBinaryFromNodeModules) {
    return $linuxBinaryFromNodeModules
  }

  $ffmpegPackagePath = Join-Path $ProjectRoot "node_modules\\ffmpeg-static\\package.json"
  if (-not (Test-Path -LiteralPath $ffmpegPackagePath)) {
    return $null
  }

  $packageJson = Get-Content -LiteralPath $ffmpegPackagePath -Raw | ConvertFrom-Json
  $releaseTag = $packageJson."ffmpeg-static"."binary-release-tag"
  if (-not $releaseTag) {
    return $null
  }

  New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null

  $downloadUrl = "https://github.com/eugeneware/ffmpeg-static/releases/download/$releaseTag/ffmpeg-linux-x64.gz"
  $downloadedGzipPath = Join-Path $TempDirectory "ffmpeg-linux-x64.gz"
  $expandedBinaryPath = Join-Path $TempDirectory "ffmpeg-linux-x64"

  Write-Host "Downloading Linux ffmpeg binary from $downloadUrl ..." -ForegroundColor Cyan
  Invoke-WebRequest -Uri $downloadUrl -OutFile $downloadedGzipPath
  Expand-GzipFile -SourceGzipPath $downloadedGzipPath -DestinationPath $expandedBinaryPath

  return $expandedBinaryPath
}

function Get-LinuxYtDlpBinaryPath {
  param(
    [Parameter(Mandatory = $true)][string]$ProjectRoot,
    [Parameter(Mandatory = $true)][string]$TempDirectory
  )

  New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null

  $downloadUrl = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp"
  $downloadedBinaryPath = Join-Path $TempDirectory "yt-dlp.py"

  Write-Host "Downloading yt-dlp script from $downloadUrl ..." -ForegroundColor Cyan
  Invoke-WebRequest -Uri $downloadUrl -OutFile $downloadedBinaryPath

  return $downloadedBinaryPath
}

Push-Location $projectRoot
try {
  # Avoid recursive bundle bloat when standalone tracing pulls in project root.
  if (Test-Path -LiteralPath $distDirectory) {
    Remove-Item -LiteralPath $distDirectory -Recurse -Force
  }
  New-Item -ItemType Directory -Path $distDirectory -Force | Out-Null

  Write-Host "Building production app..." -ForegroundColor Cyan
  npm run build

  if (Test-Path -LiteralPath $resolvedOutputDirectory) {
    Remove-Item -LiteralPath $resolvedOutputDirectory -Recurse -Force
  }
  New-Item -ItemType Directory -Path $resolvedOutputDirectory -Force | Out-Null

  Write-Host "Preparing standalone structure for cPanel..." -ForegroundColor Cyan
  $outputDotNext = Join-Path $resolvedOutputDirectory ".next"
  $outputStandalone = Join-Path $outputDotNext "standalone"
  New-Item -ItemType Directory -Path $outputStandalone -Force | Out-Null

  Copy-Item -Path ".next\\standalone\\*" -Destination $outputStandalone -Recurse -Force

  # Defensive cleanup: if tracing pulled repository artifacts into standalone, remove them.
  foreach ($tracedPath in @("dist", ".git", ".tmp")) {
    $candidate = Join-Path $outputStandalone $tracedPath
    if (Test-Path -LiteralPath $candidate) {
      Remove-Item -LiteralPath $candidate -Recurse -Force
    }
  }

  $outputStandaloneStatic = Join-Path $outputStandalone ".next\\static"
  New-Item -ItemType Directory -Path $outputStandaloneStatic -Force | Out-Null
  Copy-Item -Path ".next\\static\\*" -Destination $outputStandaloneStatic -Recurse -Force

  Copy-Item -Path "public" -Destination (Join-Path $outputStandalone "public") -Recurse -Force

  $linuxBundleBinaryDirectory = Join-Path $outputStandalone "bin\\linux"
  New-Item -ItemType Directory -Path $linuxBundleBinaryDirectory -Force | Out-Null

  $linuxFfprobeSourcePath = Join-Path $projectRoot "node_modules\\ffprobe-static\\bin\\linux\\x64\\ffprobe"
  if (Test-Path -LiteralPath $linuxFfprobeSourcePath) {
    Copy-Item -LiteralPath $linuxFfprobeSourcePath -Destination (Join-Path $linuxBundleBinaryDirectory "ffprobe") -Force
    Write-Host "Included Linux ffprobe binary." -ForegroundColor Green
  } else {
    Write-Warning "Linux ffprobe binary was not found in node_modules\\ffprobe-static. Set FFPROBE_PATH manually on the host."
  }

  $linuxFfmpegSourcePath = Get-LinuxFfmpegBinaryPath -ProjectRoot $projectRoot -TempDirectory $bundleTempDirectory
  if ($linuxFfmpegSourcePath -and (Test-Path -LiteralPath $linuxFfmpegSourcePath)) {
    Copy-Item -LiteralPath $linuxFfmpegSourcePath -Destination (Join-Path $linuxBundleBinaryDirectory "ffmpeg") -Force
    Write-Host "Included Linux ffmpeg binary." -ForegroundColor Green
  } else {
    Write-Warning "Linux ffmpeg binary was not available. Set FFMPEG_PATH manually on the host."
  }

  $linuxYtDlpSourcePath = Get-LinuxYtDlpBinaryPath -ProjectRoot $projectRoot -TempDirectory $bundleTempDirectory
  if ($linuxYtDlpSourcePath -and (Test-Path -LiteralPath $linuxYtDlpSourcePath)) {
    $ytDlpScriptPath = Join-Path $linuxBundleBinaryDirectory "yt-dlp.py"
    Copy-Item -LiteralPath $linuxYtDlpSourcePath -Destination $ytDlpScriptPath -Force

    $ytDlpLauncherPath = Join-Path $linuxBundleBinaryDirectory "yt-dlp"
    [System.IO.File]::WriteAllText(
      $ytDlpLauncherPath,
      @'
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
YT_DLP_SCRIPT="$SCRIPT_DIR/yt-dlp.py"

if [[ ! -f "$YT_DLP_SCRIPT" ]]; then
  echo "yt-dlp launcher could not find script at '$YT_DLP_SCRIPT'." >&2
  exit 127
fi

supports_python() {
  local candidate="$1"
  "$candidate" - <<'PY' >/dev/null 2>&1
import sys
raise SystemExit(0 if sys.version_info >= (3, 10) else 1)
PY
}

declare -a CANDIDATES=()
if [[ -n "${YT_DLP_PYTHON:-}" ]]; then
  CANDIDATES+=("$YT_DLP_PYTHON")
fi

CANDIDATES+=(
  "/opt/alt/python313/bin/python3"
  "/opt/alt/python312/bin/python3"
  "/opt/alt/python311/bin/python3"
  "/opt/alt/python310/bin/python3"
  "/usr/bin/python3"
  "/bin/python3"
  "python3"
)

for candidate in "${CANDIDATES[@]}"; do
  if command -v "$candidate" >/dev/null 2>&1; then
    resolved_candidate="$(command -v "$candidate")"
  elif [[ -x "$candidate" ]]; then
    resolved_candidate="$candidate"
  else
    continue
  fi

  if supports_python "$resolved_candidate"; then
    exec "$resolved_candidate" "$YT_DLP_SCRIPT" "$@"
  fi
done

echo "No compatible Python runtime (>=3.10) found for yt-dlp. Set YT_DLP_PYTHON to a Python 3.10+ executable path." >&2
exit 127
'@,
      [System.Text.UTF8Encoding]::new($false)
    )

    Write-Host "Included Linux yt-dlp launcher + script (auto Python 3.10+ detection)." -ForegroundColor Green
  } else {
    Write-Warning "yt-dlp script was not available. Set YT_DLP_PATH manually on the host."
  }

  $appJsPath = Join-Path $resolvedOutputDirectory "app.js"
  Set-Content -LiteralPath $appJsPath -Encoding ascii -Value @'
const fs = require("node:fs");
const path = require("node:path");

function wireBundledBinary(binaryName, envVariable) {
  if (process.env[envVariable]) {
    return;
  }

  const extension = process.platform === "win32" ? ".exe" : "";
  const candidatePath = path.join(__dirname, ".next", "standalone", "bin", process.platform, `${binaryName}${extension}`);
  if (!fs.existsSync(candidatePath)) {
    return;
  }

  if (process.platform !== "win32") {
    try {
      fs.chmodSync(candidatePath, 0o755);
    } catch {
      // Best effort only; host may still allow execution with existing perms.
    }
  }

  process.env[envVariable] = candidatePath;
}

wireBundledBinary("ffmpeg", "FFMPEG_PATH");
wireBundledBinary("ffprobe", "FFPROBE_PATH");
wireBundledBinary("yt-dlp", "YT_DLP_PATH");

require("./.next/standalone/server.js");
'@

  $serverJsPath = Join-Path $resolvedOutputDirectory "server.js"
  Set-Content -LiteralPath $serverJsPath -Encoding ascii -Value "require('./app.js');`n"

  $startCmdPath = Join-Path $resolvedOutputDirectory "start.cmd"
  Set-Content -LiteralPath $startCmdPath -Encoding ascii -Value "@echo off`r`nset NODE_ENV=production`r`nnode app.js`r`n"

  $startShPath = Join-Path $resolvedOutputDirectory "start.sh"
  Set-Content -LiteralPath $startShPath -Encoding ascii -Value "#!/usr/bin/env sh`nexport NODE_ENV=production`nnode app.js`n"

  $envExamplePath = Join-Path $resolvedOutputDirectory ".env.example"
  Set-Content -LiteralPath $envExamplePath -Encoding utf8 -Value @"
NODE_ENV=production
PORT=3000
HOSTNAME=0.0.0.0
NEXT_PUBLIC_SITE_URL=https://video.haus
SITE_URL=https://video.haus
FFMPEG_PATH=
FFPROBE_PATH=
YT_DLP_PATH=
YT_DLP_COOKIES_PATH=
INSTAGRAM_COOKIES_PATH=
YT_DLP_PYTHON=
VIDEO_HAUS_TEMP_ROOT=.tmp/media
VIDEO_HAUS_MAX_UPLOAD_SIZE_BYTES=1000000000
VIDEO_HAUS_COMMAND_TIMEOUT_MS=120000
VIDEO_HAUS_CLEANUP_MAX_AGE_MS=1800000
"@

  $deployReadmePath = Join-Path $resolvedOutputDirectory "DEPLOY.txt"
  Set-Content -LiteralPath $deployReadmePath -Encoding utf8 -Value @"
video.haus cPanel drop-in bundle
================================

Set Node app startup file to: app.js
Fallback startup file: server.js
Do NOT run NPM install for this bundle.

This package includes:
- .next/standalone runtime (with its own node_modules)
- .next/static
- public assets
- Linux ffmpeg/ffprobe fallbacks in .next/standalone/bin/linux
- Linux yt-dlp launcher + script (auto-detects Python 3.10+)
- If extraction permissions look wrong, run: chmod -R u+rwX,go+rX /home/USERNAME/video.haus/apps/videohaus_clean
"@

  if (Test-Path -LiteralPath $resolvedZipFilePath) {
    Remove-Item -LiteralPath $resolvedZipFilePath -Force
  }

  $itemsToZip = Get-ChildItem -LiteralPath $resolvedOutputDirectory -Force
  Compress-Archive -LiteralPath $itemsToZip.FullName -DestinationPath $resolvedZipFilePath -CompressionLevel Optimal -Force

  Write-Host "cPanel bundle created successfully." -ForegroundColor Green
  Write-Host "Folder: $resolvedOutputDirectory" -ForegroundColor Green
  Write-Host "Zip:    $resolvedZipFilePath" -ForegroundColor Green
} finally {
  Pop-Location
}
