#!/bin/bash

# --- CONFIGURATION ---
REPO_NAME="your_repo_name" # TODO: Set this to your repo name
SUPABASE_URL="https://supabase.appmonitor.co.za/" # TODO: Set your Supabase URL
SUPABASE_KEY="your_supabase_service_role_key" # TODO: Set your Supabase service role key
PORT=9000
BACKUP_DIR="$(dirname "$0")/../backup"
MIGRATION_DIR="$(dirname "$0")/../migration"
ENV_FILE="$(dirname "$0")/../.env"
LOG_FILE="$(dirname "$0")/deploy.log"
MAX_RETRIES=3

# --- LOAD ENV ---
if [ -f "$ENV_FILE" ]; then
  export $(grep -v '^#' "$ENV_FILE" | xargs)
else
  echo ".env file not found!" | tee -a "$LOG_FILE"
  exit 1
fi

# --- PARSE DB URL ---
parse_db_url() {
  # Expects mysql://user:pass@host:port/db?params
  proto_removed="${DATABASE_URL#*://}"
  user_pass_host_port_db="${proto_removed%%\?*}"
  user_pass="${user_pass_host_port_db%%@*}"
  host_port_db="${user_pass_host_port_db#*@}"
  DB_USER="${user_pass%%:*}"
  DB_PASS="${user_pass#*:}"
  DB_HOST="${host_port_db%%:*}"
  port_db="${host_port_db#*:}"
  DB_PORT="${port_db%%/*}"
  DB_NAME="${port_db#*/}"
}

# --- SUPABASE HELPERS ---
update_status() {
  local id="$1"; local status="$2"
  curl -s -X PATCH "$SUPABASE_URL/rest/v1/code_deploy?id=eq.$id" \
    -H "apikey: $SUPABASE_KEY" -H "Authorization: Bearer $SUPABASE_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"status\":\"$status\",\"updated_at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" >> "$LOG_FILE"
}
update_error() {
  local id="$1"; local error="$2"
  curl -s -X PATCH "$SUPABASE_URL/rest/v1/code_deploy?id=eq.$id" \
    -H "apikey: $SUPABASE_KEY" -H "Authorization: Bearer $SUPABASE_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"error\":\"$error\",\"status\":\"error\",\"updated_at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" >> "$LOG_FILE"
}
mark_processed() {
  local id="$1"
  curl -s -X PATCH "$SUPABASE_URL/rest/v1/code_deploy?id=eq.$id" \
    -H "apikey: $SUPABASE_KEY" -H "Authorization: Bearer $SUPABASE_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"processed\":true,\"status\":\"running\",\"updated_at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" >> "$LOG_FILE"
}

# --- SERVER MANAGEMENT ---
stop_server() {
  fuser -k ${PORT}/tcp 2>/dev/null || true
}
start_server() {
  npm run start:production &
  sleep 5
}
check_server() {
  curl -s "http://localhost:$PORT" >/dev/null
}

# --- DB BACKUP ---
backup_db() {
  parse_db_url
  mkdir -p "$BACKUP_DIR"
  mysqldump -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$BACKUP_DIR/backup_$(date +%Y%m%d_%H%M%S).sql"
}

# --- MIGRATIONS ---
run_migrations() {
  parse_db_url
  for file in "$MIGRATION_DIR"/*.sql; do
    fname=$(basename "$file")
    # Check if migration already applied for this repo
    applied=$(mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -N -e "SELECT COUNT(*) FROM migrations WHERE repo_name='$REPO_NAME' AND filename='$fname';" 2>/dev/null)
    if [ "$applied" = "0" ]; then
      mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" < "$file"
      mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "INSERT INTO migrations (repo_name, filename) VALUES ('$REPO_NAME', '$fname');"
    fi
  done
}

# --- MAIN LOOP ---
while true; do
  # 1. Check Supabase code_deploy for unprocessed row for this repo
  deploy_json=$(curl -s "$SUPABASE_URL/rest/v1/code_deploy?repo_name=eq.$REPO_NAME&processed=eq.false&select=id" -H "apikey: $SUPABASE_KEY" -H "Authorization: Bearer $SUPABASE_KEY")
  deploy_id=$(echo "$deploy_json" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
  if [ -n "$deploy_id" ]; then
    update_status "$deploy_id" "starting"
    echo "[$(date)] Starting deploy for $REPO_NAME (id=$deploy_id)" | tee -a "$LOG_FILE"
    # 3. Stop current server
    stop_server
    update_status "$deploy_id" "stopped server"
    # 5. Git pull
    if git pull; then
      update_status "$deploy_id" "git pulled"
    else
      update_error "$deploy_id" "git pull failed"
      continue
    fi
    # 7. Backup DB
    if backup_db; then
      update_status "$deploy_id" "db backed up"
    else
      update_error "$deploy_id" "db backup failed"
      continue
    fi
    # 9. Run migrations
    if run_migrations; then
      update_status "$deploy_id" "migrated"
    else
      update_error "$deploy_id" "migration failed"
      continue
    fi
    # 11. npm install
    if npm install; then
      update_status "$deploy_id" "npm installed"
    else
      update_error "$deploy_id" "npm install failed"
      continue
    fi
    # 13. Start server
    start_server
    # 14. Check server health and self-heal
    retries=0
    until check_server; do
      ((retries++))
      if [ $retries -ge $MAX_RETRIES ]; then
        update_error "$deploy_id" "server failed to start after $MAX_RETRIES attempts"
        break
      fi
      echo "[$(date)] Server not healthy, retry $retries" | tee -a "$LOG_FILE"
      stop_server
      start_server
      sleep 5
    done
    if check_server; then
      mark_processed "$deploy_id"
      update_status "$deploy_id" "running"
      echo "[$(date)] Deploy successful for $REPO_NAME (id=$deploy_id)" | tee -a "$LOG_FILE"
    fi
  fi
  sleep 900
done 