#!/bin/bash
# ================================================================
# Nexus 6.0 — One-Click Install Script
#
# Usage:
#   curl -fsSL https://YOUR_DOMAIN/deploy/install.sh | sudo bash -s -- --domain nexus.example.com
#   sudo bash install.sh --domain nexus.example.com
#
# Supports: Ubuntu 20.04+, Debian 11+, CentOS 7/8, Rocky 8/9, AlmaLinux 8/9
# Auto-detects BT Panel (宝塔面板) and adapts paths accordingly.
# ================================================================

set -euo pipefail

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

info()  { echo -e "${GREEN}[INFO]${NC} $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; }

# ── Helper: Idempotent config write ──
write_config() {
    local target="$1" content="$2"
    if [ -f "$target" ]; then
        local existing
        existing=$(cat "$target" 2>/dev/null || true)
        if [ "$existing" = "$content" ]; then
            info "  [skip] $target (unchanged)"
            return 0
        fi
        info "  [update] $target (content changed)"
    else
        info "  [create] $target"
    fi
    echo "$content" > "$target"
}

# ── Defaults ──
DOMAIN=""
DEPLOY_DIR=""
PORT=8600
SKIP_NGINX=false
SKIP_SUPERVISOR=false
BT_MODE=false
NEXUS_REPO=""

# ── Parse Arguments ──
while [[ $# -gt 0 ]]; do
    case $1 in
        --domain)          DOMAIN="$2"; shift 2 ;;
        --deploy-dir)      DEPLOY_DIR="$2"; shift 2 ;;
        --port)            PORT="$2"; shift 2 ;;
        --skip-nginx)      SKIP_NGINX=true; shift ;;
        --skip-supervisor) SKIP_SUPERVISOR=true; shift ;;
        --repo)            NEXUS_REPO="$2"; shift 2 ;;
        -h|--help)
            echo "Usage: sudo bash install.sh --domain DOMAIN [options]"
            echo ""
            echo "Options:"
            echo "  --domain DOMAIN       Required. Domain or IP for Nginx server_name"
            echo "  --deploy-dir PATH     Installation directory (auto-detected)"
            echo "  --port PORT           uvicorn port (default: 8600)"
            echo "  --skip-nginx          Skip Nginx configuration"
            echo "  --skip-supervisor     Skip Supervisor configuration"
            echo "  --repo URL            Git repository URL (optional, for cloning)"
            exit 0 ;;
        *) shift ;;
    esac
done

# ── Banner ──
echo ""
echo "=========================================="
echo "  Nexus 6.0 Install Script"
echo "=========================================="
echo ""

# ================================================================
# Phase 1: Pre-flight Checks
# ================================================================

info "Phase 1/7: Pre-flight checks..."

# 1.1 Must run as root
if [ "$(id -u)" -ne 0 ]; then
    error "This script must be run as root. Use: sudo bash install.sh"
    exit 1
fi

# 1.2 Domain is required
if [ -z "$DOMAIN" ]; then
    error "--domain is required. Usage: sudo bash install.sh --domain nexus.example.com"
    exit 1
fi

# 1.3 OS detection
if [ ! -f /etc/os-release ]; then
    error "Cannot detect OS. /etc/os-release not found."
    exit 1
fi

OS_ID=$(grep '^ID=' /etc/os-release | head -1 | cut -d'=' -f2 | tr -d '"' | cut -d'-' -f1)
OS_VERSION=$(grep '^VERSION_ID=' /etc/os-release | head -1 | cut -d'=' -f2 | tr -d '"')

case "$OS_ID" in
    ubuntu|debian) PKG_MANAGER="apt" ;;
    centos|rocky|almalinux|rhel) PKG_MANAGER="yum" ;;
    *)
        warn "Unsupported OS: $OS_ID. Script may still work but is untested."
        PKG_MANAGER="apt"
        ;;
esac
info "  OS: $OS_ID $OS_VERSION (pkg: $PKG_MANAGER)"

# 1.4 BT Panel detection
if [ -d "/www/server/panel" ] && [ -f "/www/server/panel/class/common.py" ]; then
    BT_MODE=true
    info "  BT Panel: detected"
else
    info "  BT Panel: not detected (standard mode)"
fi

# 1.5 Set deploy directory
if [ -z "$DEPLOY_DIR" ]; then
    if [ "$BT_MODE" = true ]; then
        DEPLOY_DIR="/www/wwwroot/$DOMAIN"
    else
        DEPLOY_DIR="/opt/nexus"
    fi
fi
VENV_DIR="$DEPLOY_DIR/venv"

# Set log paths early (used in multiple phases)
if [ "$BT_MODE" = true ]; then
    LOG_DIR="/www/wwwlogs"
else
    LOG_DIR="/var/log/nexus"
