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

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DIST_DIR="${ROOT_DIR}/dist"
PROFILE="${PROFILE:-OWALUATOR_API}"
# Owalisaattori must use an app-specific feed path to avoid colliding with
# Owaluator's root latest-mac.yml feed.
DOWNLOAD_BASE_DEFAULT="https://downloads.kullervokapital.com/owalisaattori"
DOWNLOAD_BASE="${DOWNLOAD_BASE:-$DOWNLOAD_BASE_DEFAULT}"
UPLOAD_HOST_DEFAULT="root@92.205.180.198"
UPLOAD_DIR_DEFAULT="/var/www/owaluator/owalisaattori"
UPLOAD_RETRIES="${UPLOAD_RETRIES:-4}"
CONTROL_PATH="${CONTROL_PATH:-/tmp/owalisaattori-release-${USER}-$$.sock}"
SSH_IDENTITY="${SSH_IDENTITY:-${OG_RELEASE_SSH_KEY:-}}"

if [[ -n "${SSH_IDENTITY}" && "${SSH_IDENTITY}" == "~/"* ]]; then
  SSH_IDENTITY="${HOME}/${SSH_IDENTITY#~/}"
fi

DO_BUILD=0
DO_UPLOAD=0
UPLOAD_ONLY=0
DO_SMOKE=1
DO_PYTHON_BUNDLE=1
ROLLBACK_VERSION=""
VERSION_OVERRIDE=""
UPLOAD_HOST="${UPLOAD_HOST:-$UPLOAD_HOST_DEFAULT}"
UPLOAD_DIR="${UPLOAD_DIR:-$UPLOAD_DIR_DEFAULT}"

while (($#)); do
  case "$1" in
    --build)
      DO_BUILD=1
      shift
      ;;
    --upload)
      DO_UPLOAD=1
      shift
      ;;
    --upload-only|--publish-only)
      DO_UPLOAD=1
      UPLOAD_ONLY=1
      shift
      ;;
    --no-smoke)
      DO_SMOKE=0
      shift
      ;;
    --no-python-bundle)
      DO_PYTHON_BUNDLE=0
      shift
      ;;
    --rollback)
      ROLLBACK_VERSION="${2:-}"
      DO_UPLOAD=1
      UPLOAD_ONLY=1
      shift 2
      ;;
    --version)
      VERSION_OVERRIDE="${2:-}"
      shift 2
      ;;
    --profile)
      PROFILE="${2:-}"
      shift 2
      ;;
    --upload-host)
      UPLOAD_HOST="${2:-}"
      shift 2
      ;;
    --upload-dir)
      UPLOAD_DIR="${2:-}"
      shift 2
      ;;
    --download-base)
      DOWNLOAD_BASE="${2:-}"
      shift 2
      ;;
    *)
      echo "Tuntematon argumentti: $1"
      echo "Käyttö: $0 [--build] [--upload] [--upload-only] [--no-smoke] [--no-python-bundle] [--rollback VERSION] [--version VERSION] [--profile OWALUATOR_API] [--upload-host user@host] [--upload-dir /path] [--download-base https://downloads.kullervokapital.com/owalisaattori]"
      exit 1
      ;;
  esac
done

cd "$ROOT_DIR"

if [[ "$DO_BUILD" -eq 1 ]]; then
  echo "==> Päivitä avainohjeet (PDF)"
  npm run guide:pdf:user
  npm run guide:pdf:admin
  npm run guide:pdf:onepager

  if [[ "$DO_PYTHON_BUNDLE" -eq 1 ]]; then
    echo "==> Build Python API standalone bundle (PyInstaller)"
    npm run build:python-api
  else
    echo "==> Python API bundle build ohitettu (--no-python-bundle)"
  fi

  echo "==> Build (npm run dist)"
  npm run dist
fi

if [[ -n "$VERSION_OVERRIDE" ]]; then
  VERSION="$VERSION_OVERRIDE"
else
  VERSION="$(node -p "require('./package.json').version")"
fi

