#!/bin/bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  REMOTE_HOST=150.158.105.6 \
  REMOTE_USER=root \
  REMOTE_PASSWORD='your-password' \
  ./scripts/deploy-remote.sh

Optional environment variables:
  REMOTE_PORT=22
  REMOTE_DIR=/root/lingma-proxy-compose
  REMOTE_BUILD_DIR=/root/lingma-proxy-compose/src
  REMOTE_PUBLIC_PORT=13123
  REMOTE_CONTAINER_NAME=lingma-proxy-uploaded
  REMOTE_IMAGE_NAME=lingma-proxy-uploaded
  REMOTE_SESSION_BUNDLE_PATH=/root/lingma-proxy-compose/secrets/lingma-session.b64
  LINGMA_REMOTE_BASE_URL=https://lingma.alibabacloud.com
  LINGMA_SOURCE_TYPE=vsix
  LINGMA_VSIX_URL=https://tongyi-code.oss-cn-hangzhou.aliyuncs.com/vscode/tongyi-lingma-latest.vsix
  LINGMA_MARKETPLACE_PUBLISHER=Alibaba-Cloud
  LINGMA_MARKETPLACE_EXTENSION=tongyi-lingma
  LINGMA_PROXY_MODEL=org_auto
  VERIFY_PUBLIC=false
EOF
}

require_env() {
  local name="$1"
  if [ -z "${!name:-}" ]; then
    echo "Missing required environment variable: $name" >&2
    usage >&2
    exit 1
  fi
}

require_cmd() {
  command -v "$1" >/dev/null 2>&1 || {
    echo "Required command not found: $1" >&2
    exit 1
  }
}

if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then
  usage
  exit 0
fi

require_cmd sshpass
require_cmd ssh
require_cmd scp
require_cmd curl
require_cmd tar

require_env REMOTE_HOST
require_env REMOTE_USER
require_env REMOTE_PASSWORD

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

REMOTE_PORT="${REMOTE_PORT:-22}"
REMOTE_DIR="${REMOTE_DIR:-/root/lingma-proxy-compose}"
REMOTE_BUILD_DIR="${REMOTE_BUILD_DIR:-$REMOTE_DIR/src}"
REMOTE_PUBLIC_PORT="${REMOTE_PUBLIC_PORT:-13123}"
REMOTE_CONTAINER_NAME="${REMOTE_CONTAINER_NAME:-lingma-proxy-uploaded}"
REMOTE_IMAGE_NAME="${REMOTE_IMAGE_NAME:-lingma-proxy-uploaded}"
REMOTE_SESSION_BUNDLE_PATH="${REMOTE_SESSION_BUNDLE_PATH:-$REMOTE_DIR/secrets/lingma-session.b64}"
LINGMA_REMOTE_BASE_URL="${LINGMA_REMOTE_BASE_URL:-https://lingma.alibabacloud.com}"
LINGMA_SOURCE_TYPE="${LINGMA_SOURCE_TYPE:-vsix}"
LINGMA_VSIX_URL="${LINGMA_VSIX_URL:-https://tongyi-code.oss-cn-hangzhou.aliyuncs.com/vscode/tongyi-lingma-latest.vsix}"
LINGMA_MARKETPLACE_PUBLISHER="${LINGMA_MARKETPLACE_PUBLISHER:-Alibaba-Cloud}"
LINGMA_MARKETPLACE_EXTENSION="${LINGMA_MARKETPLACE_EXTENSION:-tongyi-lingma}"
LINGMA_PROXY_MODEL="${LINGMA_PROXY_MODEL:-org_auto}"
VERIFY_PUBLIC="${VERIFY_PUBLIC:-false}"

if [ "$REMOTE_BUILD_DIR" = "$REMOTE_DIR" ]; then
  echo "REMOTE_BUILD_DIR must be different from REMOTE_DIR" >&2
  exit 1
fi