fi

info "  Deploy dir: $DEPLOY_DIR"
info "  Domain: $DOMAIN"
info "  Port: $PORT"

# ================================================================
# Phase 2: System Dependencies
# ================================================================

info "Phase 2/7: Installing system dependencies..."

if [ "$PKG_MANAGER" = "apt" ]; then
    export DEBIAN_FRONTEND=noninteractive
    apt-get update -qq
    apt-get install -y -qq \
        python3 python3-venv python3-pip python3-dev \
        build-essential libssl-dev libffi-dev default-libmysqlclient-dev \
        git curl >/dev/null 2>&1 || warn "Some apt packages failed to install (may already exist)"
elif [ "$PKG_MANAGER" = "yum" ]; then
    if command -v dnf >/dev/null 2>&1; then
        dnf install -y -q \
            python3 python3-devel python3-pip \
            gcc openssl-devel libffi-devel mysql-devel \
            git curl >/dev/null 2>&1 || warn "Some dnf packages failed to install"
    else
        yum install -y -q \
            python3 python3-devel python3-pip \
            gcc openssl-devel libffi-devel mysql-devel \
            git curl >/dev/null 2>&1 || warn "Some yum packages failed to install"
    fi
fi

# ================================================================
# Phase 3: Python 3.10+ Resolution
# ================================================================

info "Phase 3/7: Resolving Python 3.10+..."

PYTHON=""
CANDIDATES="python3.12 python3.11 python3.10 /usr/bin/python3.12 /usr/bin/python3.11 /usr/bin/python3.10 python3"

