#!/usr/bin/env bash

set -Eeuo pipefail

unset DOCKER_HOST DOCKER_TLS_VERIFY DOCKER_CERT_PATH DOCKER_TLS_CERTDIR

DEPLOY_DIR="${DEPLOY_DIR:-/home/gitlab-runner/deploy/call-center}"
APP_IMAGE_NAME="${APP_IMAGE_NAME:-call-center-app}"
APP_IMAGE_TAG="${APP_IMAGE_TAG:-${CI_COMMIT_SHORT_SHA:-latest}}"
COMPOSE_FILE="${COMPOSE_FILE:-$DEPLOY_DIR/deployment/docker-compose.server.yml}"
HEALTHCHECK_URL="${HEALTHCHECK_URL:-http://127.0.0.1:8080/health}"
HEALTHCHECK_TIMEOUT_SECONDS="${HEALTHCHECK_TIMEOUT_SECONDS:-120}"

require_command() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "Missing required command: $1" >&2
    exit 1
  fi
}

wait_for_health() {
  python3 - "$HEALTHCHECK_URL" "$HEALTHCHECK_TIMEOUT_SECONDS" <<'PY'
import sys
import time
import urllib.request

url = sys.argv[1]
timeout_seconds = int(sys.argv[2])
deadline = time.time() + timeout_seconds
last_error = None

while time.time() < deadline:
    try:
        with urllib.request.urlopen(url, timeout=5) as response:
            if response.getcode() == 200:
                print(f"Healthcheck passed: {url}")
                sys.exit(0)
            last_error = f"unexpected status {response.getcode()}"
    except Exception as exc:
        last_error = str(exc)
    time.sleep(3)

print(f"Healthcheck failed for {url}: {last_error}", file=sys.stderr)
sys.exit(1)
PY
}

require_command docker
require_command rsync
require_command python3

repair_deploy_permissions() {
  if [[ ! -d "$DEPLOY_DIR" ]]; then
    return
  fi

  local target_uid
  local target_gid
  target_uid="$(id -u)"
  target_gid="$(id -g)"

  docker run --rm \
    -e TARGET_UID="$target_uid" \
    -e TARGET_GID="$target_gid" \
    -v "$DEPLOY_DIR:/deploy" \
    alpine:3.21 \
    sh -lc '
      set -eu
      chown "$TARGET_UID:$TARGET_GID" /deploy
      chmod u+rwx /deploy
      for path in /deploy/* /deploy/.[!.]* /deploy/..?*; do
        [ -e "$path" ] || continue
        case "$path" in
          /deploy/.env.production|/deploy/.env.production.*|\
          /deploy/.data|/deploy/.data_gate3|/deploy/.data_gate4|\
          /deploy/.data_uat_dry_run|/deploy/.data_uat_preflight|\
          /deploy/.models|/deploy/.db_backups|/deploy/.deploy_backups)
            continue
            ;;
        esac
        chown -R "$TARGET_UID:$TARGET_GID" "$path"
        find "$path" -type d -exec chmod u+rwx {} +
        find "$path" -type f -exec chmod u+rw {} +
      done
    '
}

if docker compose version >/dev/null 2>&1; then
  COMPOSE_CMD=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then
  COMPOSE_CMD=(docker-compose)
else
  echo "Missing docker compose or docker-compose" >&2
  exit 1
fi

if [[ -z "${CI_PROJECT_DIR:-}" || ! -d "${CI_PROJECT_DIR:-}" ]]; then
  echo "CI_PROJECT_DIR is not set or does not exist" >&2
  exit 1
fi

if ! docker info >/dev/null 2>&1; then
  echo "Docker daemon is not reachable for the runner user" >&2
  exit 1
fi

install -d "$DEPLOY_DIR"
repair_deploy_permissions
cd "$DEPLOY_DIR"

if [[ "$CI_PROJECT_DIR" != "$DEPLOY_DIR" ]]; then
  rsync -a --delete \
    --exclude '.git/' \
    --exclude '.env.production' \
    --exclude '.env.production.*' \
    --exclude '.data/' \
    --exclude '.data_local/' \
    --exclude '.data_gate3/' \
    --exclude '.data_gate4/' \
    --exclude '.data_uat_dry_run/' \
    --exclude '.data_uat_preflight/' \
    --exclude '.venv/' \
    --exclude '.pytest_cache/' \
    --exclude '.local_stack/' \
    --exclude '.models/' \
    --exclude 'test-results/' \
    --exclude '.codex_backup/' \
    --exclude '.db_backups/' \
    --exclude '.deploy_backups/' \
    "$CI_PROJECT_DIR/" "$DEPLOY_DIR/"
fi

if [[ ! -f "$DEPLOY_DIR/.env.production" ]]; then
  if [[ -n "${DEPLOY_ENV_FILE:-}" && -f "${DEPLOY_ENV_FILE}" ]]; then
    install -m 600 "$DEPLOY_ENV_FILE" "$DEPLOY_DIR/.env.production"
  else
    echo "Missing $DEPLOY_DIR/.env.production. Create it once on the server or set DEPLOY_ENV_FILE." >&2
    exit 1
  fi
fi

install -d "$DEPLOY_DIR/.data_local"
install -d "$DEPLOY_DIR/.data_local/generated_ivr_yandex/ivr"

if [[ -d "$DEPLOY_DIR/.asterisk_assets/ivr" ]]; then
  rsync -a --delete \
    "$DEPLOY_DIR/.asterisk_assets/ivr/" \
    "$DEPLOY_DIR/.data_local/generated_ivr_yandex/ivr/"
fi

export CALL_CENTER_IMAGE="${APP_IMAGE_NAME}:${APP_IMAGE_TAG}"
export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-call-center}"

echo "Deploy directory: $DEPLOY_DIR"
echo "Building image: $CALL_CENTER_IMAGE"

docker build -t "$CALL_CENTER_IMAGE" -t "${APP_IMAGE_NAME}:latest" "$DEPLOY_DIR"

if docker ps -a --format '{{.Names}}' | grep -Fxq 'call-center-api-gateway' \
  && ! docker ps -a --format '{{.Names}}' | grep -Fxq 'call-center-app'; then
  echo "Removing legacy gateway container call-center-api-gateway before rename to call-center-app"
  docker rm -f call-center-api-gateway
fi

"${COMPOSE_CMD[@]}" -f "$COMPOSE_FILE" config -q
"${COMPOSE_CMD[@]}" -f "$COMPOSE_FILE" up -d --remove-orphans --force-recreate

wait_for_health

docker ps --filter "name=^call-center-app$" --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
