#!/bin/bash

set -e

export DEBIAN_FRONTEND=noninteractive

LOG_FILE="/var/log/aubo_setup_$(date +%Y%m%d_%H%M%S).log"

log_info() {
    echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

log_warn() {
    echo "[WARN] $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

log_success() {
    echo "[SUCCESS] $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

log_section() {
    echo "" | tee -a "$LOG_FILE"
    echo "============================================================" | tee -a "$LOG_FILE"
    echo "  $1" | tee -a "$LOG_FILE"
    echo "============================================================" | tee -a "$LOG_FILE"
}

run_cmd() {
    local cmd="$1"
    local description="$2"
    local fail_on_error=${3:-true}

    log_info "Executing: $cmd"
    if eval "$cmd" >> "$LOG_FILE" 2>&1; then
        [ -n "$description" ] && log_success "$description"
        return 0
    else
        if [ "$fail_on_error" = "true" ]; then
            log_error "Command failed: $cmd"
            return 1
        else
            log_warn "Command failed (non-critical): $cmd"
            return 0
        fi
    fi
}

check_root() {
    if [ "$EUID" -ne 0 ]; then
        log_error "Please run as root"
        exit 1
    fi
}

cleanup_on_exit() {
    local exit_code=$?
    if [ $exit_code -ne 0 ]; then
        log_error "Script failed with exit code $exit_code"
        log_error "Check log file: $LOG_FILE"
    fi
    exit $exit_code
}

trap cleanup_on_exit EXIT

check_root

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

if [ -f "$SCRIPT_DIR/config.sh" ]; then
    source "$SCRIPT_DIR/config.sh"
    log_info "Loaded configuration from config.sh"
else
    log_warn "config.sh not found, using default values"
fi

PHASE=1

log_section "Aubo Setup Script - Starting"

if [ -z "$VERSION" ]; then
    VERSION=$(ls /opt/arcs/ 2>/dev/null | grep -E '^[0-9]' | head -1 || echo "")
fi

log_section "Phase $PHASE: System Preparation"

log_info "Enabling network apt sources..."
run_cmd "sed -i 's/^#deb /deb /' /etc/apt/sources.list" "Enable network sources" false

ISO_MOUNT_POINT="${ISO_MOUNT_POINT:-/media/cdrom}"

if [ -n "$ISO_PATH" ]; then
    log_info "Mounting ISO from: $ISO_PATH"
    run_cmd "mkdir -p '$ISO_MOUNT_POINT'" "Create mount directory"
    run_cmd "mount -o loop '$ISO_PATH' '$ISO_MOUNT_POINT' 2>/dev/null || true" "Mount ISO" false
else
    log_info "Mounting CDROM..."
    run_cmd "mkdir -p '$ISO_MOUNT_POINT'" "Create cdrom directory"
    run_cmd "mount /dev/cdrom '$ISO_MOUNT_POINT' 2>/dev/null || mount -o loop /dev/sr0 '$ISO_MOUNT_POINT' 2>/dev/null || true" "Mount CDROM" false
fi

log_info "Adding CDROM apt source..."
run_cmd "apt-cdrom -m -d '$ISO_MOUNT_POINT' add 2>/dev/null || true" "Add CDROM source" false

log_info "Updating package lists..."
run_cmd "apt-get update -y" "Update apt"

log_info "Upgrading system..."
run_cmd "apt-get dist-upgrade -y" "Distribution upgrade" false

log_section "Phase $PHASE: Installing Required Packages"

PACKAGES=(
    "ia32-libs"
    "curl"
    "wget"
    "net-tools"
    "iproute2"
    "gdb"
    "lsb-release"
    "binutils"
    "unzip"
    "file"
    "openssh-server"
    "execstack"
    "build-essential"
    "libnuma-dev"
    "git"
    "picom"
)

for pkg in "${PACKAGES[@]}"; do
    run_cmd "apt-get install -y $pkg" "Install $pkg" false
done

if [ -f "$SCRIPT_DIR/nginx.zip" ]; then
    log_info "Extracting nginx.zip to /usr/local/nginx..."
    run_cmd "unzip -o '$SCRIPT_DIR/nginx.zip' -d /usr/local/" "Extract nginx" false
fi

if [ -f "$SCRIPT_DIR/nginx.conf" ]; then
    log_info "Replacing nginx.conf..."
    run_cmd "cp '$SCRIPT_DIR/nginx.conf' /usr/local/nginx/conf/nginx.conf" "Replace nginx.conf"
    log_success "Nginx configuration replaced"
fi

if [ -d "$SCRIPT_DIR/lib" ]; then
    log_info "Copying libcrypto and libssl..."
    run_cmd "cp -av '$SCRIPT_DIR/lib/libcrypto.so.1.1' /lib/x86_64-linux-gnu/" "Copy libcrypto" false
    run_cmd "cp -av '$SCRIPT_DIR/lib/libssl.so.1.1' /lib/x86_64-linux-gnu/" "Copy libssl" false
    run_cmd "ldconfig" "Update library cache"
    log_success "Libraries copied"
fi

if [ -f "$SCRIPT_DIR/openssl" ]; then
    log_info "Installing openssl..."
    run_cmd "cp -av '$SCRIPT_DIR/openssl' /usr/bin/openssl" "Copy openssl to /usr/bin"
    run_cmd "chmod a+x /usr/bin/openssl" "Set openssl executable"
    log_success "OpenSSL installed"
fi

log_section "Phase $PHASE: Configuring SSH"

SSH_PORT=8822
log_info "Configuring SSH port to $SSH_PORT..."
run_cmd "sed -i.bak 's/^#Port 22/Port $SSH_PORT/' /etc/ssh/sshd_config" "Set SSH port" false
run_cmd "sed -i 's/^Port 22/Port $SSH_PORT/' /etc/ssh/sshd_config" "Set SSH port" false
run_cmd "sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/' /etc/ssh/sshd_config" "Allow SSH listen" false

if systemctl is-active --quiet sshd 2>/dev/null; then
    run_cmd "systemctl restart sshd" "Restart SSH"
elif systemctl is-active --quiet ssh 2>/dev/null; then
    run_cmd "systemctl restart ssh" "Restart SSH"
fi

run_cmd "systemctl enable sshd 2>/dev/null || systemctl enable ssh 2>/dev/null || true" "Enable SSH" false
log_success "SSH configured on port $SSH_PORT"

log_section "Phase $PHASE: Installing Touch Screen Driver"
wget https://download.aubo-robotics.cn/tools/pmLinux-Ubuntu_14.04_24_04_v4_7_7_R15_x86_64_aarch64_20240820_touch.tar
if [ -f "pmLinux-Ubuntu_14.04_24_04_v4_7_7_R15_x86_64_aarch64_20240820_touch.tar" ]; then
    run_cmd "tar -xvf pmLinux-Ubuntu_14.04_24_04_v4_7_7_R15_x86_64_aarch64_20240820_touch.tar" "Extract touch driver"
    run_cmd "cd ./pmLinux-Ubuntu && echo 24.4 | ./install.sh" "Install touch driver" false
else
    log_warn "Touch driver archive not found, skipping..."
fi

log_section "Phase $PHASE: Configuring GRUB for PARSEC"

GRUB_PARAMS_PARSEC="${GRUB_PARAMS_PARSEC:-parsec.mac=0 parsec.execstack=1}"
GRUB_PARAMS_ISOLCPUS="${GRUB_PARAMS_ISOLCPUS:-kthread_cpus=0,2,3 irqaffinity=0,2,3 isolcpus=1}"

log_info "Disabling PARSEC execstack protection..."
run_cmd "sed -i.bak '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"/\" $GRUB_PARAMS_PARSEC/' /etc/default/grub" "Update GRUB config"
run_cmd "update-grub" "Update GRUB"

log_info "Configuring isolcpus for real-time..."
run_cmd "sed -i.bak '/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"/\" $GRUB_PARAMS_ISOLCPUS/' /etc/default/grub" "Add isolcpus parameters"
run_cmd "update-grub" "Update GRUB"

log_info "Kernel parameters configured. Will reboot after all installations complete."

log_section "Phase $PHASE: Downloading and Installing ARCS"

ARCS_VERSION="${ARCS_VERSION:-0.31.0-rc.89+6d5db69}"
ARCS_URLS=(
    "https://download.aubo-robotics.cn/arcs/arcs_update-${ARCS_VERSION}-x86_64.run"
)

for url in "${ARCS_URLS[@]}"; do
    filename=$(basename "$url")
    if [ ! -f "$filename" ]; then
        log_info "Downloading $filename..."
        run_cmd "wget -q --show-progress '$url' -O '$filename'" "Download $filename" false
    fi
done

run_cmd "chmod +x arcs_update-*.run" "Set execute permission"

log_info "Installing ARCS..."
run_cmd "./arcs_update-*.run install" "Install ARCS" false

if [ -f /etc/default/arcs ]; then
    sed -i '/arcs_ws.*Is a directory/d' /etc/default/arcs 2>/dev/null || true
    source /etc/default/arcs 2>/dev/null || true
    
    AUBO_SCOPE_LD_PRELOAD="${AUBO_SCOPE_LD_PRELOAD:-/lib/x86_64-linux-gnu/libstdc++.so.6:/lib/x86_64-linux-gnu/libgcc_s.so.1}"
    
    if ! grep -q "LD_PRELOAD=" /etc/default/arcs 2>/dev/null; then
        echo "" >> /etc/default/arcs
        echo "LD_PRELOAD=$AUBO_SCOPE_LD_PRELOAD" >> /etc/default/arcs
        log_info "Added aubo_scope environment variables to /etc/default/arcs"
    fi

    if ! grep -q "xhost +local:root" /etc/profile 2>/dev/null; then
        echo "" >> /etc/profile
        echo "xhost +local:root" >> /etc/profile
        log_info "Added xhost +local:root to /etc/profile"
    fi
fi

# 添加system unit配置
CONF_FILE="/etc/systemd/system.conf"
TARGET_ENV='DefaultEnvironment="OPENSSL_CONF=/dev/null" "LD_PRELOAD=/lib/x86_64-linux-gnu/libstdc++.so.6:/lib/x86_64-linux-gnu/libgcc_s.no.1"'

echo "开始配置 systemd 全局环境变量..."

# 1. 检查文件是否存在
if [ ! -f "$CONF_FILE" ]; then
    echo "错误: 找不到配置文件 $CONF_FILE"
    exit 1
fi

# 2. 检查是否已经存在该配置（幂等性检查）
# 使用 grep 精确匹配，避免重复添加
if grep -qF "$TARGET_ENV" "$CONF_FILE"; then
    echo "检查通过: 配置已存在，无需修改。"
else
    echo "检测到配置缺失，正在添加..."
    
    # 备份原文件
    cp "$CONF_FILE" "${CONF_FILE}.bak_$(date +%F_%T)"

    # 逻辑：查找 [Manager] 并在其下方插入配置
    # 如果已存在被注释的 DefaultEnvironment，则直接替换它
    if grep -q "^#DefaultEnvironment=" "$CONF_FILE"; then
        sed -i "s|^#DefaultEnvironment=.*|$TARGET_ENV|" "$CONF_FILE"
    else
        # 如果没有注释行，则在 [Manager] 字段下插入
        sed -i "/^\[Manager\]/a $TARGET_ENV" "$CONF_FILE"
    fi
    systemctl daemon-reload
fi

# Configuration
cat <<EOF > "/lib/systemd/system/picom.service"
[Unit]
Description=Picom Compositor
After=display-manager.service

[Service]
Type=simple
# 建议改为普通用户执行，如果是嵌入式环境强制 root 请保持
User=root
Environment=DISPLAY=:0
Environment=XAUTHORITY=/root/.Xauthority

ExecStart=/usr/bin/picom --backend glx --xrender-sync-fence --glx-no-stencil --glx-no-rebind-pixmap --no-use-damage
Restart=always
RestartSec=3

[Install]
WantedBy=graphical.target
EOF

systemctl daemon-reload
systemctl enable --now picom

VERSION=$(ls /opt/arcs/ 2>/dev/null | grep -E '^[0-9]' | head -1 || echo "")

log_info "ARCS Version: $VERSION"

log_section "Phase $PHASE: Setting Permissions"

if [ -d "/opt/arcs" ]; then
    log_info "Setting 777 permissions on /opt/arcs..."
    run_cmd "chmod -R 777 /opt/arcs" "Set 777 permissions on /opt/arcs"
    log_success "ARCS directory permissions set to 777"
fi

log_section "Phase $PHASE: Installing CppMicroServices"

CPP_MICROSERVICES_URL="${CPP_MICROSERVICES_URL:-https://download.aubo-robotics.cn/sdk/CppMicroServices-4.0.0-Linux_x86_64+9f641ed.zip}"
CPP_FILENAME=$(basename "$CPP_MICROSERVICES_URL")

if [ ! -f "$CPP_FILENAME" ]; then
    log_info "Downloading $CPP_FILENAME..."
    run_cmd "wget -q '$CPP_MICROSERVICES_URL'" "Download CppMicroServices" false
fi

CPP_DIR="${CPP_FILENAME%.zip}"
if [ -d "$CPP_DIR" ]; then
    run_cmd "unzip -o -d /tmp '$CPP_FILENAME' && cp -r /tmp/$CPP_DIR/lib/* /usr/lib/ 2>/dev/null || true" "Copy CppMicroServices libraries" false
else
    run_cmd "unzip -o '$CPP_FILENAME'" "Extract CppMicroServices"
    run_cmd "cp $CPP_DIR/lib/*.so* /usr/lib/ 2>/dev/null || true" "Copy libraries" false
fi
run_cmd "execstack -c /usr/lib/libCppMicroServices.so.4.0.0 2>/dev/null || true" "Fix execstack" false
run_cmd "cd /usr/lib && ln -sf libCppMicroServices.so.4.0.0 libCppMicroServices.so.4 2>/dev/null || true" "Create symlink" false
run_cmd "cd /usr/lib && ln -sf libCppMicroServices.so.4.0.0 libCppMicroServices.so 2>/dev/null || true" "Create symlink" false
run_cmd "ldconfig" "Update library cache"

log_success "CppMicroServices installed"

log_section "Phase $PHASE: Configuring ARCS Services"

if [ -n "$VERSION" ] && [ -d "/opt/arcs/$VERSION" ]; then
    log_info "Configuring ARCS version: $VERSION"

    if [ -f "/opt/arcs/$VERSION/bin/aubo_control" ]; then
        run_cmd "ln -sf /opt/arcs/$VERSION/bin/aubo_control /usr/bin/aubo_control" "Create aubo_control symlink"
        run_cmd "chmod +x /opt/arcs/$VERSION/bin/aubo_control" "Set aubo_control executable"
    fi

    if [ -f "/opt/arcs/$VERSION/extensions/pnio/bin/pn_server" ]; then
        run_cmd "ln -sf /opt/arcs/$VERSION/extensions/pnio/bin/pn_server /usr/bin/pn_server" "Create pn_server symlink"
        run_cmd "chmod +x /opt/arcs/$VERSION/extensions/pnio/bin/pn_server" "Set pn_server executable"
    fi

    log_info "Fixing library execstack flags..."
    find "/opt/arcs/$VERSION" -name "*.so" -type f 2>/dev/null | while read -r lib; do
        if readelf -l "$lib" 2>/dev/null | grep -q "GNU_STACK.*RWE"; then
            execstack -c "$lib" 2>/dev/null || true
        fi
    done

    run_cmd "execstack -c /usr/lib/libCppMicroServices.so.4.0.0 2>/dev/null || true" "Fix CppMicroServices flags"

    if [ -f "/opt/arcs/$VERSION/bin/aubo_control" ]; then
        log_info "Checking aubo_control dependencies..."
        if ldd /opt/arcs/$VERSION/bin/aubo_control 2>/dev/null | grep -qi "not found"; then
            log_warn "Some dependencies not found for aubo_control"
            ldd /opt/arcs/$VERSION/bin/aubo_control 2>/dev/null | grep -i "not found" || true
        else
            log_success "All dependencies found"
        fi
    fi
else
    log_warn "ARCS installation not found, skipping service configuration"
fi

log_section "Phase $PHASE: Configuring Web Interface"

WEB_PORT="8090"

if [ -n "$VERSION" ] && [ -d "/opt/arcs/$VERSION/web" ]; then
    log_info "Web interface found, configuring..."

    if ss -tln 2>/dev/null | grep -q ":$WEB_PORT "; then
        log_warn "Port $WEB_PORT is already in use"
    fi

    run_cmd "systemctl stop nginx 2>/dev/null || true" "Stop nginx"

    if [ ! -d "/opt/arcs/$VERSION/web/frontend/dist" ]; then
        log_info "Creating minimal frontend structure..."
        run_cmd "mkdir -p /opt/arcs/$VERSION/web/frontend/dist" "Create frontend directory"
        echo '<html><body><h1>ARCS Web Interface</h1><p>Loading...</p></body></html>' > /opt/arcs/$VERSION/web/frontend/dist/index.html
    fi

    run_cmd "chown -R www-data:www-data '/opt/arcs/$VERSION/web/frontend/dist' 2>/dev/null || true" "Set owner"

    for dir in "/opt/arcs/$VERSION" "/opt/arcs/$VERSION/web" "/opt/arcs/$VERSION/web/frontend"; do
        run_cmd "chmod o+x '$dir' 2>/dev/null || true" "Set dir permission" false
    done

    if sudo -u www-data ls "/opt/arcs/$VERSION/web/frontend/dist/" >/dev/null 2>&1; then
        log_success "Access permissions configured correctly"
    else
        log_error "Access permission check failed"
    fi
else
    log_warn "Web interface not found, skipping..."
fi

log_section "Phase $PHASE: Configuring Nginx"

cat > /lib/systemd/system/nginx.service << 'EOF'
[Unit]
Description=nginx
PartOf=arcs.service
After=arcs.service
 
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

run_cmd "systemctl daemon-reload" "Reload systemd"

if [ -f "/etc/nginx/sites-available/arcs" ]; then
    run_cmd "rm -f /etc/nginx/sites-enabled/default 2>/dev/null || true" "Remove default config"
    run_cmd "ln -sf /etc/nginx/sites-available/arcs /etc/nginx/sites-enabled/ 2>/dev/null || true" "Enable arcs config" false
    NGINX_CONFIG_OK=true
else
    log_warn "ARCS nginx config not found, creating default config"
    mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled
    cat > /etc/nginx/sites-available/default << 'NGINX_EOF'
server {
    listen 8090;
    server_name localhost;
    root /opt/arcs;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}
NGINX_EOF
    run_cmd "ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default" "Enable default config" false
    NGINX_CONFIG_OK=true
fi

if nginx -t 2>/dev/null; then
    run_cmd "systemctl restart nginx" "Restart nginx"
    run_cmd "systemctl enable nginx" "Enable nginx"
    log_success "Nginx configured and started"
else
    log_warn "Nginx configuration test failed, trying to start anyway..."
    run_cmd "systemctl start nginx" "Start nginx" false
fi

log_section "Phase $PHASE: Installing Real-time Test Tools"

run_cmd "apt-get install -y build-essential libnuma-dev" "Install build tools" false

if [ ! -d "/root/rt-tests" ]; then
    run_cmd "git clone https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git /root/rt-tests" "Clone rt-tests"
fi

if [ -d "/root/rt-tests" ]; then
    run_cmd "cd /root/rt-tests && make -j$(nproc)" "Build rt-tests"
    run_cmd "cd /root/rt-tests && make install" "Install rt-tests"
    cd /
fi

log_section "Setup Complete"

log_success "========================================"
log_success "  Aubo Setup Completed Successfully!"
log_success "========================================"
log_info "Log file: $LOG_FILE"

echo ""
echo "============================================================"
echo "  System will reboot in 10 seconds..."
echo "============================================================"
sleep 10
reboot
