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

usage() {
  cat <<'EOF'
Usage:
  HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
    scripts/run-hypertwist-remote-unreal-automation.sh --filter HyperTwist.FirstParty.Skill

Options:
  --filter <automation-filter>
      Required Unreal automation filter.

  --report-name <name>
      Optional report/log folder suffix. Defaults to a sanitized filter name.

  --extra-arg <value>
      Append an extra UnrealEditor-Cmd.exe argument. May be repeated.

  --dry-run
      Print the generated remote PowerShell payload instead of executing it.

Environment:
  HYPERTWIST_REMOTE_WINDOWS_PASSWORD      Required by the underlying tunnel wrapper.
  HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT Optional, defaults to C:\HyperTwist_worktrees\phase10validate
  HYPERTWIST_REMOTE_WINDOWS_PROJECT_PATH  Optional, defaults beneath the worktree root.
  HYPERTWIST_REMOTE_WINDOWS_UNREAL_EDITOR_CMD
                                         Optional, defaults to the UE 5.7 UnrealEditor-Cmd.exe path.
  HYPERTWIST_REMOTE_WINDOWS_AUTOMATION_REPORT_ROOT
                                         Optional, defaults beneath Saved\AutomationReports.
  HYPERTWIST_REMOTE_WINDOWS_LOG_ROOT      Optional, defaults beneath Saved\Logs.
EOF
}

filter=""
report_name=""
dry_run="false"
extra_args=()

while [[ $# -gt 0 ]]; do
  case "$1" in
    --filter)
      filter="${2:-}"
      shift 2
      ;;
    --report-name)
      report_name="${2:-}"
      shift 2
      ;;
    --extra-arg)
      extra_args+=("${2:-}")
      shift 2
      ;;
    --dry-run)
      dry_run="true"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      usage >&2
      exit 1
      ;;
  esac
done

if [[ -z "$filter" ]]; then
  echo "Provide --filter." >&2
  exit 1
fi

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
remote_ps_wrapper="${script_dir}/run-hypertwist-remote-windows-powershell.sh"

if [[ ! -x "$remote_ps_wrapper" ]]; then
  echo "Expected executable wrapper at $remote_ps_wrapper" >&2
  exit 1
fi

worktree_root="${HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT:-C:\\HyperTwist_worktrees\\phase10validate}"
project_path="${HYPERTWIST_REMOTE_WINDOWS_PROJECT_PATH:-${worktree_root}\\UnrealHyperTwist\\UnrealHyperTwist.uproject}"
editor_cmd_path="${HYPERTWIST_REMOTE_WINDOWS_UNREAL_EDITOR_CMD:-C:\\Program Files\\Epic Games\\UE_5.7\\Engine\\Binaries\\Win64\\UnrealEditor-Cmd.exe}"
report_root="${HYPERTWIST_REMOTE_WINDOWS_AUTOMATION_REPORT_ROOT:-${worktree_root}\\UnrealHyperTwist\\Saved\\AutomationReports}"
log_root="${HYPERTWIST_REMOTE_WINDOWS_LOG_ROOT:-${worktree_root}\\UnrealHyperTwist\\Saved\\Logs}"

if [[ -z "$report_name" ]]; then
  report_name="$(printf '%s' "$filter" | sed 's/[^[:alnum:]._+-]/_/g')"
fi

report_export_path="${report_root}\\${report_name}"
abs_log_path="${log_root}\\${report_name}.log"

powershell_payload="$(
  python3 - <<'PY' \
    "$editor_cmd_path" \
    "$project_path" \
    "$report_export_path" \
    "$abs_log_path" \
    "$filter" \
    "${extra_args[@]}"
import sys

editor_cmd_path, project_path, report_export_path, abs_log_path, filter_name, *extra_args = sys.argv[1:]

def ps_single_quote(value: str) -> str:
    return "'" + value.replace("'", "''") + "'"

lines = [
    f"$EditorCmdPath = {ps_single_quote(editor_cmd_path)}",
    f"$ProjectPath = {ps_single_quote(project_path)}",
    f"$ReportExportPath = {ps_single_quote(report_export_path)}",
    f"$AbsLogPath = {ps_single_quote(abs_log_path)}",
    f"$Filter = {ps_single_quote(filter_name)}",
    "$ReportIndexPath = Join-Path $ReportExportPath 'index.json'",
    "",
    "if (Test-Path -LiteralPath $ReportExportPath) {",
    "  Remove-Item -LiteralPath $ReportExportPath -Recurse -Force",
    "}",
    "New-Item -ItemType Directory -Force -Path $ReportExportPath | Out-Null",
    "New-Item -ItemType Directory -Force -Path (Split-Path -Parent $AbsLogPath) | Out-Null",
    "",
    "if (-not (Test-Path -LiteralPath $EditorCmdPath)) {",
    "  throw \"UnrealEditor-Cmd.exe was not found at '$EditorCmdPath'.\"",
    "}",
    "",
    "if (-not (Test-Path -LiteralPath $ProjectPath)) {",
    "  throw \"Project file was not found at '$ProjectPath'.\"",
    "}",
    "",
    "& $EditorCmdPath `",
    "  $ProjectPath `",
    "  -unattended `",
    "  -nop4 `",
    "  -nosplash `",
    "  -NullRHI `",
    "  -log `",
    "  -stdout `",
    "  -FullStdOutLogOutput `",
    "  \"-AbsLog=$AbsLogPath\" `",
    "  \"-ReportExportPath=$ReportExportPath\" `",
    "  \"-ExecCmds=Automation RunTests $Filter\" `",
]

if extra_args:
    for extra_arg in extra_args:
        lines.append(f"  {ps_single_quote(extra_arg)} `")

lines.extend([
    "  \"-TestExit=Automation Test Queue Empty\"",
    "",
    "$EditorExitCode = $LASTEXITCODE",
    "if ($EditorExitCode -ne 0) {",
    "  exit $EditorExitCode",
    "}",
    "",
    "if (-not (Test-Path -LiteralPath $ReportIndexPath)) {",
    "  throw \"Automation report index was not written to '$ReportIndexPath'.\"",
    "}",
    "",
    "$Report = Get-Content -LiteralPath $ReportIndexPath -Raw | ConvertFrom-Json",
    "if ($null -eq $Report) {",
    "  throw \"Automation report '$ReportIndexPath' could not be parsed.\"",
    "}",
    "",
    "$FailedCount = if ($null -ne $Report.failed) { [int]$Report.failed } else { 0 }",
    "$NotRunCount = if ($null -ne $Report.notRun) { [int]$Report.notRun } else { 0 }",
    "$InProcessCount = if ($null -ne $Report.inProcess) { [int]$Report.inProcess } else { 0 }",
    "if ($FailedCount -gt 0 -or $NotRunCount -gt 0 -or $InProcessCount -gt 0) {",
    "  throw \"Automation report '$ReportIndexPath' recorded failed=$FailedCount notRun=$NotRunCount inProcess=$InProcessCount for filter '$Filter'.\"",
    "}",
    "",
    "exit 0",
])

print("\n".join(lines))
PY
)"

if [[ "$dry_run" == "true" ]]; then
  printf '%s\n' "$powershell_payload"
  exit 0
fi

exec "$remote_ps_wrapper" --command "$powershell_payload"
