#!/bin/bash

################################################################################
# VPanel - Installation Script
# Automated deployment of OpenLiteSpeed + VPanel on production servers
# Supports: Ubuntu 20.04+, Debian 10+, CentOS 7+
################################################################################

# Parse command line arguments
AUTO_YES=false

for arg in "$@"; do
    case $arg in
        --yes|-y)
            AUTO_YES=true
            shift
            ;;
        --help|-h)
            echo "Usage: $0 [OPTIONS]"
            echo "Options:"            echo "  --yes, -y    Auto-answer yes to all prompts"
            echo "  --help       Show this help message"
            exit 0
            ;;
    esac
done

set -Eeuo pipefail

# ============================================================================
# ENVIRONMENT VARIABLES
# ============================================================================
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
export NEEDRESTART_SUSPEND=1

# ============================================================================
# CONFIGURATION
# ============================================================================

PANEL_DIR="/opt/vpanel"
LOG_DIR="/var/log/vpanel"
LOG_FILE="${LOG_DIR}/install.log"
CREDENTIALS_FILE="/root/.vpanel_credentials"

# OpenLiteSpeed Configuration
OLS_ADMIN_PORT=7080
OLS_ADMIN_USER="admin"
OLS_VERSION="latest"
OLS1CLK_SCRIPT="https://vpanel.vn/ols1clk.sh"

# vPanel setup
VPANEL_SCRIPT="https://vpanel.vn/install.zip"

# PHP Configuration - use latest stable versions
PHP_VERSION="8.4"  # PHP 8.4 as default (must include decimal for ols1clk)
PHP_EXTRA_VERSIONS="8.1 8.2 8.3 8.5"  # Additional PHP versions to install

# Database Configuration
MARIADB_VERSION="11.4"  # Use LTS version

# Security Configuration
ENABLE_FAIL2BAN=true
ENABLE_OWASP=true

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color

# Deployment state
DEPLOYED_SERVICES=()
FAILED_SERVICES=()
ERROR_OCCURRED=false

# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

log() {
    local level=$1
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    # Create log directory if not exists
    if [ ! -d "${LOG_DIR}" ]; then
        mkdir -p "${LOG_DIR}" 2>/dev/null || true
    fi

    # Write to log file (with error suppression for early calls)
    echo "[${timestamp}] [${level}] ${message}" >> "${LOG_FILE}" 2>/dev/null || true

    case "${level}" in
        INFO)
            echo -e "${BLUE}[INFO]${NC} ${message}"
            ;;
        SUCCESS)
            echo -e "${GREEN}[✓]${NC} ${message}"
            ;;
        WARNING)
            echo -e "${YELLOW}[!]${NC} ${message}"
            ;;
        ERROR)
            echo -e "${RED}[✗]${NC} ${message}"
            ERROR_OCCURRED=true
            ;;
    esac
}

show_spinner() {
    local pid=$1
    local message="${2:-Dang xu ly}"
    local spin_chars='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
    local delay=0.1

    # Hide cursor
    tput civis 2>/dev/null || true

    while kill -0 $pid 2>/dev/null; do
        for i in $(seq 0 9); do
            local char=${spin_chars:$i:1}
            printf "\r${BLUE}${char}${NC} ${message}..."
            sleep $delay
            if ! kill -0 $pid 2>/dev/null; then
                break
            fi
        done
    done

    # Clear spinner line
    printf "\r\033[K"

    # Show cursor
    tput cnorm 2>/dev/null || true
}

get_server_ip() {
    local ip=""

    # Method 1: curl external service (Internet)
    ip=$(curl -s --max-time 5 ifconfig.me 2>/dev/null || curl -s --max-time 5 icanhazip.com 2>/dev/null || wget -qO- --timeout=5 icanhazip.com 2>/dev/null || true)

    # Method 2: hostname -I (Linux fallback)
    if [ -z "$ip" ] || [ "$ip" = "127.0.0.1" ]; then
        ip=$(hostname -I 2>/dev/null | awk '{print $1}' || true)
    fi

    # Method 3: ip route command
    if [ -z "$ip" ] || [ "$ip" = "127.0.0.1" ]; then
        ip=$(ip route get 1.1.1.1 2>/dev/null | grep -oP 'src \K[^ ]+' || true)
    fi

    # Method 4: ifconfig
    if [ -z "$ip" ] || [ "$ip" = "127.0.0.1" ]; then
        ip=$(ifconfig 2>/dev/null | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | head -1 | sed 's/addr://' || true)
    fi

    # Default fallback
    if [ -z "$ip" ]; then
        ip="Unable to detect IP"
    fi

    echo "$ip"
}

detect_ssh_port() {
    local ssh_port=""

    # Prefer the current SSH session port to avoid locking out active admin access.
    if [ -n "${SSH_CONNECTION:-}" ]; then
        ssh_port=$(echo "${SSH_CONNECTION}" | awk '{print $4}')
    fi

    # Fallback to effective sshd config if available.
    if [ -z "${ssh_port}" ] && command -v sshd >/dev/null 2>&1; then
        ssh_port=$(sshd -T 2>/dev/null | awk '/^port / {print $2; exit}')
    fi

    # Last fallback to explicit Port value in sshd_config.
    if [ -z "${ssh_port}" ] && [ -f /etc/ssh/sshd_config ]; then
        ssh_port=$(grep -E '^[[:space:]]*Port[[:space:]]+[0-9]+' /etc/ssh/sshd_config | awk '{print $2}' | tail -1)
    fi

    if ! [[ "${ssh_port}" =~ ^[0-9]+$ ]]; then
        ssh_port="22"
    fi

    echo "${ssh_port}"
}

get_codename() {
    local codename=""

    # Method 1: lsb_release
    if command -v lsb_release &>/dev/null; then
        codename=$(lsb_release -cs 2>/dev/null || true)
    fi

    # Method 2: /etc/os-release
    if [ -z "$codename" ] && [ -f /etc/os-release ]; then
        . /etc/os-release
        codename="${VERSION_CODENAME:-${UBUNTU_CODENAME}}"
    fi

    # Method 3: /etc/lsb-release
    if [ -z "$codename" ] && [ -f /etc/lsb-release ]; then
        . /etc/lsb-release
        codename="${DISTRIB_CODENAME}"
    fi

    # Fallback to VERSION_ID if still empty
    if [ -z "$codename" ]; then
        case "${VERSION_ID}" in
            20.04) codename="focal" ;;
            22.04) codename="jammy" ;;
            24.04) codename="noble" ;;
            *) codename="unknown" ;;
        esac
    fi

    echo "$codename"
}

detect_os() {
    export OS_NAME="unknown"
    export OS_VERSION="unknown"
    export OS_PRETTY_NAME="Unknown OS"
    export OS_FAMILY="unknown"
    export PKG_MANAGER="unknown"

    if [ -f /etc/os-release ]; then
        . /etc/os-release
        OS_NAME="${ID}"
        OS_VERSION="${VERSION_ID}"
        OS_PRETTY_NAME="${PRETTY_NAME}"
    elif [ -f /etc/redhat-release ]; then
        OS_NAME="redhat"
        OS_VERSION=$(cat /etc/redhat-release | grep -oE '[0-9]+\.[0-9]+' || echo "unknown")
        OS_PRETTY_NAME=$(cat /etc/redhat-release)
    else
        log ERROR "Khong the phat hien HDH - khong tim thay /etc/os-release"
        exit 1
    fi

    case "${OS_NAME}" in
        ubuntu)
            OS_FAMILY="debian"
            PKG_MANAGER="apt"
            local major_version=$(echo "$OS_VERSION" | cut -d. -f1)
            if [[ ! "$major_version" =~ ^(20|22|24)$ ]]; then
                log ERROR "HDH khong duoc ho tro: Ubuntu $OS_VERSION. Chi ho tro Ubuntu 20.04, 22.04, 24.04."
                exit 1
            fi
            ;;
        debian)
            OS_FAMILY="debian"
            PKG_MANAGER="apt"
            local major_version=$(echo "$OS_VERSION" | cut -d. -f1)
            if [[ ! "$major_version" =~ ^(11|12|13)$ ]]; then
                log ERROR "HDH khong duoc ho tro: Debian $OS_VERSION. Chi ho tro Debian 11, 12, 13."
                exit 1
            fi
            ;;
        centos|rhel|almalinux|rocky|fedora|ol)
            OS_FAMILY="rhel"
            local major_version=$(echo "$OS_VERSION" | cut -d. -f1)
            if [[ ! "$major_version" =~ ^(8|9|10)$ ]]; then
                log ERROR "HDH khong duoc ho tro: ${OS_PRETTY_NAME}. Chi ho tro tuong thich CentOS/RHEL 8, 9, 10."
                exit 1
            fi
            if command -v dnf &> /dev/null; then
                PKG_MANAGER="dnf"
            else
                PKG_MANAGER="yum"
            fi
            ;;
        *)
            log ERROR "HDH khong duoc ho tro: ${OS_NAME}"
            exit 1
            ;;
    esac
}