ZIP_PATH="${DIST_DIR}/Owalisaattori-${VERSION}-arm64-mac.zip"
DMG_PATH="${DIST_DIR}/Owalisaattori-${VERSION}-arm64.dmg"
YML_PATH="${DIST_DIR}/latest-mac.yml"
APP_PATH="${DIST_DIR}/mac-arm64/Owalisaattori.app"

if [[ ! -f "$ZIP_PATH" || ! -f "$DMG_PATH" || ! -f "$YML_PATH" ]]; then
  echo "Virhe: dist-tiedostot puuttuvat versiolle ${VERSION}."
  ls -la "$DIST_DIR"
  exit 1
fi
if [[ ! -d "$APP_PATH" ]]; then
  echo "Virhe: app-polku puuttuu: $APP_PATH"
  exit 1
fi

write_latest_yml_for_version() {
  local release_version="$1"
  local release_zip="$2"
  local zip_name
  zip_name="$(basename "$release_zip")"
  local size
  size="$(stat -f%z "$release_zip")"
  local sha512
  sha512="$(openssl dgst -sha512 -binary "$release_zip" | openssl base64 -A)"
  local release_date
  release_date="$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")"
  cat > "$YML_PATH" <<EOF
version: ${release_version}
files:
  - url: ${zip_name}
    sha512: ${sha512}
    size: ${size}
path: ${zip_name}
sha512: ${sha512}
releaseDate: '${release_date}'
EOF
}

upload_file() {
  local file="$1"
  local attempt=1
  while true; do
    if command -v rsync >/dev/null 2>&1; then
      if rsync -avP -e "ssh ${SSH_OPTS_STR}" "$file" "${UPLOAD_HOST}:${UPLOAD_DIR}/"; then
        return 0
      fi
    else
      if scp "${SSH_OPTS[@]}" "$file" "${UPLOAD_HOST}:${UPLOAD_DIR}/"; then
        return 0
      fi
    fi

    if [[ "$attempt" -ge "$UPLOAD_RETRIES" ]]; then
      echo "Virhe: upload epäonnistui tiedostolle $file (${attempt}/${UPLOAD_RETRIES})."
      return 1
    fi

    echo "Upload epäonnistui tiedostolle $file, uusi yritys (${attempt}/${UPLOAD_RETRIES}) 8s kuluttua..."
    attempt=$((attempt + 1))
    sleep 8
  done
}

SSH_OPTS=(
  "-oServerAliveInterval=30"
  "-oServerAliveCountMax=120"
  "-oConnectTimeout=10"
  "-oControlMaster=auto"
  "-oControlPersist=600"
  "-oControlPath=${CONTROL_PATH}"
)
if [[ -n "${SSH_IDENTITY}" ]]; then
  SSH_OPTS+=("-i" "${SSH_IDENTITY}" "-oIdentitiesOnly=yes")
fi
SSH_OPTS_STR="${SSH_OPTS[*]}"

cleanup_ssh_master() {
  ssh "${SSH_OPTS[@]}" -O exit "${UPLOAD_HOST}" >/dev/null 2>&1 || true
  rm -f "${CONTROL_PATH}" >/dev/null 2>&1 || true
}
trap cleanup_ssh_master EXIT

init_ssh_master() {
  # Open a shared SSH control connection once so uploads do not prompt
  # for password on every single file/command.
  ssh "${SSH_OPTS[@]}" -Nf "${UPLOAD_HOST}" || true
}

if [[ -n "$ROLLBACK_VERSION" ]]; then
  ROLLBACK_ZIP="${DIST_DIR}/Owalisaattori-${ROLLBACK_VERSION}-arm64-mac.zip"
  if [[ ! -f "$ROLLBACK_ZIP" ]]; then
    echo "Virhe: rollback-versiota ei loydy paikallisesti: $ROLLBACK_ZIP"
    exit 1
  fi
  echo "==> Build latest-mac.yml rollback-versiolle ${ROLLBACK_VERSION}"
  write_latest_yml_for_version "$ROLLBACK_VERSION" "$ROLLBACK_ZIP"
fi

