#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
    scripts/run-hypertwist-remote-exact-source-browser-package-refresh.sh

Options:
  --worktree-root <path>
      Optional Windows worktree root. Defaults to C:\HyperTwist_worktrees\phase10validate.

  --report-stamp <YYYYMMDD>
      Optional suffix used for the browser automation report and package archive.
      Defaults to the current UTC date.

  --fallback-worktree-root <path>
      Optional fallback Windows worktree root to use if the primary refresh
      fails. Useful when the maintained worktree is temporarily locked by
      another Windows-side process.

  --browser-filter <automation-filter>
      Optional Unreal automation filter. Defaults to HyperTwist.Browser.

  --browser-report-name <name>
      Optional explicit browser automation report name. Defaults to
      Browser-ExactSource-<report-stamp>.

  --package-archive-dir <path>
      Optional Windows archive directory for the higher-dimensional package run.
      Defaults to <worktree-root>_packaged_phase6c_higherdim_refresh_<report-stamp>.

  --sync-file <repo-relative-path>
      Optional repo-relative file to sync into the remote Windows worktree before
      validation. May be repeated.

  --skip-build
      Skip the remote Unreal editor build step.

  --skip-browser-automation
      Skip the HyperTwist.Browser automation refresh.

  --skip-package
      Skip the higher-dimensional package refresh.

  --skip-browser-report-pull
      Skip pulling the browser automation index.json back into docs/generated.

  --skip-package-report-pull
      Skip pulling the higher-dimensional package validation report back into
      docs/generated.

  --skip-summary-refresh
      Skip re-rendering website/src/shared/generated/windows-package-validation-summary.json.

  --skip-exact-source-support-sync
      Skip syncing the bounded exact-source browser/package support files that
      the fallback Windows validation root needs for truthful browser/package
      refreshes.

  --dry-run
      Print the wrapper invocations without executing them.

Environment:
  HYPERTWIST_REMOTE_WINDOWS_PASSWORD      Required by the underlying remote wrappers.
  HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT Optional default for --worktree-root.
  HYPERTWIST_REMOTE_WINDOWS_FALLBACK_WORKTREE_ROOT
                                         Optional default for --fallback-worktree-root.
  HYPERTWIST_REMOTE_WINDOWS_SKIP_EXACT_SOURCE_SUPPORT_SYNC
                                         Optional default for --skip-exact-source-support-sync.
EOF
}

ps_single_quote() {
  printf "'%s'" "${1//\'/\'\'}"
}

run_or_print() {
  if [[ "$dry_run" == "true" ]]; then
    printf '%q ' "$@"
    printf '\n'
    return 0
  fi

  "$@"
}

worktree_root="${HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT:-C:\\HyperTwist_worktrees\\phase10validate}"
fallback_worktree_root="${HYPERTWIST_REMOTE_WINDOWS_FALLBACK_WORKTREE_ROOT:-}"
report_stamp="$(date -u '+%Y%m%d')"
browser_filter="HyperTwist.Browser"
browser_report_name=""
package_archive_dir=""
sync_files=()
skip_build="false"
skip_browser_automation="false"
skip_package="false"
skip_browser_report_pull="false"
skip_package_report_pull="false"
skip_summary_refresh="false"
skip_exact_source_support_sync="${HYPERTWIST_REMOTE_WINDOWS_SKIP_EXACT_SOURCE_SUPPORT_SYNC:-false}"
dry_run="false"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --worktree-root)
      worktree_root="${2:-}"
      shift 2
      ;;
    --report-stamp)
      report_stamp="${2:-}"
      shift 2
      ;;
    --fallback-worktree-root)
      fallback_worktree_root="${2:-}"
      shift 2
      ;;
    --browser-filter)
      browser_filter="${2:-}"
      shift 2
      ;;
    --browser-report-name)
      browser_report_name="${2:-}"
      shift 2
      ;;
    --package-archive-dir)
      package_archive_dir="${2:-}"
      shift 2
      ;;
    --sync-file)
      sync_files+=("${2:-}")
      shift 2
      ;;
    --skip-build)
      skip_build="true"
      shift
      ;;
    --skip-browser-automation)
      skip_browser_automation="true"
      shift
      ;;
    --skip-package)
      skip_package="true"
      shift
      ;;
    --skip-browser-report-pull)
      skip_browser_report_pull="true"
      shift
      ;;
    --skip-package-report-pull)
      skip_package_report_pull="true"
      shift
      ;;
    --skip-summary-refresh)
      skip_summary_refresh="true"
      shift
      ;;
    --skip-exact-source-support-sync)
      skip_exact_source_support_sync="true"
      shift
      ;;
    --dry-run)
      dry_run="true"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      usage >&2
      exit 1
      ;;
  esac
done

if [[ -z "$browser_report_name" ]]; then
  browser_report_name="Browser-ExactSource-${report_stamp}"
fi

if [[ -z "$package_archive_dir" ]]; then
  package_archive_dir="${worktree_root}_packaged_phase6c_higherdim_refresh_${report_stamp}"