system_update_package_list() {
    case $PKG_MANAGER in
        apt) apt-get update --allow-releaseinfo-change >/dev/null 2>&1 || true ;;
        dnf) dnf makecache -y -q >/dev/null 2>&1 || true ;;
        yum) yum makecache -y -q >/dev/null 2>&1 || true ;;
    esac
}

system_install_package() {
    case $PKG_MANAGER in
        apt) export DEBIAN_FRONTEND=noninteractive; apt-get -o Dpkg::Lock::Timeout=120 -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install -yqq "$@" >/dev/null 2>&1 ;;
        dnf) dnf install -yq "$@" >/dev/null 2>&1 ;;
        yum) yum install -yq "$@" >/dev/null 2>&1 ;;
        *) return 1 ;;
    esac
}

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log ERROR "Kich ban nay phai duoc chay voi quyen root (su dung sudo)"
        exit 1
    fi
}

cleanup_on_error() {
    local exit_code=$?
    if [ ${exit_code} -ne 0 ]; then
        log ERROR "Cai dat that bai tai dong $BASH_LINENO (ma loi: ${exit_code})"
        log WARNING "Dang thu khoi phuc lai..."
        rollback_installation
    fi
}

# Use ERR trap instead of EXIT to avoid rollback on successful completion
trap cleanup_on_error ERR

rollback_installation() {
    log WARNING "Dang khoi phuc lai cai dat..."

    # Stop services
    for service in lsws mysql redis memcached; do
        if systemctl is-active --quiet ${service}; then
            log INFO "Dang dung ${service}..."
            systemctl stop ${service} || true
        fi
    done

    # Remove panel if installed
    if [ -d "${PANEL_DIR}" ]; then
        log INFO "Dang xoa ${PANEL_DIR}..."
        rm -rf "${PANEL_DIR}" || true
    fi

    # Remove symlink
    rm -f /usr/local/bin/vpanel || true

    log WARNING "Khoi phuc hoan tat"
}

run_command() {
    local description="$1"
    shift

    # Run command in background with spinner, redirecting stdin from /dev/null to prevent SIGTTIN hanging
    "$@" >> "${LOG_FILE}" 2>&1 < /dev/null &
    local cmd_pid=$!

    # Show spinner while command is running
    show_spinner $cmd_pid "${description}"

    # Wait for command to complete and get exit code
    local exit_code=0
    wait $cmd_pid || exit_code=$?

    if [ $exit_code -eq 0 ]; then
        log SUCCESS "${description}"
        return 0
    else
        log ERROR "${description} that bai"
        return 1
    fi
}

run_command_warn() {
    local description="$1"
    shift

    # Run command in background with spinner, redirecting stdin from /dev/null to prevent SIGTTIN hanging
    "$@" >> "${LOG_FILE}" 2>&1 < /dev/null &
    local cmd_pid=$!

    # Show spinner while command is running
    show_spinner $cmd_pid "${description}"

    # Wait for command to complete and get exit code
    local exit_code=0
    wait $cmd_pid || exit_code=$?

    if [ $exit_code -eq 0 ]; then
        log SUCCESS "${description}"
        return 0
    else
        log WARNING "${description} that bai"
        FAILED_SERVICES+=("${description}")
        return 1
    fi
}

configure_default_server_site() {
    local vhconf="/usr/local/lsws/conf/vhosts/Example/vhconf.conf"
    local html_dir="/usr/local/lsws/Example/html"

    if [ -f "$vhconf" ]; then
        # Xóa các block context mặc định của OpenLiteSpeed trong default vhconf
        sed -i '/^context \/docs\//,/^}/d' "$vhconf"
        sed -i '/^context \/protected\//,/^}/d' "$vhconf"
        sed -i '/^context \/blocked\//,/^}/d' "$vhconf"
        sed -i '/^context \/cgi-bin\//,/^}/d' "$vhconf"
    fi

    # Dọn dẹp thư mục html mặc định
    if [ -d "$html_dir" ]; then
        rm -rf "${html_dir:?}/"*

        # Bố trí trang index.html từ public/default_html/ sau khi VPanel đã clone
        if [ -d "${PANEL_DIR}/public/default_html" ]; then
            cp -rf "${PANEL_DIR}/public/default_html/"* "${html_dir}/"
        else
            echo "<h1>Server is Running Successfully!</h1>" > "${html_dir}/index.html"
        fi

        chown -R nobody:nogroup "$html_dir" 2>/dev/null || chown -R nobody:nobody "$html_dir" 2>/dev/null
        find "$html_dir" -type f -exec chmod 644 {} \;
        find "$html_dir" -type d -exec chmod 755 {} \;
    fi

    # Restart OLS gracefully to apply context removal configuration
    if systemctl is-active --quiet lsws 2>/dev/null; then
        systemctl reload lsws || /usr/local/lsws/bin/lswsctrl restart 2>/dev/null || true
    else
        /usr/local/lsws/bin/lswsctrl restart 2>/dev/null || true
    fi
}

