name: Deploy to VPS

on:
  push:
    branches:
      - main
  workflow_dispatch:

concurrency:
  group: deploy-vps-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test-build:
    name: Lint, test, and build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9.15.9

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm

      - name: Install dependencies
        run: pnpm install --frozen-lockfile --prefer-offline

      - name: Lint
        run: pnpm lint

      - name: Run tests
        run: pnpm test

      - name: Type check
        run: pnpm type-check

      - name: Build shared packages
        run: |
          pnpm --filter @my-roadtrip/utils build
          pnpm --filter @my-roadtrip/types build
          pnpm --filter @my-roadtrip/validators build

      - name: Build API
        run: pnpm --filter @my-roadtrip/api build

      - name: Build Web
        run: pnpm --filter @my-roadtrip/web build

  deploy:
    name: Deploy over SSH
    needs: test-build
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to VPS
        uses: appleboy/ssh-action@v1.2.0
        env:
          DEPLOY_PATH: ${{ secrets.VPS_DEPLOY_PATH }}
          API_HEALTHCHECK_URL: ${{ secrets.VPS_API_HEALTHCHECK_URL }}
          WEB_HEALTHCHECK_URL: ${{ secrets.VPS_WEB_HEALTHCHECK_URL }}
          ENV_ROOT_B64: ${{ secrets.ENV_ROOT_B64 }}
          ENV_ROOT_DEV_B64: ${{ secrets.ENV_ROOT_DEV_B64 }}
          ENV_PRODUCTION_B64: ${{ secrets.ENV_PRODUCTION_B64 }}
          ENV_API_B64: ${{ secrets.ENV_API_B64 }}
          ENV_WEB_B64: ${{ secrets.ENV_WEB_B64 }}
          SERVICE_ACCOUNT_B64: ${{ secrets.SERVICE_ACCOUNT_B64 }}
          FIREBASE_TAR_B64: ${{ secrets.FIREBASE_TAR_B64 }}
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          port: ${{ secrets.VPS_SSH_PORT }}
          script: |
            set -euo pipefail
            DEPLOY_PATH="${DEPLOY_PATH:-/srv/myroadtrip}"
            REPO_PATH="$DEPLOY_PATH/repo"
            API_HEALTHCHECK_URL="${API_HEALTHCHECK_URL:-https://api.roadtripper.io/health}"
            WEB_HEALTHCHECK_URL="${WEB_HEALTHCHECK_URL:-https://roadtripper.io/}"

            sync_secret_file() {
              local data="$1"
              local dest="$2"
              local mode="${3:-600}"
              if [ -z "$data" ]; then
                return
              fi
              local tmp_file
              tmp_file=$(mktemp)
              echo "$data" | base64 --decode > "$tmp_file"
              sudo install -d -m 750 -o myroadtrip -g myroadtrip "$(dirname "$dest")"
              sudo mv "$tmp_file" "$dest"
              sudo chown myroadtrip:myroadtrip "$dest"
              sudo chmod "$mode" "$dest"
              echo "Synced $(basename "$dest")"
            }

            sync_secret_dir() {
              local data="$1"
              local dest="$2"
              if [ -z "$data" ]; then
                return
              fi
              local tmp_file
              tmp_file=$(mktemp)
              echo "$data" | base64 --decode > "$tmp_file"
              sudo rm -rf "$dest"
              sudo install -d -m 750 -o myroadtrip -g myroadtrip "$(dirname "$dest")"
              sudo tar -xzf "$tmp_file" -C "$(dirname "$dest")"
              sudo mv "$(dirname "$dest")/firebase" "$dest"
              sudo chown -R myroadtrip:myroadtrip "$dest"
              rm -f "$tmp_file"
              echo "Synced directory $(basename "$dest")"
            }

            sync_secret_file "$ENV_ROOT_B64" "$REPO_PATH/.env"
            sync_secret_file "$ENV_ROOT_DEV_B64" "$REPO_PATH/.env.development"
            sync_secret_file "$ENV_PRODUCTION_B64" "$DEPLOY_PATH/.env.production"
            sync_secret_file "$ENV_API_B64" "$REPO_PATH/apps/api/.env"
            sync_secret_file "$ENV_WEB_B64" "$REPO_PATH/apps/web/.env"
            sync_secret_file "$SERVICE_ACCOUNT_B64" "$DEPLOY_PATH/serviceAccount.json"
            sync_secret_dir "$FIREBASE_TAR_B64" "$DEPLOY_PATH/firebase"

            echo "Using repository path: $REPO_PATH"
            cd "$REPO_PATH"

            git fetch origin main
            git checkout main
            git reset --hard origin/main

            if command -v corepack >/dev/null 2>&1; then
              corepack enable pnpm >/dev/null 2>&1 || true
            fi

            if ! command -v pnpm >/dev/null 2>&1; then
              echo "pnpm is required on the VPS" >&2
              exit 1
            fi

            pnpm install --frozen-lockfile --prefer-offline
            pnpm --filter @my-roadtrip/utils build
            pnpm --filter @my-roadtrip/types build
            pnpm --filter @my-roadtrip/validators build
            pnpm --filter @my-roadtrip/api build
            pnpm --filter @my-roadtrip/web build

            sudo systemctl restart myroadtrip-api
            echo "Waiting for API to restart..."
            sleep 5
            curl -fsS "$API_HEALTHCHECK_URL"

            TIMESTAMP=$(date +%Y%m%d%H%M%S)
            if [ -d /srv/www/roadtripper ]; then
              sudo mkdir -p /srv/www/backups
              sudo tar -czf "/srv/www/backups/roadtripper-${TIMESTAMP}.tgz" -C /srv/www roadtripper
            fi

            sudo rsync -a --delete "$REPO_PATH/apps/web/dist/" /srv/www/roadtripper/
            sudo chown -R myroadtrip:myroadtrip /srv/www/roadtripper
            sudo systemctl reload caddy
            curl -fsS "$WEB_HEALTHCHECK_URL" >/dev/null