fi

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "${script_dir}/.." && pwd)"
remote_ps_wrapper="${script_dir}/run-hypertwist-remote-windows-powershell.sh"
remote_build_wrapper="${script_dir}/run-hypertwist-remote-unreal-build.sh"
remote_automation_wrapper="${script_dir}/run-hypertwist-remote-unreal-automation.sh"
remote_sync_wrapper="${script_dir}/run-hypertwist-remote-windows-file-sync.sh"
remote_pull_wrapper="${script_dir}/run-hypertwist-remote-windows-file-pull.sh"
summary_refresh_script="${script_dir}/render-hypertwist-web-package-validation-summary.mjs"

for required_wrapper in \
  "$remote_ps_wrapper" \
  "$remote_build_wrapper" \
  "$remote_automation_wrapper" \
  "$remote_sync_wrapper" \
  "$remote_pull_wrapper"
do
  if [[ ! -x "$required_wrapper" ]]; then
    echo "Expected executable wrapper at $required_wrapper" >&2
    exit 1
  fi
done

if [[ ! -f "$summary_refresh_script" ]]; then
  echo "Expected summary refresh script at $summary_refresh_script" >&2
  exit 1
fi

if [[ -z "${HYPERTWIST_REMOTE_WINDOWS_PASSWORD:-}" ]]; then
  echo "Set HYPERTWIST_REMOTE_WINDOWS_PASSWORD before running this refresh." >&2
  exit 1
fi

host_probe_command="Write-Output ('USER=' + [System.Security.Principal.WindowsIdentity]::GetCurrent().Name); Write-Output ('HOST=' + \$env:COMPUTERNAME)"
browser_report_local_path="docs/generated/browser_automation/${browser_report_name}/index.json"
package_report_local_path="docs/generated/higher_dimensional_training_maps/phase6c_dedicated_family_package_validation_report.json"
exact_source_support_files=(
  "Content/Browser/index.html"
  "Content/Browser/src/browser-runtime-bootstrap.js"
  "Content/Browser/src/browser-spatial-runtime-fallback.js"
  "Content/Browser/src/runtime/shell.ts"
  "scripts/Invoke-HyperTwistHigherDimensionalPackage.ps1"
  "scripts/Launch-HyperTwistHigherDimensionalPackage.ps1"
  "docs/generated/higher_dimensional_training_maps/phase6c_dedicated_family_map_manifest.json"
  "UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp"
  "UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibraryInternal.h"
  "UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibraryCoachPolicies.cpp"
  "UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibraryCoachWorkflow.cpp"
  "UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibraryCoachSummaries.cpp"
)
effective_sync_files=()

add_effective_sync_file() {
  local candidate="$1"
  local existing
  for existing in "${effective_sync_files[@]}"; do
    if [[ "$existing" == "$candidate" ]]; then
      return 0
    fi
  done
  effective_sync_files+=("$candidate")
}

if [[ "$skip_exact_source_support_sync" != "true" ]]; then
  for sync_file in "${exact_source_support_files[@]}"; do
    add_effective_sync_file "$sync_file"
  done
fi

for sync_file in "${sync_files[@]}"; do
  add_effective_sync_file "$sync_file"
done