install_ip_ssl_and_force_https() {
    local server_ip=$(get_server_ip)
    # Su dung dinh dang domain cho email de tranh loi invalidContact cua Let's Encrypt
    local formatted_ip=$(echo "$server_ip" | tr '.' '-')
    local email="admin@ip-${formatted_ip}.vpanel.vn"

    # Bo qua cai dat SSL neu dang chay test tren mang local (IP Private)
    if [[ "$server_ip" =~ ^10\..* ]] || [[ "$server_ip" =~ ^172\.(1[6-9]|2[0-9]|3[0-1])\..* ]] || [[ "$server_ip" =~ ^192\.168\..* ]] || [[ "$server_ip" =~ ^127\..* ]] || [[ "$server_ip" == "" || "$server_ip" == "localhost" ]]; then
        log INFO "Bo qua cai dat SSL va ep HTTPS vi dang chay tren server local (IP: ${server_ip})"
        return 0
    fi

    # 1. Cai dat acme.sh neu chua co
    if [ ! -f /root/.acme.sh/acme.sh ]; then
        curl -s https://get.acme.sh | sh -s email="${email}" >> "${LOG_FILE}" 2>&1
    fi
    /root/.acme.sh/acme.sh --upgrade >> "${LOG_FILE}" 2>&1

    # Dang ky / Cap nhat lai tai khoan Let's Encrypt voi dung email de tranh loi invalidContact do IP cu
    # Xoa cache account cu cua Let's Encrypt de buoc tao lai
    rm -rf /root/.acme.sh/ca/acme-v02.api.letsencrypt.org/directory/account.* 2>/dev/null || true

    if grep -q "ACCOUNT_EMAIL" /root/.acme.sh/account.conf 2>/dev/null; then
        sed -i "s/ACCOUNT_EMAIL=.*/ACCOUNT_EMAIL='${email}'/g" /root/.acme.sh/account.conf
    fi
    /root/.acme.sh/acme.sh --register-account -m "${email}" --server letsencrypt >> "${LOG_FILE}" 2>&1 || true

    # 2. Cap chung chi Let's Encrypt cho IP (shortlived)
    local acme_dir="/usr/local/lsws/Example/html/.well-known/acme-challenge"
    mkdir -p "${acme_dir}" 2>/dev/null || true
    chmod -R 755 "/usr/local/lsws/Example/html/.well-known" 2>/dev/null || true

    if /root/.acme.sh/acme.sh --issue -d "${server_ip}" --webroot /usr/local/lsws/Example/html --server letsencrypt --cert-profile shortlived --days 3 --force >> "${LOG_FILE}" 2>&1; then
        local privkey_path="/etc/letsencrypt/live/${server_ip}/privkey.pem"
        local fullchain_path="/etc/letsencrypt/live/${server_ip}/fullchain.pem"
        mkdir -p "/etc/letsencrypt/live/${server_ip}/"

        local reloadcmd="cp -f ${privkey_path} /usr/local/lsws/conf/example.key; cp -f ${fullchain_path} /usr/local/lsws/conf/example.crt; cp -f ${privkey_path} /usr/local/lsws/admin/conf/webadmin.key; cp -f ${fullchain_path} /usr/local/lsws/admin/conf/webadmin.crt; chown lsadm:lsadm /usr/local/lsws/conf/example.key /usr/local/lsws/conf/example.crt /usr/local/lsws/admin/conf/webadmin.key /usr/local/lsws/admin/conf/webadmin.crt; if systemctl is-active --quiet lsws 2>/dev/null; then systemctl restart lsws; else /usr/local/lsws/bin/lswsctrl restart; fi"

        /root/.acme.sh/acme.sh --install-cert -d "${server_ip}" \
            --key-file "${privkey_path}" \
            --fullchain-file "${fullchain_path}" \
            --reloadcmd "${reloadcmd}" >> "${LOG_FILE}" 2>&1

        eval "${reloadcmd}" >> "${LOG_FILE}" 2>&1
        log SUCCESS "Da cap SSL Let's Encrypt cho IP Server thanh cong"
    else
        log WARNING "Cap chung chi SSL cho IP that bai. Vui long kiem tra bang cach cai thu cong tu panel"
    fi

    # 3. Ep tat ca ung dung su dung qua IP phai dung HTTPS bang cach config rewrite rules trong Example vhost
    local vhconf="/usr/local/lsws/conf/vhosts/Example/vhconf.conf"
    if [ -f "${vhconf}" ]; then
        # Xoa block rewrite hien co neu co
        sed -i '/^rewrite  *{/,/^}/d' "${vhconf}"
        cat >> "${vhconf}" << 'EOF'

rewrite  {
  enable                  1
  autoLoadHtaccess        1
  rules                   <<<END_rules
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
  END_rules
}
EOF
        log SUCCESS "Da cau hinh ep buoc HTTPS cho IP Server"
    fi
}

# ============================================================================
# PHASE 1: PRE-INSTALLATION CHECKS
# ============================================================================

