#!/usr/bin/env bash
# Starian SSH Setup Script
# Usage (원격): curl -fsSL https://setup.starian.us/ssh | bash
# Usage (로컬): bash /home/llm/projects/oracle-setup/ssh
#
# 목적: SSH 키와 config만 설정. 이미 환경이 있는 디바이스에 SSH 접근만 추가.
# Seoul(server-seoul)이 메인 허브.
#
# 동작:
#   - OS 자동 감지 (Linux/macOS/Android-Termux)
#   - Starian SSH 키 다운로드/생성 (~/.ssh/starian_key.pem)
#   - ~/.ssh/config에 Starian 서버 엔트리 추가
#   - 기존 config 백업
#   - 권한 설정 (600/700)

set -euo pipefail

# ── 색상 ──
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
info()    { echo -e "${BLUE}[starian]${NC} $1"; }
ok()      { echo -e "${GREEN}  [+]${NC} $1"; }
warn()    { echo -e "${YELLOW}  [!]${NC} $1"; }
fail()    { echo -e "${RED}  [x]${NC} $1"; exit 1; }
section() { echo -e "\n${BLUE}──${NC} $1"; }

# ── OS 감지 ──
detect_os() {
  if [ -d "/data/data/com.termux" ] || [ -n "${TERMUX_VERSION:-}" ]; then
    DETECTED_OS="termux"
  elif [[ "$(uname -s)" == "Darwin" ]]; then
    DETECTED_OS="macos"
  elif [[ "$(uname -s)" == "Linux" ]]; then
    if grep -qi microsoft /proc/version 2>/dev/null; then
      DETECTED_OS="wsl"
    else
      DETECTED_OS="linux"
    fi
  else
    DETECTED_OS="unknown"
  fi
}

# ── SSH 디렉토리 결정 ──
get_ssh_dir() {
  if [ "$DETECTED_OS" = "termux" ]; then
    echo "${HOME}/.ssh"
  else
    echo "${HOME}/.ssh"
  fi
}

# ── 헤더 출력 ──
echo ""
echo "  Starian SSH Setup"
echo "  =================="
echo ""

detect_os
SSH_DIR="$(get_ssh_dir)"
SSH_KEY="${SSH_DIR}/starian_key.pem"
SSH_CONFIG="${SSH_DIR}/config"

info "OS:       $DETECTED_OS"
info "SSH Dir:  $SSH_DIR"
echo ""

# ═══════════════════════════════════════════════
# Step 0: Tailscale + SSH 서버 확인
# ═══════════════════════════════════════════════
section "Step 0: Tailscale + SSH 서버 확인"

# Tailscale 설치/확인
if command -v tailscale &>/dev/null; then
  ok "Tailscale (이미 설치됨)"
  if tailscale status &>/dev/null 2>&1; then
    ts_ip="$(tailscale ip -4 2>/dev/null || echo 'IP 확인 불가')"
    ok "Tailscale 연결됨 ($ts_ip)"
  else
    warn "Tailscale 로그인이 필요합니다"
    case "$DETECTED_OS" in
      macos) open -a Tailscale 2>/dev/null; info "Tailscale 앱이 열렸습니다. 로그인하세요." ;;
      termux) warn "Google Play Store에서 Tailscale 앱을 설치하고 로그인하세요" ;;
      *) sudo tailscale up 2>/dev/null || tailscale up 2>/dev/null || warn "tailscale up 실행 실패" ;;
    esac
  fi
else
  info "Tailscale 설치 중..."
  case "$DETECTED_OS" in
    macos)     brew install --cask tailscale 2>/dev/null && ok "Tailscale 설치 완료" || warn "Tailscale 수동 설치: https://tailscale.com/download" ;;
    linux|wsl) curl -fsSL https://tailscale.com/install.sh | sh 2>/dev/null && ok "Tailscale 설치 완료" || warn "Tailscale 수동 설치: https://tailscale.com/download" ;;
    termux)    warn "Google Play Store에서 Tailscale 앱을 설치하세요"; info "  https://play.google.com/store/apps/details?id=com.tailscale.ipn" ;;
    *)         warn "Tailscale 수동 설치: https://tailscale.com/download" ;;
  esac
fi

# SSH 서버 확인
case "$DETECTED_OS" in
  macos)
    if systemsetup -getremotelogin 2>/dev/null | grep -q "On"; then
      ok "SSH 서버 활성화됨"
    else
      if sudo systemsetup -setremotelogin on 2>/dev/null; then
        ok "SSH 서버 활성화 완료"
      else
        warn "SSH 서버 수동 활성화: 시스템 환경설정 > 공유 > 원격 로그인"
      fi
    fi
    ;;
  linux|wsl)
    if systemctl is-active sshd &>/dev/null || systemctl is-active ssh &>/dev/null; then
      ok "SSH 서버 실행 중"
    else
      sudo systemctl enable --now sshd 2>/dev/null || sudo systemctl enable --now ssh 2>/dev/null && ok "SSH 서버 시작 완료" || warn "SSH 서버 시작 실패"
    fi
    ;;
  termux)
    if command -v sshd &>/dev/null; then
      ok "sshd 사용 가능 (포트 8022)"
    else
      pkg install -y openssh 2>/dev/null && ok "openssh 설치 완료" || warn "openssh 설치 실패"
    fi
    info "Termux SSH 시작: sshd / 비밀번호 설정: passwd"
    ;;