case "$REMOTE_BUILD_DIR" in
  "$REMOTE_DIR"/*) REMOTE_BUILD_CONTEXT_SUBDIR="${REMOTE_BUILD_DIR#"$REMOTE_DIR"/}" ;;
  *)
    echo "REMOTE_BUILD_DIR must be inside REMOTE_DIR so Docker can access it" >&2
    exit 1
    ;;
esac

if [ ! -d "$REPO_ROOT/vendor" ]; then
  echo "Missing vendor/ directory. Run 'go mod vendor' first." >&2
  exit 1
fi

SSH_BASE=(sshpass -p "$REMOTE_PASSWORD" ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST")
SCP_BASE=(sshpass -p "$REMOTE_PASSWORD" scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT")

work_dir="$(mktemp -d)"
trap 'rm -rf "$work_dir"' EXIT

source_dir="$work_dir/source"
archive_path="$work_dir/source.tar.gz"
dockerfile_path="$work_dir/Dockerfile.uploaded"
env_path="$work_dir/.env.container"
remote_archive_path="$REMOTE_DIR/source.tar.gz"

mkdir -p "$source_dir"
cp -R "$REPO_ROOT/cmd" "$source_dir/cmd"
cp -R "$REPO_ROOT/internal" "$source_dir/internal"
cp -R "$REPO_ROOT/vendor" "$source_dir/vendor"
cp "$REPO_ROOT/go.mod" "$source_dir/go.mod"
cp "$REPO_ROOT/go.sum" "$source_dir/go.sum"
if [ -d "$REPO_ROOT/pkg" ]; then
  cp -R "$REPO_ROOT/pkg" "$source_dir/pkg"
fi

tar -C "$source_dir" -czf "$archive_path" .

cat >"$dockerfile_path" <<EOF
FROM golang:1.23.6-bookworm AS builder
WORKDIR /src
COPY $REMOTE_BUILD_CONTEXT_SUBDIR/ /src/
ENV GOTOOLCHAIN=local GOFLAGS=-mod=vendor CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go build -o /out/lingma-proxy ./cmd/lingma-ipc-proxy

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /out/lingma-proxy /usr/local/bin/lingma-proxy
EXPOSE 8095
CMD ["lingma-proxy", "--host", "0.0.0.0", "--port", "8095", "--backend", "remote"]
EOF

cat >"$env_path" <<EOF
LINGMA_REMOTE_BASE_URL=$LINGMA_REMOTE_BASE_URL
LINGMA_REMOTE_AUTH_FILE=
LINGMA_BOOTSTRAP_ENABLED=true
LINGMA_SOURCE_TYPE=$LINGMA_SOURCE_TYPE
LINGMA_VSIX_URL=$LINGMA_VSIX_URL
LINGMA_MARKETPLACE_PUBLISHER=$LINGMA_MARKETPLACE_PUBLISHER
LINGMA_MARKETPLACE_EXTENSION=$LINGMA_MARKETPLACE_EXTENSION
LINGMA_BIN=/app/data/bin/Lingma
LINGMA_BOOTSTRAP_OUTPUT_DIR=/app/data/bin/release
LINGMA_BOOTSTRAP_ALWAYS=true
LINGMA_FORCE_REFRESH=false
LINGMA_WORK_DIR=/app/data/.lingma/vscode/sharedClientCache
LINGMA_SESSION_BUNDLE=
LINGMA_SESSION_BUNDLE_FILE=/secrets/lingma-session.b64
LINGMA_PROXY_BACKEND=remote
LINGMA_PROXY_SESSION_MODE=auto
LINGMA_PROXY_MODEL=$LINGMA_PROXY_MODEL
LINGMA_PROXY_TIMEOUT_SECONDS=0
LINGMA_REMOTE_FALLBACK_ENABLED=true
EOF

echo "==> Ensuring remote deploy directory exists"
"${SSH_BASE[@]}" "mkdir -p '$REMOTE_DIR' '$REMOTE_DIR/data' '$REMOTE_DIR/secrets' '$REMOTE_BUILD_DIR'"

echo "==> Checking remote build prerequisites"
"${SSH_BASE[@]}" "command -v docker >/dev/null 2>&1 && command -v tar >/dev/null 2>&1 && command -v curl >/dev/null 2>&1"

echo "==> Checking remote session bundle"
"${SSH_BASE[@]}" "test -f '$REMOTE_SESSION_BUNDLE_PATH'"

echo "==> Uploading source bundle and runtime files"
"${SCP_BASE[@]}" "$archive_path" "$REMOTE_USER@$REMOTE_HOST:$remote_archive_path"
"${SCP_BASE[@]}" "$dockerfile_path" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/Dockerfile.uploaded"
"${SCP_BASE[@]}" "$env_path" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/.env.container"

echo "==> Preparing remote build context"
"${SSH_BASE[@]}" "rm -rf '$REMOTE_BUILD_DIR' && mkdir -p '$REMOTE_BUILD_DIR' && tar -xzf '$remote_archive_path' -C '$REMOTE_BUILD_DIR'"

echo "==> Rebuilding remote runtime image"
"${SSH_BASE[@]}" "cd '$REMOTE_DIR' && docker build -f Dockerfile.uploaded -t '$REMOTE_IMAGE_NAME' ."

echo "==> Recreating remote container"
"${SSH_BASE[@]}" "cd '$REMOTE_DIR' && docker rm -f '$REMOTE_CONTAINER_NAME' >/dev/null 2>&1 || true && docker run -d --name '$REMOTE_CONTAINER_NAME' --restart unless-stopped --env-file .env.container -p '$REMOTE_PUBLIC_PORT:8095' -v '$REMOTE_DIR/data:/app/data' -v '$REMOTE_DIR/secrets:/secrets:ro' '$REMOTE_IMAGE_NAME' >/dev/null"

echo "==> Waiting for remote health endpoint"
"${SSH_BASE[@]}" 'for i in $(seq 1 24); do curl -fsS "http://127.0.0.1:'"$REMOTE_PUBLIC_PORT"'/runtime/status" && exit 0; sleep 5; done; docker logs --tail 120 '"$REMOTE_CONTAINER_NAME"' >&2; exit 1'

echo
echo "==> Remote models"
"${SSH_BASE[@]}" "curl -fsS http://127.0.0.1:$REMOTE_PUBLIC_PORT/v1/models"

if [ "$VERIFY_PUBLIC" = "true" ]; then
  echo
  echo "==> Public runtime check"
  curl -fsS "http://$REMOTE_HOST:$REMOTE_PUBLIC_PORT/runtime/status"
fi

echo
echo "Deploy complete: http://$REMOTE_HOST:$REMOTE_PUBLIC_PORT"
