#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────
# EdgeBits — Safe Docker Compose CLI
#
# Master script with individual stack control (edge, edge-manager, sync).
# Allowlisted commands only — destructive operations are blocked.
#
# Usage:
#   ./reset.sh <stack> <command> [args...]
#   ./reset.sh edge up              # start edge in dev mode
#   ./reset.sh edge-manager up             # start edge-manager in dev mode
#   ./reset.sh all up               # start everything
#   ./reset.sh edge logs core       # tail edge gateway logs
#   ./reset.sh reset                # full nuclear reset (all stacks)
#
# ─────────────────────────────────────────────────────────────────
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
EDGE_DIR="$ROOT_DIR/edge"
EDGE_MANAGER_DIR="$ROOT_DIR/edge-manager"

DOCKER="${DOCKER:-$(command -v docker 2>/dev/null || echo /usr/local/bin/docker)}"

# Colors
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'

log()  { echo -e "${GREEN}▸${NC} $1"; }
warn() { echo -e "${YELLOW}▸${NC} $1"; }
err()  { echo -e "${RED}✗${NC} $1"; }
hdr()  { echo -e "\n${CYAN}┌─ ${BOLD}$1${NC}\n${CYAN}└──────────────────────────────────${NC}\n"; }

# ── Safety: blocked patterns ──
BLOCKED_PATTERNS="rm |rmi |prune|system prune|volume rm|container rm|image rm"

_safety_check() {
  local args="$*"
  if echo "$args" | grep -qEi "($BLOCKED_PATTERNS)"; then
    err "Blocked: destructive command not allowed"
    echo "  Blocked patterns: $BLOCKED_PATTERNS"
    exit 1
  fi
}

# ── Compose commands per stack ──
_compose() {
  local dir="$1"; shift
  (cd "$dir" && $DOCKER compose -f docker-compose.yml -f docker-compose.dev.yml "$@")
}

_compose_edge()  { _compose "$EDGE_DIR" "$@"; }
_compose_edge_manager() { _compose "$EDGE_MANAGER_DIR" "$@"; }

# ── Individual stack commands ──

stack_up() {
  local stack="$1"; shift
  hdr "$stack — Starting (dev mode, hot reload)"
  case "$stack" in
    edge)  _compose_edge up --build "$@" ;;
    edge-manager) _compose_edge-manager up --build "$@" ;;
    all)   stack_up edge-manager -d "$@"; stack_up edge "$@" ;;
  esac
}

stack_down() {
  local stack="$1"; shift
  hdr "$stack — Stopping"
  case "$stack" in
    edge)  _compose_edge down "$@" ;;
    edge-manager) _compose_edge-manager down "$@" ;;
    all)   _compose_edge down "$@"; _compose_edge-manager down "$@" ;;
  esac
}

stack_restart() {
  local stack="$1"; shift
  hdr "$stack — Restarting"
  stack_down "$stack" 2>/dev/null || true
  stack_up "$stack" -d "$@"
  echo ""
  log "Waiting for services..."
  sleep 8
  stack_health "$stack"
}

stack_logs() {
  local stack="$1"; shift
  case "$stack" in
    edge)  _compose_edge logs -f --tail 50 "$@" ;;
    edge-manager) _compose_edge-manager logs -f --tail 50 "$@" ;;
    all)   err "Use 'edge' or 'edge-manager' for logs"; exit 1 ;;
  esac
}

stack_ps() {
  local stack="$1"
  case "$stack" in
    edge)  hdr "Edge Containers"; _compose_edge ps ;;
    edge-manager) hdr "Edge Manager Containers"; _compose_edge_manager ps ;;
    all)   stack_ps edge; stack_ps edge-manager ;;
  esac
}

stack_build() {
  local stack="$1"; shift
  hdr "$stack — Building"
  case "$stack" in
    edge)  _compose_edge build "$@" ;;
    edge-manager) _compose_edge_manager build "$@" ;;
    all)   _compose_edge_manager build "$@"; _compose_edge build "$@" ;;
  esac
}