if [[ "$UPLOAD_ONLY" -eq 0 ]]; then
  if [[ "$DO_SMOKE" -eq 1 ]]; then
    if [[ -z "${E2E_AUTH_ADMIN_KEY:-}" ]]; then
      echo "Virhe: smoke-preflight vaatii E2E_AUTH_ADMIN_KEY ympäristömuuttujan."
      echo "Aseta esimerkiksi:"
      echo "  export E2E_AUTH_ADMIN_KEY=\"\$OWALISAATTORI_ADMIN_KEY\""
      echo "Tai ohita hätätilassa: --no-smoke"
      exit 1
    fi

    echo "==> Smoke preflight (auth + RBAC)"
    npm run smoke:e2e:auth-rbac
  else
    echo "==> Smoke preflight ohitettu (--no-smoke)"
  fi

  echo "==> Notarize zip (${ZIP_PATH})"
  xcrun notarytool submit "$ZIP_PATH" --keychain-profile "$PROFILE" --wait

  echo "==> Notarize dmg (${DMG_PATH})"
  xcrun notarytool submit "$DMG_PATH" --keychain-profile "$PROFILE" --wait

  echo "==> Staple app + dmg"
  xcrun stapler staple "$APP_PATH"
  xcrun stapler staple "$DMG_PATH"

  echo "==> Validate app + dmg"
  xcrun stapler validate "$APP_PATH"
  xcrun stapler validate "$DMG_PATH"
  spctl -a -vv "$APP_PATH"
fi

if [[ "$DO_UPLOAD" -eq 1 ]]; then
  echo "==> Upload release files to ${UPLOAD_HOST}:${UPLOAD_DIR}"
  init_ssh_master
  ssh "${SSH_OPTS[@]}" "${UPLOAD_HOST}" "mkdir -p '${UPLOAD_DIR}'"
  if [[ -z "$ROLLBACK_VERSION" ]]; then
    upload_file "$ZIP_PATH"
    upload_file "$DMG_PATH"
  fi
  # Upload latest metadata last to avoid clients seeing a half-uploaded release.
  upload_file "$YML_PATH"

  ZIP_FILE="$(python3 - <<PY
import re
from pathlib import Path
txt = Path("$YML_PATH").read_text(encoding="utf-8")
m = re.search(r"^path:\\s*(.+)$", txt, flags=re.M)
print(m.group(1).strip() if m else "")
PY
)"
  DMG_FILE="${ZIP_FILE/-mac.zip/.dmg}"
  echo "==> Verify HTTP availability"
  set +e
  curl -fsSI "${DOWNLOAD_BASE}/latest-mac.yml"
  verify_manifest_status=$?
  if [[ -n "$ZIP_FILE" ]]; then
    curl -fsSI "${DOWNLOAD_BASE}/${ZIP_FILE}"
    verify_zip_status=$?
  fi
  if [[ -z "$ROLLBACK_VERSION" ]]; then
    curl -fsSI "${DOWNLOAD_BASE}/${DMG_FILE}"
    verify_dmg_status=$?
  fi
  set -e

  if [[ "${verify_manifest_status}" -ne 0 || "${verify_zip_status:-0}" -ne 0 || "${verify_dmg_status:-0}" -ne 0 ]]; then
    echo ""
    echo "Virhe: HTTP verify epaonnistui."
    echo "Tarkista erityisesti upload-dir ja download-base -pari."
    echo "Suositus Owalisaattorille:"
    echo "  --upload-dir /var/www/owaluator/owalisaattori"
    echo "  --download-base https://downloads.kullervokapital.com/owalisaattori"
    exit 1
  fi

  REMOTE_FEED_PATH="$(curl -fsSL "${DOWNLOAD_BASE}/latest-mac.yml" | sed -n 's/^path:[[:space:]]*//p' | head -n1 | tr -d '\r')"
  if [[ -n "$ZIP_FILE" && "$REMOTE_FEED_PATH" != "$ZIP_FILE" ]]; then
    echo ""
    echo "Virhe: remote latest-mac.yml osoittaa eri zip-tiedostoon."
    echo "  expected: ${ZIP_FILE}"
    echo "  actual:   ${REMOTE_FEED_PATH:-<tyhja>}"
    exit 1
  fi
fi

echo "==> Valmis (versio ${VERSION}, feed ${DOWNLOAD_BASE})"