# Add BT Panel Python paths
if [ "$BT_MODE" = true ]; then
    for p in /www/server/python-manager/versions/*/bin/python3.*; do
        [ -x "$p" ] && CANDIDATES="$CANDIDATES $p"
    done
fi

for candidate in $CANDIDATES; do
    if command -v "$candidate" >/dev/null 2>&1 || [ -x "$candidate" ]; then
        ver=$("$candidate" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || true)
        if [ -n "$ver" ]; then
            major=$(echo "$ver" | cut -d'.' -f1)
            minor=$(echo "$ver" | cut -d'.' -f2)
            if [ "$major" -eq 3 ] && [ "${minor:-0}" -ge 10 ] 2>/dev/null; then
                PYTHON="$candidate"
                break
            fi
        fi
    fi
done

# Fallback: install Python 3.12 on Ubuntu via deadsnakes PPA
if [ -z "$PYTHON" ] && [ "$OS_ID" = "ubuntu" ]; then
    warn "  Python 3.10+ not found. Adding deadsnakes PPA..."
    export DEBIAN_FRONTEND=noninteractive
    apt-get install -y -qq software-properties-common >/dev/null 2>&1
    add-apt-repository -y ppa:deadsnakes/ppa >/dev/null 2>&1
    apt-get update -qq
    apt-get install -y -qq python3.12 python3.12-venv python3.12-dev >/dev/null 2>&1
    if command -v python3.12 >/dev/null 2>&1; then
        PYTHON="python3.12"
    fi
fi

if [ -z "$PYTHON" ]; then
    error "Python 3.10+ is required but not found."
    error "Install Python 3.10+ manually and re-run."
    exit 1
fi

PYTHON_VERSION=$("$PYTHON" --version 2>&1)
info "  Using: $PYTHON ($PYTHON_VERSION)"

# ================================================================
# Phase 4: Application Deployment
# ================================================================

info "Phase 4/7: Deploying application..."

# 4.1 Create deploy directory
mkdir -p "$DEPLOY_DIR"

# 4.2 Download / Clone Nexus
if [ -d "$DEPLOY_DIR/server" ] && [ -d "$DEPLOY_DIR/web" ]; then
    info "  Application files already exist in $DEPLOY_DIR (skipping download)"
    if [ -d "$DEPLOY_DIR/.git" ]; then
        info "  Git repo detected, pulling latest..."
        (cd "$DEPLOY_DIR" && git pull --ff-only 2>/dev/null || warn "  git pull failed (may have local changes)")
    fi
elif [ -n "$NEXUS_REPO" ]; then
    info "  Cloning from $NEXUS_REPO..."
    git clone "$NEXUS_REPO" "$DEPLOY_DIR" 2>/dev/null || {
        error "git clone failed. Check the repository URL."
        exit 1
    }
else
    error "No application files found in $DEPLOY_DIR and no --repo URL provided."
    error "Either:"
    error "  1. Copy Nexus files to $DEPLOY_DIR manually and re-run"
    error "  2. Use --repo https://your-gitea-url/Nexus.git"
    exit 1
fi

# 4.3 Create Python venv
if [ -d "$VENV_DIR/bin" ] && "$VENV_DIR/bin/python" -c 'import sys; v=sys.version_info; assert v.major==3 and v.minor>=10' 2>/dev/null; then
    info "  venv already exists with Python 3.10+ (skipping)"
else
    info "  Creating Python venv..."
    rm -rf "$VENV_DIR"
    "$PYTHON" -m venv "$VENV_DIR"
fi

# 4.4 Install pip dependencies
info "  Installing Python dependencies (this may take a few minutes)..."
"$VENV_DIR/bin/pip" install -q --upgrade pip
"$VENV_DIR/bin/pip" install -q -r "$DEPLOY_DIR/requirements.txt" 2>/dev/null || {
    warn "  pip install had some warnings, but continuing..."
}

# 4.5 Create log directory
mkdir -p "$LOG_DIR"

# 4.6 Create backup directory
mkdir -p "$DEPLOY_DIR/backups"

# ================================================================
# Phase 5: Supervisor Configuration
# ================================================================

if [ "$SKIP_SUPERVISOR" = true ]; then
    warn "Phase 5/7: Skipping Supervisor (per --skip-supervisor)"
else
    info "Phase 5/7: Configuring Supervisor..."

    # Calculate worker count
    WORKERS=$(nproc 2>/dev/null || echo 2)
    [ "$WORKERS" -gt 4 ] && WORKERS=4
    [ "$WORKERS" -lt 1 ] && WORKERS=1

    # Set Supervisor config path
    if [ "$BT_MODE" = true ]; then
        SUPERVISOR_CONF_DIR="/www/server/panel/plugin/supervisor/profile"
        CONF_FILE="$SUPERVISOR_CONF_DIR/nexus.ini"
    else
        SUPERVISOR_CONF_DIR="/etc/supervisor/conf.d"
        CONF_FILE="$SUPERVISOR_CONF_DIR/nexus.conf"
    fi

    # Generate Supervisor config
    SUPERVISOR_CONF="[program:nexus]
command=$VENV_DIR/bin/uvicorn server.main:app --host 0.0.0.0 --port $PORT --workers $WORKERS --loop uvloop --http httptools --log-level info
directory=$DEPLOY_DIR
user=root
autostart=true
autorestart=true
startretries=10
startsecs=3
stopwaitsecs=10
stopsignal=INT
environment=PATH=\"$VENV_DIR/bin:%(ENV_PATH)s\",HOME=\"/root\",NEXUS_WORKERS=\"$WORKERS\"
stderr_logfile=$LOG_DIR/nexus_error.log
stdout_logfile=$LOG_DIR/nexus_access.log
stderr_logfile_maxbytes=50MB
stdout_logfile_maxbytes=50MB
stderr_logfile_backups=5
stdout_logfile_backups=5"

    # Write config (idempotent)
    mkdir -p "$SUPERVISOR_CONF_DIR"
    write_config "$CONF_FILE" "$SUPERVISOR_CONF"

    # Ensure Supervisor is running
    if ! supervisorctl status >/dev/null 2>&1; then
        if [ "$BT_MODE" = true ]; then
            if [ -f /etc/init.d/supervisor ]; then
                /etc/init.d/supervisor start >/dev/null 2>&1 || true
            fi
        else
            systemctl start supervisor >/dev/null 2>&1 || true
        fi
        sleep 2
    fi

    # Reload Supervisor config
    supervisorctl reread >/dev/null 2>&1 || true
    supervisorctl update >/dev/null 2>&1 || true
    info "  Supervisor config written to $CONF_FILE (workers=$WORKERS)"
fi

# ================================================================
# Phase 6: Nginx Configuration
# ================================================================

if [ "$SKIP_NGINX" = true ]; then
    warn "Phase 6/7: Skipping Nginx (per --skip-nginx)"
else
    info "Phase 6/7: Configuring Nginx..."

    if [ "$BT_MODE" = true ]; then
        NGINX_CONF_FILE="/www/server/panel/vhost/nginx/$DOMAIN.conf"
        NGINX_RELOAD_CMD="/www/server/nginx/sbin/nginx -s reload"
        NGINX_TEST_CMD="/www/server/nginx/sbin/nginx -t"
        NGINX_ACCESS_LOG="/www/wwwlogs/$DOMAIN.log"
        NGINX_ERROR_LOG="/www/wwwlogs/$DOMAIN.error.log"
    else
        NGINX_CONF_FILE="/etc/nginx/sites-available/nexus"
        NGINX_RELOAD_CMD="systemctl reload nginx"
        NGINX_TEST_CMD="nginx -t"
        NGINX_ACCESS_LOG="/var/log/nginx/nexus_access.log"
        NGINX_ERROR_LOG="/var/log/nginx/nexus_error.log"
    fi

    NGINX_CONF="# Nexus 6.0 — Nginx Reverse Proxy
# Auto-generated by install.sh
upstream nexus_api {
    server 127.0.0.1:$PORT;
    keepalive 32;
}

server {
    listen 80;
    server_name $DOMAIN;

    # Reverse proxy to Nexus (uvicorn)
    location / {
        proxy_pass http://nexus_api;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }

    # WebSocket support (terminal, alerts)
    location /ws/ {
        proxy_pass http://nexus_api;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection \"upgrade\";
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_read_timeout 3600s;
    }

    # Static assets caching
    location /app/vendor/ {
        proxy_pass http://nexus_api;
        expires 7d;
        add_header Cache-Control \"public, immutable\";
    }

    # Block sensitive files
    location ~ ^/(\\.env|\\.git|\\.svn) {
        return 404;
    }

    # Block config.json access
    location ~ /data/config\\.json$ {
        return 404;
    }

    # Upload limit
    client_max_body_size 100m;

    # Well-known for SSL cert validation
    location ~ \\.well-known {
        allow all;
    }

    access_log  $NGINX_ACCESS_LOG;
    error_log   $NGINX_ERROR_LOG;
}"

    # Write Nginx config
    if [ "$BT_MODE" = true ]; then
        write_config "$NGINX_CONF_FILE" "$NGINX_CONF"
    else
        mkdir -p /etc/nginx/sites-available
        write_config "$NGINX_CONF_FILE" "$NGINX_CONF"
        if [ ! -L /etc/nginx/sites-enabled/nexus ]; then
            ln -sf "$NGINX_CONF_FILE" /etc/nginx/sites-enabled/nexus
        fi
    fi

    # Test and reload Nginx
    if $NGINX_TEST_CMD >/dev/null 2>&1; then
        $NGINX_RELOAD_CMD >/dev/null 2>&1 || warn "  Nginx reload failed"
        info "  Nginx config written to $NGINX_CONF_FILE"
    else
        warn "  Nginx config test failed. Please check $NGINX_CONF_FILE manually"
    fi
fi

# ================================================================
# Phase 7: Start Application + Verify
# ================================================================

info "Phase 7/7: Starting application..."

# Start via Supervisor
if [ "$SKIP_SUPERVISOR" = false ]; then
    supervisorctl start nexus >/dev/null 2>&1 || supervisorctl restart nexus >/dev/null 2>&1 || true
fi

# Wait for health check
HEALTH_OK=false
for i in $(seq 1 15); do
    if curl -sf "http://127.0.0.1:$PORT/health" >/dev/null 2>&1; then
        HEALTH_OK=true
        break
    fi
    sleep 2
done

# ── Print Results ──
echo ""
echo "=========================================="

if [ "$HEALTH_OK" = true ]; then
    echo -e "  ${GREEN}Nexus installed successfully!${NC}"
else
    echo -e "  ${YELLOW}Nexus process started but health check pending.${NC}"
    echo -e "  ${YELLOW}It may need a few more seconds to start up.${NC}"
fi

echo "=========================================="
echo ""
echo "  Deploy:      $DEPLOY_DIR"
echo "  Domain:      $DOMAIN"
echo "  Port:        $PORT"
echo "  Workers:     ${WORKERS:-N/A}"
echo "  BT Panel:    $BT_MODE"
echo ""

if [ "$HEALTH_OK" = true ]; then
    echo -e "  ${GREEN}Next step:${NC} Open your browser and complete the web install wizard:"
    echo ""
    echo "    http://$DOMAIN/app/install.html"
    echo ""
    echo "  The wizard will guide you through:"
    echo "    Step 1: Welcome & prerequisites"
    echo "    Step 2: Environment check"
    echo "    Step 3: MySQL + Redis configuration"
    echo "    Step 4: Admin account + brand"
    echo "    Step 5: Complete"
else
    echo "  Troubleshooting:"
    echo "    supervisorctl status nexus"
    echo "    tail -f $LOG_DIR/nexus_error.log"
    echo "    curl http://127.0.0.1:$PORT/health"
fi

echo ""
echo "  Post-install:"
echo "    1. Configure SSL (HTTPS)"
if [ "$BT_MODE" = true ]; then
    echo "       BT Panel -> Website -> $DOMAIN -> SSL"
else
    echo "       certbot --nginx -d $DOMAIN"
fi
echo "    2. Set up health monitor crontab:"
echo "       * * * * * $DEPLOY_DIR/deploy/health_monitor.sh"
echo "    3. Set up database backup crontab:"
echo "       0 3 * * * $DEPLOY_DIR/deploy/db_backup.sh"
echo ""
echo "  Management:"
echo "    supervisorctl status nexus"
echo "    supervisorctl restart nexus"
echo "    supervisorctl stop nexus"
echo ""
