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

usage() {
  cat <<'EOF'
Usage:
  HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
    scripts/run-hypertwist-remote-windows-file-sync.sh \
      --file UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp

Options:
  --file <path>
      Relative repo path to copy into the remote Windows worktree. May be repeated.

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

  --dry-run
      Print the copy plan without transferring files.

Environment:
  HYPERTWIST_REMOTE_WINDOWS_PASSWORD   Required password for the reverse-SSH Windows user.
  HYPERTWIST_REMOTE_TUNNEL_PORT        Optional, defaults to 22022.
  HYPERTWIST_REMOTE_WINDOWS_USER       Optional, defaults to "anthracite ace".
  HYPERTWIST_REMOTE_TUNNEL_HOST        Optional, defaults to "localhost".
EOF
}

if ! command -v sshpass >/dev/null 2>&1; then
  echo "sshpass is required but was not found on PATH." >&2
  exit 1
fi

if ! command -v sha256sum >/dev/null 2>&1; then
  echo "sha256sum is required but was not found on PATH." >&2
  exit 1
fi

if ! command -v scp >/dev/null 2>&1; then
  echo "scp is required but was not found on PATH." >&2
  exit 1
fi

if ! command -v python3 >/dev/null 2>&1; then
  echo "python3 is required but was not found on PATH." >&2
  exit 1
fi

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

remote_root='C:\HyperTwist_worktrees\phase10validate'
dry_run="false"
files=()

while [[ $# -gt 0 ]]; do
  case "$1" in
    --file)
      files+=("${2:-}")
      shift 2
      ;;
    --remote-root)
      remote_root="${2:-}"
      shift 2
      ;;
    --dry-run)
      dry_run="true"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      usage >&2
      exit 1
      ;;
  esac
done

if [[ ${#files[@]} -eq 0 ]]; then
  echo "Provide at least one --file." >&2
  exit 1
fi

remote_port="${HYPERTWIST_REMOTE_TUNNEL_PORT:-22022}"
remote_user="${HYPERTWIST_REMOTE_WINDOWS_USER:-anthracite ace}"
remote_host="${HYPERTWIST_REMOTE_TUNNEL_HOST:-localhost}"

encode_powershell_command() {
  local script_text="$1"

  python3 - <<'PY' "$script_text"
import base64
import sys

script = sys.argv[1]
sys.stdout.write(base64.b64encode(script.encode("utf-16le")).decode("ascii"))
PY
}

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

ssh_base=(
  sshpass -p "${HYPERTWIST_REMOTE_WINDOWS_PASSWORD}"
  ssh
  -o StrictHostKeyChecking=no
  -o PreferredAuthentications=password
  -o PubkeyAuthentication=no
  -p "${remote_port}"
  -l "${remote_user}"
  "${remote_host}"
)

scp_base=(
  sshpass -p "${HYPERTWIST_REMOTE_WINDOWS_PASSWORD}"
  scp
  -q
  -o StrictHostKeyChecking=no
  -o PreferredAuthentications=password
  -o PubkeyAuthentication=no
  -P "${remote_port}"
)

for relative_path in "${files[@]}"; do
  if [[ "$relative_path" = /* ]]; then
    echo "Use repo-relative paths only: $relative_path" >&2
    exit 1
  fi

  if [[ ! -f "$relative_path" ]]; then
    echo "File not found: $relative_path" >&2
    exit 1
  fi

  windows_relative_path="${relative_path//\//\\}"
  windows_dest_path="${remote_root}\\${windows_relative_path}"
  local_hash="$(sha256sum "$relative_path" | awk '{print tolower($1)}')"
  windows_incoming_path="${windows_dest_path}.hypertwist-incoming-${local_hash:0:12}"

  if [[ "$dry_run" == "true" ]]; then
    printf '%s -> %s (%s)\n' "$relative_path" "$windows_dest_path" "$local_hash"
    continue
  fi

  remote_prepare_script="$(
    cat <<EOF
\$ProgressPreference = 'SilentlyContinue'
\$ErrorActionPreference = 'Stop'
\$Path = $(ps_single_quote "$windows_dest_path")
\$IncomingPath = $(ps_single_quote "$windows_incoming_path")
\$dir = [System.IO.Path]::GetDirectoryName(\$Path)
if (\$dir) {
  [System.IO.Directory]::CreateDirectory(\$dir) | Out-Null
}
if (Test-Path -LiteralPath \$IncomingPath) {
  Remove-Item -LiteralPath \$IncomingPath -Force
}
EOF
  )"
  encoded_remote_prepare_script="$(encode_powershell_command "$remote_prepare_script")"
  "${ssh_base[@]}" "powershell -NoProfile -EncodedCommand ${encoded_remote_prepare_script}" >/dev/null

  incoming_scp_path="${windows_incoming_path//\\//}"
  "${scp_base[@]}" \
    "$relative_path" \
    "${remote_user}@${remote_host}:${incoming_scp_path}"

  remote_finalize_script="$(
    cat <<EOF
\$ErrorActionPreference = 'Stop'
\$Path = $(ps_single_quote "$windows_dest_path")
\$IncomingPath = $(ps_single_quote "$windows_incoming_path")
\$ExpectedHash = '${local_hash}'
if (-not (Test-Path -LiteralPath \$IncomingPath -PathType Leaf)) {
  throw "Incoming upload was not found at '\$IncomingPath'."
}
\$IncomingHash = (Get-FileHash -LiteralPath \$IncomingPath -Algorithm SHA256).Hash.ToLowerInvariant()
if (\$IncomingHash -ne \$ExpectedHash) {
  Remove-Item -LiteralPath \$IncomingPath -Force
  throw "Incoming hash mismatch: expected \$ExpectedHash but received \$IncomingHash."
}
Move-Item -LiteralPath \$IncomingPath -Destination \$Path -Force
Write-Output ('REMOTE_HASH=' + (Get-FileHash -LiteralPath \$Path -Algorithm SHA256).Hash.ToLowerInvariant())
EOF
  )"
  encoded_remote_finalize_script="$(encode_powershell_command "$remote_finalize_script")"
  remote_hash="$(
    "${ssh_base[@]}" "powershell -NoProfile -EncodedCommand ${encoded_remote_finalize_script}" \
      | tr -d '\r' \
      | sed -n 's/^REMOTE_HASH=//p'
  )"

  if [[ "$remote_hash" != "$local_hash" ]]; then
    echo "Hash mismatch for $relative_path" >&2
    echo "  local : $local_hash" >&2
    echo "  remote: $remote_hash" >&2
    exit 1
  fi

  printf 'Synced %s -> %s (%s)\n' "$relative_path" "$windows_dest_path" "$local_hash"
done