esac

# ═══════════════════════════════════════════════
# Step 1: SSH 디렉토리 생성 + 권한
# ═══════════════════════════════════════════════
section "Step 1: SSH 디렉토리 확인"

mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"
ok "SSH 디렉토리 준비: $SSH_DIR"

# ═══════════════════════════════════════════════
# Step 2: SSH 키 설정
# ═══════════════════════════════════════════════
section "Step 2: SSH 키 설정"

if [ -f "$SSH_KEY" ]; then
  ok "SSH 키 이미 존재: $SSH_KEY"
else
  # Seoul 허브에서 키 다운로드 시도
  SETUP_BASE="https://setup.starian.us"
  TMP_KEY="/tmp/starian_key_download.pem"

  if curl -fsSL --connect-timeout 10 --max-time 30 "${SETUP_BASE}/keys/starian_key.pem" -o "$TMP_KEY" 2>/dev/null; then
    mv "$TMP_KEY" "$SSH_KEY"
    chmod 600 "$SSH_KEY"
    ok "SSH 키 다운로드 완료: $SSH_KEY"
  else
    rm -f "$TMP_KEY"
    warn "키 다운로드 실패 — 새 키를 생성합니다"

    if [ "$DETECTED_OS" = "termux" ]; then
      ssh-keygen -t ed25519 -f "$SSH_KEY" -N "" -C "starian@$(hostname)" 2>/dev/null
    else
      ssh-keygen -t ed25519 -f "$SSH_KEY" -N "" -C "starian@$(hostname)" 2>/dev/null
    fi

    chmod 600 "$SSH_KEY"
    ok "SSH 키 생성 완료: $SSH_KEY"
    echo ""
    warn "새로 생성된 공개 키를 Starian 서버에 등록해야 합니다:"
    echo ""
    echo "  공개 키 내용:"
    cat "${SSH_KEY}.pub"
    echo ""
    warn "위 내용을 각 서버의 ~/.ssh/authorized_keys에 추가하세요."
  fi
fi

# ═══════════════════════════════════════════════
# Step 3: SSH config 백업
# ═══════════════════════════════════════════════
section "Step 3: SSH config 백업"

if [ -f "$SSH_CONFIG" ]; then
  BACKUP_STAMP="$(date +%Y%m%d-%H%M%S)"
  BACKUP_FILE="${SSH_CONFIG}.bak-${BACKUP_STAMP}"
  cp "$SSH_CONFIG" "$BACKUP_FILE"
  ok "기존 config 백업: $BACKUP_FILE"
else
  touch "$SSH_CONFIG"
  ok "새 config 파일 생성"
fi

chmod 600 "$SSH_CONFIG"

# ═══════════════════════════════════════════════
# Step 4: Starian 서버 엔트리 추가
# ═══════════════════════════════════════════════
section "Step 4: SSH config에 Starian 서버 추가"

# Starian 마커 확인 — 이미 등록되어 있으면 교체
MARKER_BEGIN="# ── Starian Servers ──"
MARKER_END="# ── End Starian ──"

STARIAN_BLOCK="$MARKER_BEGIN
# Seoul Hub (메인 허브)
Host server-seoul seoul
  HostName 34.22.90.130
  User llm
  IdentityFile $SSH_KEY
  Port 22
  ServerAliveInterval 60
  ServerAliveCountMax 3

Host seoul.starian.us
  HostName 34.22.90.130
  User llm
  IdentityFile $SSH_KEY
  Port 22
  ServerAliveInterval 60
  ServerAliveCountMax 3

# GCP US (server-main)
Host server-main
  HostName 34.56.229.230
  User llm
  IdentityFile $SSH_KEY
  Port 22
  ServerAliveInterval 60
  ServerAliveCountMax 3

# Mac Mini M4
Host macmini
  HostName macmini.starian.us
  User whitegun
  IdentityFile $SSH_KEY
  Port 22
  ServerAliveInterval 60
  ServerAliveCountMax 3

# Galaxy S25+ (Termux)
Host sm-s936n
  HostName sm-s936n.starian.us
  User u0_a229
  IdentityFile $SSH_KEY
  Port 8022
  ServerAliveInterval 60
  ServerAliveCountMax 3
$MARKER_END"