run_refresh_for_root() {
  local current_worktree_root="$1"
  local current_validation_report_path="${current_worktree_root}\\docs\\generated\\higher_dimensional_training_maps\\phase6c_dedicated_family_package_validation_report.json"
  local browser_report_remote_path="${current_worktree_root}\\UnrealHyperTwist\\Saved\\AutomationReports\\${browser_report_name}\\index.json"
  local package_report_remote_path="$current_validation_report_path"
  local current_package_script_path="${current_worktree_root}\\scripts\\Invoke-HyperTwistHigherDimensionalPackage.ps1"
  local current_package_archive_dir="$package_archive_dir"
  local current_game_target_receipt_path="${current_worktree_root}\\UnrealHyperTwist\\Binaries\\Win64\\UnrealHyperTwist.target"
  local package_skip_build_clause=""
  local pre_package_editor_build_ps_bool='$false'
  local pre_package_editor_build_result='not-run'
  local step_exit=0

  if [[ "$current_worktree_root" != "$worktree_root" && "$package_archive_dir" == "${worktree_root}_packaged_phase6c_higherdim_refresh_${report_stamp}" ]]; then
    current_package_archive_dir="${current_worktree_root}_packaged_phase6c_higherdim_refresh_${report_stamp}"
  fi

  echo "Re-proving remote Windows lane through ${current_worktree_root}."
  if run_or_print "$remote_ps_wrapper" --command "$host_probe_command"; then
    :
  else
    step_exit="$?"
    return "$step_exit"
  fi

  if [[ ${#effective_sync_files[@]} -gt 0 ]]; then
    echo "Syncing ${#effective_sync_files[@]} repo-relative exact-source support file(s) into ${current_worktree_root}."
    local sync_command=("$remote_sync_wrapper")
    local sync_file
    for sync_file in "${effective_sync_files[@]}"; do
      sync_command+=(--file "$sync_file")
    done
    sync_command+=(--remote-root "$current_worktree_root")
    if run_or_print "${sync_command[@]}"; then
      :
    else
      step_exit="$?"
      return "$step_exit"
    fi
  fi

  if [[ "$skip_build" != "true" ]]; then
    echo "Running remote Unreal editor build."
    if run_or_print "$remote_build_wrapper" --worktree-root "$current_worktree_root"; then
      pre_package_editor_build_ps_bool='$true'
      pre_package_editor_build_result='passed'
      :
    else
      step_exit="$?"
      return "$step_exit"
    fi
  fi

  if [[ "$skip_browser_automation" != "true" ]]; then
    echo "Running remote browser automation refresh (~10-20s once the editor lane is warm)."
    if run_or_print \
      env HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT="$current_worktree_root" \
      "$remote_automation_wrapper" \
      --filter "$browser_filter" \
      --report-name "$browser_report_name"
    then
      :
    else
      step_exit="$?"
      return "$step_exit"
    fi
  fi

  if [[ "$skip_package" != "true" ]]; then
    echo "Running remote higher-dimensional package refresh (~1-3m on the maintained lane)."
    if [[ "$dry_run" == "true" ]]; then
      echo "Dry run: package helper would auto-detect whether ${current_game_target_receipt_path} exists before deciding on -SkipBuild."
    else
      local package_skip_build_probe_output
      if package_skip_build_probe_output="$(
        "$remote_ps_wrapper" --command "\$GameTargetReceiptPath = $(ps_single_quote "$current_game_target_receipt_path"); Write-Output ('PACKAGE_SKIP_BUILD=' + (Test-Path -LiteralPath \$GameTargetReceiptPath).ToString().ToLowerInvariant())" \
          | tr -d '\r'
      )"; then
        :
      else
        step_exit="$?"
        return "$step_exit"
      fi
      if printf '%s\n' "$package_skip_build_probe_output" | grep -Fq 'PACKAGE_SKIP_BUILD=true'; then
        package_skip_build_clause=" -SkipBuild"
        echo "Package helper will reuse the existing Win64 game target receipt."
      else
        echo "Package helper will rebuild the Win64 game target because the packaged-game receipt is absent."
      fi
    fi
    local package_command
    package_command="$(
      cat <<EOF
\$ProjectRoot = $(ps_single_quote "$current_worktree_root")
\$ArchiveDirectory = $(ps_single_quote "$current_package_archive_dir")
\$PackageScriptPath = $(ps_single_quote "$current_package_script_path")
\$ValidationReportPath = $(ps_single_quote "$current_validation_report_path")
\$PrePackageEditorBuildPerformed = ${pre_package_editor_build_ps_bool}
\$PrePackageEditorBuildResult = $(ps_single_quote "$pre_package_editor_build_result")
if (-not (Test-Path -LiteralPath \$PackageScriptPath)) {
  throw "Higher-dimensional package script was not found at '\$PackageScriptPath'."
}
& \$PackageScriptPath -ProjectRoot \$ProjectRoot -ArchiveDirectory \$ArchiveDirectory -ValidationReportPath \$ValidationReportPath -PrePackageEditorBuildPerformed:\$PrePackageEditorBuildPerformed -PrePackageEditorBuildResult \$PrePackageEditorBuildResult${package_skip_build_clause}
exit \$LASTEXITCODE
EOF
    )"
    if run_or_print "$remote_ps_wrapper" --command "$package_command"; then
      :
    else
      step_exit="$?"
      return "$step_exit"
    fi
  fi

  if [[ "$skip_browser_automation" != "true" && "$skip_browser_report_pull" != "true" ]]; then
    echo "Pulling remote browser automation index.json back into docs/generated."
    if run_or_print \
      "$remote_pull_wrapper" \
      --map "${browser_report_remote_path}::${browser_report_local_path}"
    then
      :
    else
      step_exit="$?"
      return "$step_exit"
    fi
  fi

  if [[ "$skip_package" != "true" && "$skip_package_report_pull" != "true" ]]; then
    echo "Pulling remote higher-dimensional package report back into docs/generated."
    if run_or_print \
      "$remote_pull_wrapper" \
      --map "${package_report_remote_path}::${package_report_local_path}"
    then
      :
    else
      step_exit="$?"
      return "$step_exit"
    fi
  fi

  if [[ "$skip_package" != "true" && "$skip_package_report_pull" != "true" && "$skip_summary_refresh" != "true" ]]; then
    echo "Refreshing the checked-in website package-validation summary."
    if run_or_print node "$summary_refresh_script"; then
      :
    else
      step_exit="$?"
      return "$step_exit"
    fi
  fi
}

active_worktree_root="$worktree_root"
if run_refresh_for_root "$worktree_root"; then
  :
else
  primary_exit="$?"
  if [[ -n "$fallback_worktree_root" ]]; then
    echo "Primary remote refresh failed on ${worktree_root}. Falling back to ${fallback_worktree_root}." >&2
    run_refresh_for_root "$fallback_worktree_root"
    active_worktree_root="$fallback_worktree_root"
  else
    exit "$primary_exit"
  fi
fi

echo "Remote exact-source browser/package refresh complete through ${active_worktree_root}."