stack_health() {
  local stack="$1"
  echo ""
  if [[ "$stack" == "edge-manager" || "$stack" == "all" ]]; then
    if curl -sf http://localhost:9000/health > /dev/null 2>&1; then
      log "☁️  Cloud API (9000)  — ${GREEN}UP${NC}"
    else
      warn "☁️  Cloud API (9000)  — ${RED}DOWN${NC}"
    fi
  fi
  if [[ "$stack" == "edge" || "$stack" == "all" ]]; then
    if curl -sf http://localhost:8080/_system/health > /dev/null 2>&1; then
      log "📡 Edge Gateway (8080) — ${GREEN}UP${NC}"
      # Show service count
      local svc_count
      svc_count=$(curl -sf http://localhost:8080/api/v1/services 2>/dev/null | python3 -c "import sys,json; print(len(json.load(sys.stdin).get('services',[])))" 2>/dev/null || echo "?")
      log "   Services registered: $svc_count"
    else
      warn "📡 Edge Gateway (8080) — ${RED}DOWN${NC}"
    fi
    if curl -sf http://localhost:3000 > /dev/null 2>&1; then
      log "🖥  Edge UI (3000)     — ${GREEN}UP${NC}"
    else
      warn "🖥  Edge UI (3000)     — ${RED}DOWN${NC}"
    fi
  fi
  echo ""
}

# ── Full reset (nuclear) ──

cmd_reset() {
  hdr "Full Reset — All Stacks"
  warn "This will stop all containers, delete volumes, and wipe all data."
  read -p "Continue? [y/N] " confirm
  if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
    echo "Cancelled."
    exit 0
  fi

  log "Stopping edge stack..."
  _compose_edge down --remove-orphans -v 2>/dev/null || true

  log "Stopping edge-manager stack..."
  _compose_edge-manager down --remove-orphans -v 2>/dev/null || true

  # Remove edge-sync SQLite
  if [ -f "$EDGE_DIR/edge-sync/data/sync.db" ]; then
    log "Removing edge-sync local SQLite..."
    rm -f "$EDGE_DIR/edge-sync/data/sync.db"
    rm -f "$EDGE_DIR/edge-sync/data/sync.db-wal"
    rm -f "$EDGE_DIR/edge-sync/data/sync.db-shm"
  fi

  # Remove stale gateway SQLite
  find "$EDGE_DIR" -name "*.db" -path "*/data/*" -delete 2>/dev/null || true
  find "$EDGE_DIR" -name "*.db-wal" -path "*/data/*" -delete 2>/dev/null || true
  find "$EDGE_DIR" -name "*.db-shm" -path "*/data/*" -delete 2>/dev/null || true

  echo ""
  log "✅ All data wiped. Fresh state."
  echo ""

  if [[ "${1:-}" == "--no-start" ]]; then
    warn "Skipping restart (--no-start)."
    exit 0
  fi

  log "Rebuilding and starting edge-manager stack (dev mode)..."
  _compose_edge-manager up --build -d

  log "Rebuilding and starting edge stack (dev mode)..."
  _compose_edge up --build -d

  echo ""
  log "Waiting for services..."
  sleep 10

  stack_health all
  log "Done. Full reset complete."
}

# ── Help ──

cmd_help() {
  cat << 'EOF'

  EdgeBits — Safe Docker Compose CLI

  USAGE:
    ./reset.sh <stack> <command> [args...]

  STACKS:
    edge        Edge platform (gateway, mqtt, ui, connectors, egress)
    edge-manager  Edge Manager platform (API server, Redis, Postgres)
    all         Both edge + edge-manager

  COMMANDS:
    up              Start stack in dev mode (hot reload, attached)
    up -d           Start stack in dev mode (detached)
    down            Stop stack
    restart         Stop + start (detached)
    logs [service]  Tail logs (all or specific container)
    ps              List running containers
    build           Build images without starting
    health          Check endpoint health

  SPECIAL:
    reset           Full nuclear reset — stop all, wipe volumes, start fresh
    help            Show this help

  BLOCKED:
    rm, prune, rmi — destructive commands are not allowed.

  EXAMPLES:
    ./reset.sh edge up              # start edge attached (see logs)
    ./reset.sh edge up -d           # start edge detached
    ./reset.sh edge-manager up -d          # start edge-manager detached
    ./reset.sh all up -d            # start everything detached
    ./reset.sh edge logs core       # tail gateway logs
    ./reset.sh edge logs ui         # tail UI logs
    ./reset.sh edge-manager logs api       # tail edge-manager API logs
    ./reset.sh edge restart         # quick edge restart
    ./reset.sh all health           # check all endpoints
    ./reset.sh reset                # full nuclear reset

EOF
}

# ── Main dispatch ──

if [ $# -eq 0 ]; then
  cmd_help
  exit 0
fi

FIRST="$1"; shift

# Safety check all args
_safety_check "$FIRST" "$@"

# Special top-level commands (no stack needed)
case "$FIRST" in
  reset)  cmd_reset "$@"; exit 0 ;;
  help|-h|--help) cmd_help; exit 0 ;;
esac

# Stack + command pattern
STACK="$FIRST"
if [[ "$STACK" != "edge" && "$STACK" != "edge-manager" && "$STACK" != "all" ]]; then
  err "Unknown stack: $STACK"
  echo "  Valid stacks: edge, edge-manager, all"
  exit 1
fi

if [ $# -eq 0 ]; then
  err "No command specified. Use: up, down, restart, logs, ps, build, health"
  exit 1
fi

CMD="$1"; shift
_safety_check "$CMD" "$@"

case "$CMD" in
  up)       stack_up "$STACK" "$@" ;;
  down)     stack_down "$STACK" "$@" ;;
  restart)  stack_restart "$STACK" "$@" ;;
  logs)     stack_logs "$STACK" "$@" ;;
  ps)       stack_ps "$STACK" ;;
  build)    stack_build "$STACK" "$@" ;;
  health)   stack_health "$STACK" ;;
  *)
    err "Unknown command: $CMD"
    echo "  Valid commands: up, down, restart, logs, ps, build, health"
    exit 1
    ;;
esac
