#!/usr/bin/env bash
# ==============================================================================
# BillCare 배포 스크립트 — Docker Compose
# 호출: Git post-receive (Track A) | Jenkins (Track B)
# 서버 설치: /Volumes/ADATA/git/deploy-billcare.sh
# ==============================================================================
set -euo pipefail

GIT_DIR="${GIT_DIR:-/Volumes/ADATA/git/BillCare.git}"
WORK_TREE="${WORK_TREE:-/Users/aidev/apps/BillCare}"
BRANCH="${BRANCH:-main}"
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE:-${WORK_TREE}/docker-compose.yml}"
DEPLOY_LOG="${DEPLOY_LOG:-/Volumes/ADATA/logs/deploy/billcare-deploy.log}"
LOG_TAG="[billcare-deploy]"
SERVICE_NAME="${SERVICE_NAME:-all}"
DOCKER_NO_CACHE="${DOCKER_NO_CACHE:-0}"
BACKEND_HEALTH_URL="${BACKEND_HEALTH_URL:-http://127.0.0.1:18082/api/health}"
FRONTEND_URL="${FRONTEND_URL:-http://127.0.0.1:83/}"

export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:${PATH:-/usr/bin:/bin}"
# 서버 포트 (host) — 로컬 개발 82/8082 와 분리, 8082는 kakao-skill 사용 중
export FRONTEND_PORT="${FRONTEND_PORT:-83}"
export BACKEND_PORT="${BACKEND_PORT:-18082}"
export MYSQL_PORT="${MYSQL_PORT:-3308}"
export APP_CORS_ORIGINS="${APP_CORS_ORIGINS:-https://billcare.exdev.co.kr,http://billcare.exdev.co.kr,http://localhost:83,http://127.0.0.1:83}"

mkdir -p "$(dirname "$DEPLOY_LOG")"
exec >> "$DEPLOY_LOG" 2>&1

log()  { echo "$(date '+%Y-%m-%d %H:%M:%S') $LOG_TAG $*"; }
info() { log "[INFO]  $*"; }
warn() { log "[WARN]  $*"; }
err()  { log "[ERROR] $*"; exit 1; }

log "======================================================"
log "  BillCare 배포 시작"
log "  서비스  : $SERVICE_NAME"
log "  브랜치  : $BRANCH"
log "  작업트리: $WORK_TREE"
log "  compose : $DOCKER_COMPOSE_FILE"
log "  실행자  : $(whoami)"
log "======================================================"

LOCK_FILE="/tmp/billcare_deploy.lock"
if [ -f "$LOCK_FILE" ]; then
  LOCK_PID=$(cat "$LOCK_FILE" 2>/dev/null || echo "")
  if [ -n "$LOCK_PID" ] && kill -0 "$LOCK_PID" 2>/dev/null; then
    err "다른 배포 진행 중 (PID: $LOCK_PID)"
  fi
  rm -f "$LOCK_FILE"
fi
echo $$ > "$LOCK_FILE"
trap 'rm -f "$LOCK_FILE"; log "락 파일 해제"' EXIT

# Phase 1
info "[Phase 1] Git checkout"
[ ! -d "$WORK_TREE" ] && mkdir -p "$WORK_TREE"
[ ! -d "$GIT_DIR" ] && err "GIT_DIR 없음: $GIT_DIR"
git --work-tree="$WORK_TREE" --git-dir="$GIT_DIR" checkout -f "$BRANCH"
COMMIT="$(git --git-dir="$GIT_DIR" rev-parse HEAD)"
info "체크아웃 완료: $(git --git-dir="$GIT_DIR" rev-parse --short HEAD)"

if [ -d "$WORK_TREE/.git" ]; then
  err "work-tree에 중첩 .git 존재 — 제거 후 재배포: rm -rf $WORK_TREE/.git"
fi
WT_HEAD="$(git --git-dir="$GIT_DIR" --work-tree="$WORK_TREE" rev-parse HEAD)"
[ "$WT_HEAD" = "$COMMIT" ] || err "work-tree HEAD 불일치: $WT_HEAD != $COMMIT"

[ ! -f "$DOCKER_COMPOSE_FILE" ] && err "docker-compose.yml 없음: $DOCKER_COMPOSE_FILE"
cd "$WORK_TREE"

# Phase 2
info "[Phase 2] Docker 이미지 빌드 ($SERVICE_NAME)"

_dc_build() {
  local svc="$1"
  if [ "$DOCKER_NO_CACHE" = "1" ]; then
    info "docker compose build --no-cache $svc"
    docker compose -f "$DOCKER_COMPOSE_FILE" build --no-cache "$svc"
  else
    info "docker compose build $svc"
    docker compose -f "$DOCKER_COMPOSE_FILE" build "$svc"
  fi
}

case "$SERVICE_NAME" in
  frontend) _dc_build frontend ;;
  backend)  _dc_build backend ;;
  all)
    _dc_build backend
    _dc_build frontend
    ;;
  docker-only) info "빌드 스킵 (docker-only)" ;;
  *) warn "알 수 없는 SERVICE_NAME=$SERVICE_NAME" ;;
esac

# Phase 3
info "[Phase 3] Docker Compose up"

case "$SERVICE_NAME" in
  frontend)
    docker compose -f "$DOCKER_COMPOSE_FILE" up -d --no-deps frontend
    ;;
  backend)
    docker compose -f "$DOCKER_COMPOSE_FILE" up -d mysql
    docker compose -f "$DOCKER_COMPOSE_FILE" up -d --no-deps backend
    ;;
  all|docker-only)
    docker compose -f "$DOCKER_COMPOSE_FILE" up -d
    ;;
esac

# Phase 4
info "[Phase 4] 헬스체크"

check_url() {
  local name="$1" url="$2" retries="${3:-20}" interval="${4:-5}"
  local i code
  for i in $(seq 1 "$retries"); do
    code=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo "000")
    if [[ "$code" =~ ^2 ]]; then
      info "$name OK (HTTP $code)"
      return 0
    fi
    warn "$name 대기 ($i/$retries) HTTP $code"
    sleep "$interval"
  done
  warn "$name 헬스체크 실패: $url"
  return 1
}

case "$SERVICE_NAME" in
  frontend) check_url "Frontend" "$FRONTEND_URL" || true ;;
  backend)  check_url "Backend" "$BACKEND_HEALTH_URL" || true ;;
  all|docker-only)
    check_url "Backend" "$BACKEND_HEALTH_URL" || true
    check_url "Frontend" "$FRONTEND_URL" || true
    ;;
esac

log "======================================================"
log "  배포 완료: $(date '+%Y-%m-%d %H:%M:%S')"
log "  커밋: $(git --git-dir="$GIT_DIR" log --oneline -1 2>/dev/null || echo N/A)"
log "  URL: https://billcare.exdev.co.kr"
log "======================================================"

docker compose -f "$DOCKER_COMPOSE_FILE" ps 2>/dev/null || docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