if grep -q "$MARKER_BEGIN" "$SSH_CONFIG" 2>/dev/null; then
  # 기존 Starian 블록 교체 (while read — macOS BSD awk 호환)
  in_block=0
  while IFS= read -r line; do
    if [ "$line" = "$MARKER_BEGIN" ]; then
      in_block=1
      echo "$STARIAN_BLOCK"
      continue
    fi
    if [ "$in_block" = "1" ] && [ "$line" = "$MARKER_END" ]; then
      in_block=0
      continue
    fi
    if [ "$in_block" = "0" ]; then
      echo "$line"
    fi
  done < "$SSH_CONFIG" > "${SSH_CONFIG}.tmp"
  mv "${SSH_CONFIG}.tmp" "$SSH_CONFIG"
  ok "Starian 서버 엔트리 업데이트 완료"
else
  # 새로 추가 (파일 끝에)
  {
    echo ""
    echo "$STARIAN_BLOCK"
  } >> "$SSH_CONFIG"
  ok "Starian 서버 엔트리 추가 완료"
fi

chmod 600 "$SSH_CONFIG"

# ═══════════════════════════════════════════════
# Step 5: 연결 테스트
# ═══════════════════════════════════════════════
section "Step 5: 연결 테스트"

test_ssh() {
  local host="$1"
  local label="$2"
  if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new -o BatchMode=yes "$host" "echo OK" 2>/dev/null | grep -q "OK"; then
    ok "$label ($host) — 연결 성공"
  else
    warn "$label ($host) — 연결 실패 (키 등록 또는 네트워크 확인 필요)"
  fi
}

test_ssh "server-seoul"  "Seoul Hub"
test_ssh "server-main"   "GCP US"
test_ssh "macmini"       "Mac Mini"
test_ssh "sm-s936n"      "Galaxy S25+"

# ═══════════════════════════════════════════════
# 완료
# ═══════════════════════════════════════════════
echo ""
echo "  Starian SSH Setup — Complete"
echo "  =============================="
echo ""
echo "  설치 항목:"
echo "    SSH 키:     $SSH_KEY"
echo "    SSH config: $SSH_CONFIG"
echo ""
echo "  등록된 호스트:"
echo "    server-seoul (34.22.90.130)    — Seoul Hub (메인)"
echo "    server-main  (34.56.229.230)   — GCP US"
echo "    macmini      (macmini.starian.us)"
echo "    sm-s936n     (sm-s936n.starian.us:8022)"
echo ""
echo "  사용법:"
echo "    ssh server-seoul"
echo "    ssh macmini"
echo ""

# ═══════════════════════════════════════════════
# Step 6: Seoul Hub 등록
# ═══════════════════════════════════════════════
section "Step 6: Seoul Hub 등록"
PUBLIC_KEY=""
# 공개키 파일 찾기 — 없으면 자동 추출
if [ -f "${SSH_KEY}.pub" ]; then
  PUBLIC_KEY="$(cat "${SSH_KEY}.pub")"
elif [ -f "${SSH_KEY}" ]; then
  # .pub 파일이 없으면 개인키에서 자동 추출
  ssh-keygen -y -f "${SSH_KEY}" > "${SSH_KEY}.pub" 2>/dev/null
  if [ -f "${SSH_KEY}.pub" ]; then
    PUBLIC_KEY="$(cat "${SSH_KEY}.pub")"
    ok "공개키 자동 추출 완료: ${SSH_KEY}.pub"
  fi
fi
if [ -n "$PUBLIC_KEY" ]; then
  # 디바이스 hostname 결정 우선순위:
  #   1) STARIAN_DEVICE_HOSTNAME 환경변수 (ex: STARIAN_DEVICE_HOSTNAME=macpro)
  #   2) 자동 감지 hostname (소문자 + 영숫자/하이픈)
  AUTO_HOSTNAME=$(hostname | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g')
  DEVICE_HOSTNAME="${STARIAN_DEVICE_HOSTNAME:-$AUTO_HOSTNAME}"
  DEVICE_IP=$(curl -s --max-time 5 https://ifconfig.me 2>/dev/null || echo "unknown")
  if [ "$DEVICE_HOSTNAME" != "$AUTO_HOSTNAME" ]; then
    info "디바이스 등록명: ${DEVICE_HOSTNAME} (override; 자동 감지=${AUTO_HOSTNAME})"
  else
    info "디바이스 등록명: ${DEVICE_HOSTNAME} (자동 감지)"
  fi
  RESPONSE=$(curl -s --max-time 10 -X POST "https://dashboard.starian.us/api/register?token=0205" \
    -H "Content-Type: application/json" \
    -d "{\"hostname\": \"${DEVICE_HOSTNAME}\", \"os\": \"${DETECTED_OS}\", \"user\": \"$(whoami)\", \"ip\": \"${DEVICE_IP}\", \"public_key\": \"${PUBLIC_KEY}\"}" 2>/dev/null)
  if echo "$RESPONSE" | grep -q '"success":true'; then
    ok "Seoul Hub 등록 완료 — dashboard에서 확인하세요"
  else
    warn "Hub 등록 실패 — 수동 등록이 필요합니다"
  fi
else
  warn "SSH 공개키를 찾을 수 없어 Hub 등록을 건너뜁니다"
fi