phase_1_pre_checks() {
    detect_os
    log SUCCESS "HDH: ${OS_NAME} ${OS_VERSION} (${OS_FAMILY})"
    check_root
    local total_ram=$(free -m | awk 'NR==2 {print int(($2+1023)/1024)}')
    local available_disk=$(df / | awk 'NR==2 {print $4}')
    local available_disk_gb=$((available_disk / 1048576))
    log INFO "RAM: ${total_ram}GB, Dung luong kha dung: ${available_disk_gb}GB"

    if [ "${total_ram}" -lt 2 ]; then
        log WARNING "He thong co it hon 2GB RAM (hien tai: ${total_ram}GB)"
    fi

    if [ "${available_disk}" -lt 5242880 ]; then
        log ERROR "Khong du dung luong o dia (can 5GB, hien co ${available_disk_gb}GB)"
        exit 1
    fi
    local existing_servers=()

    if systemctl is-active --quiet apache2 2>/dev/null; then
        existing_servers+=("Apache2")
    fi

    if systemctl is-active --quiet nginx 2>/dev/null; then
        existing_servers+=("Nginx")
    fi

    if [ ${#existing_servers[@]} -gt 0 ]; then
        log WARNING "Phat hien web server dang chay: ${existing_servers[*]}"
        log INFO "Can phai cai dat server sach se"
        log ERROR "Da huy cai dat"
        exit 1
    fi

    # Install base dependencies to ensure ols1clk components like modsecurity don't fail
    # run_command "Dang cap nhat danh sach kho luu tru he thong" \
    #     system_update_package_list || log WARNING "Cap nhat kho luu tru co the co loi, tiep tuc phan con lai..."

    # if [ "${OS_FAMILY}" = "rhel" ]; then
    #     run_command "Dang cai dat kho EPEL" \
    #         system_install_package epel-release
    # fi

    run_command "Dang cai dat cac goi phu thuoc he thong" \
        system_install_package curl wget unzip git jq certbot
}

# ============================================================================
# PHASE 2: INSTALL OPENLITESPEED + PHP + MARIADB (using official ols1clk)
# ============================================================================

phase_2_install_ols() {
    local ols1clk_tmp="/tmp/ols1clk.sh"

    if ! run_command "Tien hanh cai dat OpenLiteSpeed" bash -c "curl -fsSL --retry 3 --retry-delay 5 ${OLS1CLK_SCRIPT} -o ${ols1clk_tmp} && chmod +x ${ols1clk_tmp}"; then
        log ERROR "Khong the cai dat OpenLiteSpeed tu ${OLS1CLK_SCRIPT}"
        return 1
    fi

    if [ ! -s "${ols1clk_tmp}" ]; then
        log ERROR "Tep cai dat OpenLiteSpeed rong (loi mang)."
        return 1
    fi

    # Hotfix for Litespeed's outdated mariadb_repo_setup argument
    sed -i 's/mariadb-\$MARIADBVER/\$MARIADBVER/g' "${ols1clk_tmp}" 2>/dev/null || true

    # Prepare MariaDB Root Password for ols1clk
    local db_root_pass=""
    if [ -f "${CREDENTIALS_FILE}.mysql_root_pass" ]; then
        db_root_pass=$(cat "${CREDENTIALS_FILE}.mysql_root_pass" 2>/dev/null || true)
    fi
    if [ -z "${db_root_pass}" ]; then
        db_root_pass=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16)
        echo "${db_root_pass}" > "${CREDENTIALS_FILE}.mysql_root_pass"
        chmod 600 "${CREDENTIALS_FILE}.mysql_root_pass"
    fi

    local admin_email="admin@${HOSTNAME:-localhost}"
    log INFO "Dang cai dat: OpenLiteSpeed + PHP ${PHP_VERSION} + MariaDB ${MARIADB_VERSION}"

    # Build ols1clk command with all options
    local ols1clk_cmd="${ols1clk_tmp}"
    ols1clk_cmd+=" --quiet"                                      # Non-interactive mode
    ols1clk_cmd+=" --lsphp ${PHP_VERSION//./}"                       # Primary PHP version
    ols1clk_cmd+=" --pure-mariadb"                               # Install MariaDB only
    ols1clk_cmd+=" --mariadbver ${MARIADB_VERSION}"              # MariaDB version
    ols1clk_cmd+=" --dbrootpassword ${db_root_pass}"             # DB root password
    ols1clk_cmd+=" --adminuser ${OLS_ADMIN_USER}"                # Admin username
    ols1clk_cmd+=" --adminport ${OLS_ADMIN_PORT}"                # Admin port
    ols1clk_cmd+=" --email ${admin_email}"                       # Admin email

    # Security features
    if [ "${ENABLE_FAIL2BAN}" = true ]; then
        ols1clk_cmd+=" --fail2ban-enable"                        # Enable fail2ban
    fi

    if [ "${ENABLE_OWASP}" = true ]; then
        ols1clk_cmd+=" --owasp-enable"                           # Enable ModSecurity OWASP
    fi

    # Run the installation (auto-approve confirmation prompt) with loading spinner
    echo -e "${BLUE}[⏳]${NC} Dang cai dat OpenLiteSpeed + PHP + MariaDB (co the mat 5-10 phut)..."

    local max_retries=3
    local retry_count=0
    local ols_exit=1

    while [ $retry_count -lt $max_retries ]; do
        if [ $retry_count -gt 0 ]; then
            log WARNING "Thu lai lan $((retry_count+1))/${max_retries}..."
            sleep 10
        fi

        # Run command in background
        echo "" | bash -c "${ols1clk_cmd}" >> "${LOG_FILE}" 2>&1 &
        local ols_pid=$!

        # Show spinner with custom message
        show_spinner $ols_pid "Dang cai dat OpenLiteSpeed + PHP ${PHP_VERSION} + MariaDB ${MARIADB_VERSION}"

        # Wait for command to complete and check exit code
        ols_exit=0
        wait $ols_pid || ols_exit=$?

        if [ $ols_exit -eq 0 ]; then
            log SUCCESS "Cai dat OpenLiteSpeed va MariaDB thanh cong"
            DEPLOYED_SERVICES+=("lsws" "mysql")
            break
        else
            log ERROR "Cai dat OpenLiteSpeed that bai (Ma loi: $ols_exit)"
            retry_count=$((retry_count + 1))
        fi
    done

    if [ $ols_exit -ne 0 ]; then
        log ERROR "Cai dat OpenLiteSpeed that bai phuc hoi sau ${max_retries} lan thu - kiem tra ${LOG_FILE} de biet chi tiet"
        return 1
    fi

    # Read credentials from /usr/local/lsws/password file created by ols1clk
    local ols_password_file="/usr/local/lsws/password"
    local admin_pass=""

    if [ -f "${ols_password_file}" ]; then
        # Parse OLS admin password: WebAdmin username is [admin], password is [******].
        admin_pass=$(grep -oP 'WebAdmin username is \[\K[^\]]+' "${ols_password_file}" | head -1 || true)
        if [ -n "${admin_pass}" ]; then
            # Get the password after the username
            admin_pass=$(grep 'WebAdmin' "${ols_password_file}" | sed -n 's/.*password is \[\([^]]*\)\].*/\1/p' || true)
        fi

        # Save extracted credentials to credential files
        if [ -n "${admin_pass}" ]; then
            run_command "Luu thong tin xac thuc admin OLS" \
                bash -c "echo '${admin_pass}' > ${CREDENTIALS_FILE}.ols_admin_pass && chmod 600 ${CREDENTIALS_FILE}.ols_admin_pass"
        else
            log ERROR "Khong the trich xuat mat khau admin OLS tu ${ols_password_file}"
        fi
    else
        log ERROR "Khong tim thay file mat khau tai ${ols_password_file}"
        log INFO "Cai dat ols1clk co the chua hoan tat thanh cong"
        return 1
    fi

    # Check OpenLiteSpeed
    if systemctl is-active --quiet lsws; then
        log SUCCESS "OpenLiteSpeed dang chay"
    else
        log WARNING "OpenLiteSpeed khong chay, dang thu khoi dong..."
        systemctl start lsws || log ERROR "Khoi dong OpenLiteSpeed that bai"
    fi

    # Check MariaDB will be done in phase 4

    # Check fail2ban if enabled
    if [ "${ENABLE_FAIL2BAN}" = true ]; then
        if systemctl is-active --quiet fail2ban; then
            log SUCCESS "fail2ban dang chay"
            DEPLOYED_SERVICES+=("fail2ban")
        else
            log WARNING "fail2ban khong chay"
        fi
    fi
    local ssh_port
    ssh_port=$(detect_ssh_port)
    log INFO "Tu dong phat hien cong SSH: ${ssh_port}"

    run_command "Dang cai dat Firewall (CSF)" \
        bash -c 'if ! command -v csf &> /dev/null; then \
                    if command -v apt-get &> /dev/null; then apt-get -o Dpkg::Lock::Timeout=120 -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install -y perl libwww-perl >/dev/null 2>&1; \
                    elif command -v yum &> /dev/null; then yum install -y perl-libwww-perl wget tar >/dev/null 2>&1; fi; \
                    cd /usr/src && rm -fv csf.tgz && \
                    wget -q https://github.com/Aetherinox/csf-firewall/releases/download/15.10/csf-firewall-v15.10.tgz -O csf.tgz && \
                    tar -xzf csf.tgz && cd csf && sh install.sh >/dev/null 2>&1; \
                 fi' || log WARNING "Khong the cai dat CSF"

    if command -v csf &> /dev/null; then
        run_command "Dang cau hinh CSF Firewall" \
            bash -c "sed -i 's/TESTING = \"1\"/TESTING = \"0\"/' /etc/csf/csf.conf 2>/dev/null; \
                     sed -i 's/^TCP_IN = \".*\"/TCP_IN = \"20,21,22,25,53,80,110,143,443,465,587,993,995,3306,${ssh_port},${OLS_ADMIN_PORT}\"/' /etc/csf/csf.conf 2>/dev/null; \
                     systemctl restart rsyslog 2>/dev/null || true; \
                     csf -e > /dev/null 2>&1 || true; \
                     csf -r > /dev/null 2>&1 || true; \
                     systemctl enable csf lfd 2>/dev/null || true; \
                     systemctl start csf lfd 2>/dev/null || true" || log WARNING "Loi cau hinh CSF"
    fi

    # Create webroot for Domain Isolation
    run_command "Tao thu muc webroot" \
        bash -c "mkdir -p /www && chmod 755 /www"

    # Clean up
    rm -f "${ols1clk_tmp}"

    log SUCCESS "Cai dat OpenLiteSpeed + PHP + MariaDB hoan tat"
    log INFO "Trang quan tri: https://$(get_server_ip):${OLS_ADMIN_PORT}"
    log INFO "Tai khoan quan tri: ${OLS_ADMIN_USER}"
}

# ============================================================================
# PHASE 3: INSTALL ADDITIONAL PHP VERSIONS
# ============================================================================

phase_3_install_php() {

    # 1. Đảm bảo phiên bản PHP chính phải tồn tại thực sự (ols1clk hay báo ảo nếu upgrade)
    local primary_pkg="lsphp${PHP_VERSION//./}"
    if [ ! -x "/usr/local/lsws/${primary_pkg}/bin/php" ]; then
        log WARNING "Phat hien thieu PHP chinh, dang cuong che cai dat ${primary_pkg}..."
        bash -c "wget -qO - https://repo.litespeed.sh | bash" >/dev/null 2>&1
        system_install_package "${primary_pkg}" "${primary_pkg}-common" || true
    fi

    local install_extra_php="n"
    if [ -n "${PHP_EXTRA_VERSIONS}" ]; then
        echo ""
        log INFO "Phien ban PHP chinh: ${PHP_VERSION} (ban mac dinh)"
        echo "Cac phien ban co san de mo rong: ${PHP_EXTRA_VERSIONS}"

        if [ "${AUTO_YES}" = true ]; then
            install_extra_php="y"
        else
            read -t 10 -e -p "Cai dat them cac phien ban PHP khac? (y/N - Enter de bo qua): " -r install_extra_php || { echo ""; install_extra_php="n"; }
        fi
    fi

    if [[ "${install_extra_php}" =~ ^[Yy]$ ]]; then
        # Chay script khai bao tệp repo chinh thuc cua LiteSpeed cho cac phan mem EOL
        run_command "Dang nap danh muc kho luu tru LiteSpeed" \
            bash -c "wget -qO - https://repo.litespeed.sh | bash" || log WARNING "Nap kho luu tru that bai"

        log INFO "Dang cai dat cac phien ban bo sung: ${PHP_EXTRA_VERSIONS}"
    for php_ver in ${PHP_EXTRA_VERSIONS}; do
        # Convert version to short format (8.1 -> 81)
        local php_ver_short="${php_ver//./}"
        local php_pkg="lsphp${php_ver_short}"

        # Check if already installed
        if [ -d "/usr/local/lsws/${php_pkg}/bin" ]; then
            log INFO "${php_pkg} da duoc cai dat, bo qua"
            continue
        fi

        log INFO "Dang cai dat ${php_pkg} voi cac tien ich mo rong..."

        if [ "${OS_FAMILY}" = "debian" ]; then
            # Try to install lsphp package with extensions
            # Use apt-cache to check if package exists first
            if apt-cache search "^${php_pkg}$" | grep -q "${php_pkg}"; then
                run_command "Cai dat loi ${php_pkg}" \
                    system_install_package "${php_pkg}" "${php_pkg}-common" || log WARNING "Cai dat ${php_pkg} that bai"

                # Try to install extensions individually
                local extensions=("mysql" "gd" "curl" "zip" "xml" "mbstring" "opcache" "imagick" "intl" "soap" "bcmath" "redis" "memcached" "pgsql" "sqlite3" "mongodb" "sqlsrv" "pdo_sqlsrv" "oci8")
                (
                    for ext in "${extensions[@]}"; do
                        system_install_package "${php_pkg}-${ext}" >/dev/null 2>&1 || true
                    done
                ) >> "${LOG_FILE}" 2>&1 &
                local ext_pid=$!
                show_spinner "$ext_pid" "Cai dat extensions cho ${php_pkg}"
                wait "$ext_pid" || true
            else
                log WARNING "Khong tim thay ${php_pkg} trong kho luu tru - bo qua"
                continue
            fi
        else
            # For CentOS/RHEL/AlmaLinux/Rocky
            if $PKG_MANAGER search "${php_pkg}" 2>/dev/null | grep -q "${php_pkg}"; then
                run_command "Cai dat loi ${php_pkg}" \
                    system_install_package "${php_pkg}" "${php_pkg}-common" || log WARNING "Cai dat ${php_pkg} that bai"

                # Try to install extensions individually
                local extensions=("mysql" "gd" "curl" "zip" "xml" "mbstring" "opcache" "intl" "soap" "bcmath" "pgsql" "sqlite3" "mongodb" "sqlsrv" "pdo_sqlsrv" "oci8")
                (
                    for ext in "${extensions[@]}"; do
                        system_install_package "${php_pkg}-${ext}" >/dev/null 2>&1 || true
                    done
                ) >> "${LOG_FILE}" 2>&1 &
                local ext_pid=$!
                show_spinner "$ext_pid" "Cai dat extensions cho ${php_pkg}"
                wait "$ext_pid" || true
            else
                log WARNING "Khong tim thay ${php_pkg} trong kho luu tru - bo qua"
                continue
            fi
        fi

        # Install ionCube Loader (optional, best-effort)
        if ! command -v ioncube_loader_lin &> /dev/null; then
            log INFO "Dang cai dat ionCube Loader cho ${php_pkg}..."
            bash -c "cd /tmp && wget -q https://www.ioncube.com/downloads/ioncube_loaders_lin_x86-64.tar.gz 2>/dev/null && tar xfz ioncube_loaders_lin_x86-64.tar.gz 2>/dev/null && cp ioncube/ioncube_loader_lin_${php_ver}.so /usr/local/lsws/${php_pkg}/lib/php/extensions/no-debug-non-zts-*/ 2>/dev/null" || log WARNING "Da bo qua cai dat ionCube Loader"
        fi
    done
    else
        log INFO "Da bo qua cai dat phien ban PHP bo sung"
    fi
    for php_ver in ${PHP_VERSION} ${PHP_EXTRA_VERSIONS}; do
        # Convert version to short format (8.3 -> 83, 8.1 -> 81)
        local php_ver_short="${php_ver//./}"
        local php_ini="/usr/local/lsws/lsphp${php_ver_short}/etc/php/${php_ver}/litespeed/php.ini"

        # Try multiple possible paths
        if [ ! -f "${php_ini}" ]; then
            php_ini="/usr/local/lsws/lsphp${php_ver_short}/etc/php.ini"
        fi

        if [ ! -f "${php_ini}" ]; then
            php_ini="/usr/local/lsws/lsphp${php_ver_short}/lib/php.ini"
        fi

        if [ ! -f "${php_ini}" ]; then
            # Try looking in conf.d
            php_ini=$(find "/usr/local/lsws/lsphp${php_ver_short}" -name "php.ini" -print -quit 2>/dev/null || true)
        fi

        if [ -f "${php_ini}" ]; then
            run_command "Toi uu hoa cau hinh lsphp${php_ver}" \
                bash -c "sed -i 's/^upload_max_filesize.*/upload_max_filesize = 256M/' '${php_ini}' && \
                        sed -i 's/^post_max_size.*/post_max_size = 256M/' '${php_ini}' && \
                        sed -i 's/^memory_limit.*/memory_limit = 512M/' '${php_ini}' && \
                        sed -i 's/^max_execution_time.*/max_execution_time = 300/' '${php_ini}'" || log WARNING "Cap nhat ${php_ini} that bai"
        fi
    done
    # Convert PHP_VERSION from 8.3 to 83 for directory naming
    local php_version_short="${PHP_VERSION//./}"
    local default_php="/usr/local/lsws/lsphp${php_version_short}/bin/php"

    if [ ! -f "${default_php}" ]; then
        default_php="/usr/local/lsws/lsphp${php_version_short}/bin/lsphp"
    fi

    if [ -f "${default_php}" ]; then
        run_command "Tao symlink cho PHP CLI mac dinh" \
            bash -c "ln -sf '${default_php}' /usr/local/bin/php"

        # Verify
        local php_cli_version=$(/usr/local/bin/php -v | head -n 1 2>/dev/null || echo "unknown")
        log SUCCESS "PHP CLI mac dinh: ${php_cli_version}"
    else
        log WARNING "Khong tim thay ban thuc thi PHP CLI/LSAPI mac dinh tai ${default_php}"
    fi
    for php_ver in ${PHP_VERSION} ${PHP_EXTRA_VERSIONS}; do
        # Convert version to short format (8.3 -> 83, 8.1 -> 81)
        local php_ver_short="${php_ver//./}"
        if [ -d "/usr/local/lsws/lsphp${php_ver_short}" ]; then
            local php_bin="/usr/local/lsws/lsphp${php_ver_short}/bin/php"
            if [ -f "${php_bin}" ]; then
                local version=$("${php_bin}" -r 'echo PHP_VERSION;' 2>/dev/null || echo "unknown")
                log SUCCESS "✓ PHP ${php_ver}: ${version}"
            fi
        fi
    done


    log SUCCESS "Da cai dat xong cac phien ban PHP bo sung"
}

# ============================================================================
# PHASE 4: VERIFY DATABASE INSTALLATION
# ============================================================================

phase_4_install_databases() {

    # 1. Provide root password from credentials
    local mysql_root_pass=""
    if [ -f "${CREDENTIALS_FILE}.mysql_root_pass" ]; then
        mysql_root_pass=$(cat "${CREDENTIALS_FILE}.mysql_root_pass" 2>/dev/null || true)
    fi

    if [ -z "${mysql_root_pass}" ]; then
        log ERROR "Khong tim thay mat khau root MySQL trong ${CREDENTIALS_FILE}.mysql_root_pass"
        return 1
    fi

    # 2. Check if DB already installed and running
    if systemctl is-active --quiet mysql || systemctl is-active --quiet mariadb; then
        log SUCCESS "Dich vu MariaDB da duoc cai dat va dang chay"
    else
        log WARNING "Dich vu MariaDB khong chay, dang thu khoi dong..."
        systemctl start mysql 2>/dev/null || systemctl start mariadb || {
            log ERROR "Khoi dong MariaDB that bai"
            return 1
        }
    fi

    # Verify we can connect with root password
    if mysql -u root -p"${mysql_root_pass}" -e "SELECT VERSION();" >> "${LOG_FILE}" 2>&1; then
        local db_version=$(mysql -u root -p"${mysql_root_pass}" -e "SELECT VERSION();" 2>/dev/null | tail -n 1)
        log SUCCESS "Ket noi MariaDB thanh cong (Phien ban: ${db_version})"
    else
        log ERROR "Ket noi MariaDB voi thong tin xac thuc root that bai. Xin doi mat khau thu cong."
        return 1
    fi

    local my_cnf="/etc/mysql/mariadb.conf.d/99-vpanel.cnf"
    if [ ! -d "/etc/mysql/mariadb.conf.d" ]; then
        mkdir -p "/etc/mysql/mariadb.conf.d" 2>/dev/null || true
        # RHEL fallback
        my_cnf="/etc/my.cnf.d/99-vpanel.cnf"
        mkdir -p "/etc/my.cnf.d/" 2>/dev/null || true
    fi

    # Create custom MariaDB config for VPanel
    run_command "Dang tao cau hinh toi uu hoa MariaDB" \
        bash -c "cat > ${my_cnf} << 'EOF'
[mysqld]
# VPanel Optimizations
max_connections = 200
innodb_buffer_pool_size = 256M
innodb_log_file_size = 64M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
query_cache_size = 0
query_cache_type = 0

# Security
local_infile = 0

# Character set
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
EOF" || log WARNING "Tao cau hinh MariaDB that bai"

    # Restart MariaDB to apply changes
    run_command "Dang khoi dong lai MariaDB" \
        bash -c "systemctl restart mysql 2>/dev/null || systemctl restart mariadb" || true

    log SUCCESS "Da toi uu hoa MariaDB"
}

# ============================================================================
# PHASE 5: INSTALL ADDITIONAL SERVICES
# ============================================================================

phase_5_install_services() {

    # ============================================================================
    # OPTIONAL SERVICES (user confirmation)
    # ============================================================================
    local redis_install="n"
    if [ "${AUTO_YES}" = true ]; then
        redis_install="y"
    else
        echo ""
        read -t 10 -e -p "Cai dat may chu Redis? (y/N - Enter de bo qua): " -r redis_install || { echo ""; redis_install="n"; }
    fi
    if [[ "${redis_install}" =~ ^[Yy]$ ]]; then
        local redis_pkg="redis"
        if [ "${OS_FAMILY}" = "debian" ]; then
            redis_pkg="redis-server"
        fi
        run_command_warn "Dang cai dat Redis" \
            system_install_package "${redis_pkg}" || true

        # Enable and start Redis if it was installed
        # Debian uses redis-server, CentOS/RHEL uses redis
        local redis_service=""

        # Check which service exists by looking at actual systemd files
        if [ -f /etc/systemd/system/multi-user.target.wants/redis-server.service ] || \
           [ -f /lib/systemd/system/redis-server.service ] || \
           [ -f /usr/lib/systemd/system/redis-server.service ]; then
            redis_service="redis-server"
        elif [ -f /etc/systemd/system/multi-user.target.wants/redis.service ] || \
             [ -f /lib/systemd/system/redis.service ] || \
             [ -f /usr/lib/systemd/system/redis.service ]; then
            redis_service="redis"
        fi

        if [ -z "${redis_service}" ]; then
            log WARNING "Khong tim thay file dich vu Redis - cai dat co the da that bai"
            redis_install="n"
        fi

        if [[ "${redis_install}" =~ ^[Yy]$ ]]; then
            run_command_warn "Dang bat Redis" \
                systemctl enable "${redis_service}" || true
            run_command_warn "Dang khoi dong Redis" \
                systemctl start "${redis_service}" || true
            DEPLOYED_SERVICES+=("redis")
            log SUCCESS "Da bat va khoi dong Redis"
        fi
    else
        log INFO "Da bo qua cai dat Redis"
    fi
    local memcached_install="n"
    if [ "${AUTO_YES}" = true ]; then
        memcached_install="y"
    else
        echo ""
        read -t 10 -e -p "Cai dat Memcached? (y/N - Enter de bo qua): " -r memcached_install || { echo ""; memcached_install="n"; }
    fi
    if [[ "${memcached_install}" =~ ^[Yy]$ ]]; then
        run_command_warn "Dang cai dat Memcached" \
            system_install_package memcached || true

        # Enable and start Memcached if it was installed
        if systemctl list-unit-files | grep -q "^memcached"; then
            run_command_warn "Dang bat Memcached" \
                systemctl enable memcached || true
            run_command_warn "Dang khoi dong Memcached" \
                systemctl start memcached || true
            DEPLOYED_SERVICES+=("memcached")
            log SUCCESS "Da bat va khoi dong Memcached"
        else
            log WARNING "Khong tim thay dich vu Memcached trong systemctl - cai dat co the da that bai"
        fi
    else
        log INFO "Da bo qua cai dat Memcached"
    fi
    local nodejs_install="n"
    if [ "${AUTO_YES}" = true ]; then
        nodejs_install="y"
    else
        echo ""
        read -t 10 -e -p "Cai dat Node.js 22? (y/N - Enter de bo qua): " -r nodejs_install || { echo ""; nodejs_install="n"; }
    fi
    if [[ "${nodejs_install}" =~ ^[Yy]$ ]]; then
        if [ "${OS_FAMILY}" = "debian" ]; then
            run_command_warn "Dang them kho Node.js" \
                bash -c "curl -fsSL https://deb.nodesource.com/setup_22.x | bash -" || true
        else
            run_command_warn "Dang them kho Node.js" \
                bash -c "curl -fsSL https://rpm.nodesource.com/setup_22.x | bash -" || true
        fi
        run_command_warn "Dang cai dat Node.js" \
            system_install_package nodejs || true
        DEPLOYED_SERVICES+=("nodejs")
        log SUCCESS "Da cai dat Node.js"
    else
        log INFO "Da bo qua cai dat Node.js"
    fi
    local phpmyadmin_install="n"
    if [ "${AUTO_YES}" = true ]; then
        phpmyadmin_install="y"
    else
        echo ""
        read -t 10 -e -p "Cai dat phpMyAdmin? (y/N - Enter de bo qua): " -r phpmyadmin_install || { echo ""; phpmyadmin_install="n"; }
    fi
    if [[ "${phpmyadmin_install}" =~ ^[Yy]$ ]]; then
        # Pre-configure phpMyAdmin to avoid interactive prompts
        export DEBIAN_FRONTEND=noninteractive

        local pma_version="5.2.2"
        local pma_dir="/usr/share/phpmyadmin"

        run_command_warn "Dang tai va cai dat phpMyAdmin ${pma_version}" \
            bash -c "
                # Remove old phpmyadmin package if exists
                if command -v apt-get >/dev/null 2>&1; then
                    apt-get -o Dpkg::Lock::Timeout=120 -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" remove -y phpmyadmin >/dev/null 2>&1 || true
                fi

                mkdir -p ${pma_dir}
                rm -rf ${pma_dir}/*
                curl -fsSL https://files.phpmyadmin.net/phpMyAdmin/${pma_version}/phpMyAdmin-${pma_version}-all-languages.tar.gz | tar xzf - -C ${pma_dir} --strip-components=1
            " || true

        # Configure phpMyAdmin
        local pma_config="${pma_dir}/config.inc.php"
        log INFO "Dang cau hinh phpMyAdmin..."
        local local_secret
        local_secret=$(openssl rand -base64 32 2>/dev/null | tr -d '\n' || echo "default_secret_key_12345")
        cat > "${pma_config}" <<EOF
<?php
\$cfg['blowfish_secret'] = '${local_secret}';
\$cfg['Servers'][1]['auth_type'] = 'cookie';
\$cfg['Servers'][1]['host'] = 'localhost';
\$cfg['Servers'][1]['compress'] = false;
\$cfg['Servers'][1]['AllowNoPassword'] = false;
\$cfg['TempDir'] = '/tmp';
\$cfg['LoginCookieValidity'] = 3600;
\$cfg['AllowThirdPartyFraming'] = false;
?>
EOF
        chmod 644 "${pma_config}"

        # Configure TempDir and Permissions
        run_command_warn "Dang thiet lap quyen va thu muc cho phpMyAdmin" \
            bash -c "
                mkdir -p ${pma_dir}/tmp
                chown -R www-data:www-data ${pma_dir} 2>/dev/null || true
                find ${pma_dir} -type d -exec chmod 755 {} \; 2>/dev/null || true
                find ${pma_dir} -type f -exec chmod 644 {} \; 2>/dev/null || true
            " || true

        # Create symlink for WebRoot fallback
        local OLS_DOCROOT="/usr/local/lsws/Example/html"
        if [ ! -L "${OLS_DOCROOT}/phpmyadmin" ]; then
            run_command_warn "Dang tao symlink cho phpMyAdmin" \
                ln -sf ${pma_dir} "${OLS_DOCROOT}/phpmyadmin" || true
        fi

        DEPLOYED_SERVICES+=("phpmyadmin")
        log SUCCESS "Da cai dat va cau hinh phpMyAdmin tu source"

        # Configure Index Files for OpenLiteSpeed
        local vhost_conf="/usr/local/lsws/conf/vhosts/Example/vhconf.conf"

        run_command_warn "Dang cap nhat cau hinh Index Files" \
            bash -c "
# Remove existing index block if it exists
sed -i '/^index {/,/^}/d' '${vhost_conf}'

# Add new properly formatted index block
cat >> '${vhost_conf}' << 'INDEXEOF'

index {
  autoIndexURI /_autoindex/default.php
  indexFiles index.php, index.html
  autoIndex 0
  useServer 1
}
INDEXEOF
" || true

        # Configure Context for phpMyAdmin
        local pma_location="/usr/share/phpmyadmin/"

        run_command_warn "Dang cap nhat cau hinh Context phpMyAdmin" \
            bash -c "
# Remove existing context block if it exists
sed -i '/^context \\/phpmyadmin\\/ {/,/^}/d' '${vhost_conf}'

# Add new properly formatted context block
cat >> '${vhost_conf}' << 'CONTEXTEOF'

context /phpmyadmin/ {
  location                ${pma_location}
  allowBrowse             1
  indexFiles              index.php
  addHandler              php lsphp${PHP_VERSION//./}
  enableScript            1
  allowSymbolLink         1

  accessControl {
    allow                 *
  }
}
CONTEXTEOF
" || true

        # Also ensure scriptHandler is configured in main httpd_config.conf
        run_command_warn "Dang kiem tra scriptHandler PHP" \
            bash -c "
if ! grep -q 'scriptHandler.*lsphp${PHP_VERSION//./}' /usr/local/lsws/conf/httpd_config.conf 2>/dev/null; then
    echo 'WARNING: PHP scriptHandler may need manual configuration in WebAdmin'
else
    echo 'PHP scriptHandler already configured'
fi
" || true

        # Graceful restart instead of hard restart
        if systemctl is-active --quiet lsws 2>/dev/null; then
            run_command_warn "Khoi dong lai OpenLiteSpeed an toan" \
                /usr/local/lsws/bin/lswsctrl restart || systemctl restart lsws || true
            log SUCCESS "Da khoi dong lai OpenLiteSpeed"
        fi
    else
        log INFO "Da bo qua cai dat phpMyAdmin"
    fi

    # Ensure Apache2 is stopped and disabled if it was installed as a dependency
    if systemctl is-active --quiet apache2 2>/dev/null; then
        run_command_warn "Dang tat dich vu Apache2 xung dot" \
            bash -c "systemctl stop apache2 || true && systemctl disable apache2 || true" || true
        log SUCCESS "Da dung va tat dich vu Apache2"
    fi
    if systemctl is-active --quiet nginx 2>/dev/null; then
        run_command_warn "Dang tat dich vu Nginx xung dot" \
            bash -c "systemctl stop nginx || true && systemctl disable nginx || true" || true
        log SUCCESS "Da dung va tat dich vu Nginx"
    fi

    echo ""
    log SUCCESS "Cai dat cac dich vu bo sung hoan tat"
}

# ============================================================================
# PHASE 6: INSTALL VPANEL PANEL
# ============================================================================

phase_6_install_panel() {

    # Check and install git if needed
    if ! command -v git &> /dev/null; then
        log WARNING "Khong tim thay git, dang cai dat..."
        run_command "Dang cai dat git" \
            system_install_package git
    fi

    # Ensure jq is installed (default requirement)
    if ! command -v jq &>/dev/null; then
        run_command "Dang cai dat jq (bat buoc cho VPanel)" \
            system_install_package jq || {
            log ERROR "Khong the tu dong cai dat jq. Vui long tu cai dat."
            exit 1
        }
    fi

    # Backup old panel if exists
    if [ -d "${PANEL_DIR}" ]; then
        run_command "Dang sao luu thu muc Panel cu" \
            bash -c "mv '${PANEL_DIR}' '${PANEL_DIR}.backup.$(date +%s)'"
    fi

    run_command "Dang tao thu muc panel" \
        bash -c "mkdir -p ${PANEL_DIR}"

    # Download and extract from API
    local max_retries=3
    local retry_count=0
    local dl_success=false

    local install_zip="/tmp/vpanel_install.zip"
    local install_url="${VPANEL_SCRIPT}"

    # Ensure unzip is installed
    if ! command -v unzip &> /dev/null; then
        run_command "Dang cai dat unzip" \
            system_install_package unzip
    fi

    while [ ${retry_count} -lt ${max_retries} ] && [ "${dl_success}" = false ]; do
        echo -e "${BLUE}[⏳]${NC} Dang cai dat VPanel tu may chu..."

        # Download zip
        wget -qO "${install_zip}" "${install_url}" >> "${LOG_FILE}" 2>&1
        local dl_exit=$?

        if [ $dl_exit -eq 0 ]; then
            # Extract
            unzip -q -o "${install_zip}" -d "${PANEL_DIR}" >> "${LOG_FILE}" 2>&1
            if [ $? -eq 0 ]; then
                dl_success=true
                log SUCCESS "Da tai va giai nen VPanel thanh cong"
                rm -f "${install_zip}"
            else
                log WARNING "Giai nen file that bai"
                retry_count=$((retry_count + 1))
            fi
        else
            retry_count=$((retry_count + 1))
            if [ ${retry_count} -lt ${max_retries} ]; then
                log WARNING "Tai file that bai, thu lai sau 5 giay..."
                sleep 5
            fi
        fi
    done

    if [ "${dl_success}" = false ]; then
        log ERROR "Khong the cai dat VPanel sau ${max_retries} lan thu"
        log ERROR "Vui long kiem tra: 1) Ket noi Internet, 2) URL tai: ${install_url}"
        return 1
    fi
    run_command "Dang thiet lap quyen cho thu muc" \
        bash -c "chmod -R 755 ${PANEL_DIR}/{config,lib,features,premium}; chmod 755 ${PANEL_DIR}/*.sh"

    run_command "Dang thiet lap quyen cho file cau hinh" \
        bash -c "find ${PANEL_DIR}/config -type f -exec chmod 644 {} \\;"
    run_command "Dang tao thu muc logs" \
        bash -c "mkdir -p ${LOG_DIR} && chmod 755 ${LOG_DIR}"
    run_command "Dang tao symlink he thong" \
        bash -c "ln -sf ${PANEL_DIR}/vpanel.sh /usr/local/bin/vpanel && ln -sf ${PANEL_DIR}/vpanel.sh /usr/local/bin/vpanel && chmod +x ${PANEL_DIR}/vpanel.sh"

    log SUCCESS "Da cai dat VPanel tai ${PANEL_DIR}"
}

# ============================================================================
# PHASE 7: INTEGRATE WITH OPENLITESPEED
# ============================================================================

phase_7_integrate_ols() {
    local nobody_group="nogroup"
    if [ "${OS_FAMILY}" = "rhel" ]; then
        nobody_group="nobody"
    fi

    run_command "Dang thiet lap quyen OLS" \
        bash -c "mkdir -p /usr/local/lsws/conf/vhosts && chown -R nobody:${nobody_group} /usr/local/lsws/conf/vhosts"
    run_command "Dang tao cau hinh logrotate cho OLS" \
        bash -c "cat > /etc/logrotate.d/openlitespeed << 'EOF'
/usr/local/lsws/logs/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0644 nobody ${nobody_group}
    sharedscripts
    postrotate
        /usr/local/lsws/bin/lswsctrl restart > /dev/null 2>&1 || true
    endscript
}
EOF"
    run_command "Dang cap nhat cau hinh cache OLS" \
        bash -c "sed -i 's/enableExpires.*/enableExpires: 1/g' /usr/local/lsws/conf/httpd_config.conf || true"
    run_command "Dang tai lai OLS" \
        bash -c "/usr/local/lsws/bin/lswsctrl restart || true"
    run_command "Dang cai dat Auto-Tune Service" \
        bash -c "${PANEL_DIR}/features/autotune/autotune_manager.sh --setup || true"
}

# ============================================================================
# PHASE 8: FINALIZATION
# ============================================================================

phase_8_finalization() {
    local health_status=0

    # Check OpenLiteSpeed
    if systemctl is-active --quiet lsws; then
        log SUCCESS "OpenLiteSpeed: Dang chay"
    else
        log ERROR "OpenLiteSpeed: Khong chay"
        health_status=1
    fi

    # Check PHP
    if /usr/local/lsws/lsphp${PHP_VERSION//./}/bin/lsphp -v > /dev/null 2>&1; then
        local php_version=$(/usr/local/lsws/lsphp${PHP_VERSION//./}/bin/lsphp -v | head -1)
        log SUCCESS "PHP CLI: ${php_version}"
    else
        log ERROR "PHP CLI: Khong kha dung (/usr/local/lsws/lsphp${PHP_VERSION//./}/bin/lsphp)"
        health_status=1
    fi

    # Check MariaDB
    if systemctl is-active --quiet mysql; then
        log SUCCESS "MariaDB: Dang chay"
    else
        log ERROR "MariaDB: Khong chay"
        health_status=1
    fi

    # Check Redis if installed
    if systemctl is-active --quiet redis 2>/dev/null; then
        log SUCCESS "Redis: Dang chay"
    fi

    run_command "Cau hinh trang mac dinh (Default Server Site)" \
        configure_default_server_site

    run_command "Cai dat SSL Let's Encrypt cho IP Server" \
        install_ip_ssl_and_force_https

    run_command "Khoi dong lai dich vu OLS" \
        systemctl restart lsws

    run_command "Kich hoat License Mac Dinh" \
        bash -c "mkdir -p ${PANEL_DIR}/config && echo 'PREMIUM_LICENSE_KEY=\"VPANEL-FREE-COMMUNITY\"' >> ${PANEL_DIR}/config/settings.conf && source ${PANEL_DIR}/lib/license.sh && (activate_with_license_key \"VPANEL-FREE-COMMUNITY\" || true) && auto_check_activation || true"

    local credentials_summary="${CREDENTIALS_FILE}.summary"

    echo ""
    bash -c "cat >> ${credentials_summary} << 'CREDSEOF'
THONG TIN DANG NHAP MAC DINH:
CREDSEOF"

    if [ -f "${CREDENTIALS_FILE}.ols_admin_pass" ]; then
        local ols_pass
        ols_pass=$(cat "${CREDENTIALS_FILE}.ols_admin_pass")
        echo "" >> "${credentials_summary}"
        echo "Quan tri OLS (cong 7080):" >> "${credentials_summary}"
        echo "• URL: https://$(get_server_ip):7080" >> "${credentials_summary}"
        echo "• Ten dang nhap: ${OLS_ADMIN_USER}" >> "${credentials_summary}"
        echo "• Mat khau: ${ols_pass}" >> "${credentials_summary}"
    fi

    if [ -f "${CREDENTIALS_FILE}.mysql_root_pass" ]; then
        local mysql_pass
        mysql_pass=$(cat "${CREDENTIALS_FILE}.mysql_root_pass")
        echo "" >> "${credentials_summary}"
        echo "Quan tri CSDL MariaDB:" >> "${credentials_summary}"
        echo "• Ten dang nhap: root" >> "${credentials_summary}"
        echo "• Mat khau: ${mysql_pass}" >> "${credentials_summary}"
    fi

    # Check if phpMyAdmin was installed
    local phpmyadmin_installed=false
    for service in "${DEPLOYED_SERVICES[@]}"; do
        if [ "${service}" = "phpmyadmin" ]; then
            phpmyadmin_installed=true
            break
        fi
    done

    if [ "${phpmyadmin_installed}" = true ]; then
        echo "" >> "${credentials_summary}"
        echo "Quan tri CSDL phpMyAdmin:" >> "${credentials_summary}"
        echo "• Duong dan: https://$(get_server_ip)/phpmyadmin" >> "${credentials_summary}"
        echo "• Ten dang nhap: root" >> "${credentials_summary}"
        if [ -f "${CREDENTIALS_FILE}.mysql_root_pass" ]; then
            local mysql_root_pass=$(cat "${CREDENTIALS_FILE}.mysql_root_pass")
            echo "• Mat khau: ${mysql_root_pass}" >> "${credentials_summary}"
        fi
    fi

    # Panel CLI
    echo ""
    if [ ${#FAILED_SERVICES[@]} -gt 0 ]; then
        echo -e "${YELLOW}Cac dich vu bo sung sau khong cai dat duoc (VPanel van hoat dong):${NC}"
        for svc in "${FAILED_SERVICES[@]}"; do
            echo -e "  - ${svc}"
        done
        echo ""
    fi
    echo "VPanel CLI"
    echo -e "Su dung: ${GREEN}vpanel${NC} hoac ${GREEN}vpanel [SO_MENU]${NC} hoac ${GREEN}vpanel [TUY CHON]${NC}"
    echo "Tuy chon:"
    echo -e "  ${GREEN}[SO_MENU]${NC}      Mo nhanh vao tinh nang (vidu: vpanel 28)"
    echo -e "  ${RED}--uninstall${NC}    Chay tien trinh go cai dat he thong"
    echo -e "  ${YELLOW}--help, -h${NC}     Hien thi muc giup do nay"
    echo ""

    cat "${credentials_summary}"
    echo ""
}

# ============================================================================
# MAIN EXECUTION
# ============================================================================

main() {
    # Pre-flight checks
    check_root
    detect_os

    # Create log directory
    mkdir -p "${LOG_DIR}"

    log INFO "Bat dau cai dat VPanel"

    # Confirm start
    echo ""
    local response="n"
    if [ "${AUTO_YES}" = true ]; then
        response="y"
    else
        read -p "Ban co muon tiep tuc cai dat khong? (Y/n - Enter de tiep tuc) : " -r response

        # Debug user input

        # Trim whitespace and convert to lowercase for comparison
        response=$(echo "${response}" | tr -cd '[:alpha:]' | tr '[:upper:]' '[:lower:]')
        if [ -z "${response}" ]; then
            response="y"
        fi
    fi

    if ! [[ "${response}" =~ ^[Yy]$ ]]; then
        log WARNING "Huy cai dat"
        exit 0
    fi

    # Execute installation phases
    phase_1_pre_checks
    phase_2_install_ols
    phase_3_install_php
    phase_4_install_databases
    phase_5_install_services
    phase_6_install_panel
    phase_7_integrate_ols
    phase_8_finalization

    # Final status
    if [ "${ERROR_OCCURRED}" = true ]; then
        log WARNING "Cai dat hoan tat nhung co mot vai canh bao - xem log de biet chi tiet: ${LOG_FILE}"
    else
        log SUCCESS "Cai dat da hoan tat thanh cong"
    fi
}

# Run main
main "$@"
