#!/usr/bin/env bash

set -euo pipefail

# Configuration
PUBLIC_REPO_URL="http://repo.starwind.com/proxmox/"
KEY_URL="https://repo.starwind.com/keys/repo_public.key"

KEYRING_PATH="/usr/share/keyrings/starwind-proxmox.gpg"
SOURCE_FILE="/etc/apt/sources.list.d/starwind-proxmox.sources"

# Package configuration
OLD_PACKAGES=(starwind-proxmox-plugin)  # Old package name(s) to remove
NEW_PACKAGES=(starwind-proxmox-plugin-pve9)  # New package name(s) to install

# Path configuration
GPG_KEY_LOCAL_PATH="/root/dm-tests/new-gpg-key/starwind-proxmox.gpg"
BACKUP_DIR="/root/old-apt-configs/backup"

# Logging configuration
LOG_DIR="/var/log/starwind/starwind-proxmox-plugin"
LOG_FILE="$LOG_DIR/install.log"

# Repository selection (will be determined automatically)
SELECTED_REPO_URL=""
USE_SIGNED_REPO=false

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

# Initialize logging
init_logging() {
    mkdir -p "$LOG_DIR"
    chmod 755 "$LOG_DIR"
    
    # Start new log entry
    echo "========================================" >> "$LOG_FILE"
    echo "Installation started: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
    echo "========================================" >> "$LOG_FILE"
}

# Logging functions - output to both console and file
log_info() {
    local message="$1"
    echo -e "${GREEN}[INFO]${NC} $message"
    echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
}

log_warn() {
    local message="$1"
    echo -e "${YELLOW}[WARN]${NC} $message"
    echo "[WARN] $(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
}

log_error() {
    local message="$1"
    echo -e "${RED}[ERROR]${NC} $message"
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
}

log_command() {
    local description="$1"
    shift
    log_info "$description"
    echo "[CMD] $(date '+%Y-%m-%d %H:%M:%S') - Running: $*" >> "$LOG_FILE"
    "$@" >> "$LOG_FILE" 2>&1
    return $?
}

# Validation functions
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "This script must be run as root"
        exit 1
    fi
}

check_proxmox() {
    if [[ ! -f /etc/pve/.version ]]; then
        log_error "This doesn't appear to be a Proxmox VE system"
        exit 1
    fi
    
    local pve_version
    pve_version=$(pveversion | grep -oP 'pve-manager/\K[0-9]+' || echo "0")
    log_info "Detected Proxmox VE version: $pve_version"
    
    if [[ "$pve_version" -lt 9 ]]; then
        log_warn "Detected Proxmox VE version $pve_version. This script is designed for PVE 9+"
        read -p "Continue anyway? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Installation cancelled by user"
            exit 0
        fi
        log_info "User chose to continue despite version mismatch"
    fi
}

# Install GPG key for testing (used before final repository selection)
install_gpg_key_for_test() {
    # If key already exists, we're good
    if [[ -f "$KEYRING_PATH" ]]; then
        return 0
    fi
    
    # Check if custom key exists (offline mode)
    if [[ -f "$GPG_KEY_LOCAL_PATH" ]]; then
        log_info "Installing local GPG key for testing"
        if cp "$GPG_KEY_LOCAL_PATH" "$KEYRING_PATH" 2>> "$LOG_FILE"; then
            chmod 0644 "$KEYRING_PATH"
            return 0
        fi
    fi
    
    # Try to download key from URL
    log_info "Downloading GPG key for testing"
    if curl -fsSL --connect-timeout 10 "$KEY_URL" 2>> "$LOG_FILE" | gpg --dearmor --yes --output "$KEYRING_PATH" 2>> "$LOG_FILE"; then
        chmod 0644 "$KEYRING_PATH"
        return 0
    fi
    
    return 1
}

# Test if a repository works with apt
test_repository() {
    local repo_url="$1"
    local use_signed="$2"
    
    log_info "Testing repository configuration: $repo_url"
    
    # Create temporary sources file for testing
    local test_source_file="/tmp/starwind-test-$$.sources"
    
    if [[ "$use_signed" == "true" ]]; then
        cat > "$test_source_file" <<EOF
Types: deb
URIs: $repo_url
Suites: trixie
Components: main
Signed-By: $KEYRING_PATH
EOF
    else
        cat > "$test_source_file" <<EOF
Types: deb
URIs: $repo_url
Suites: trixie
Components: main
Trusted: yes
EOF
    fi
    
    # Try apt update with this configuration
    echo "[TEST] $(date '+%Y-%m-%d %H:%M:%S') - Testing repository: $repo_url" >> "$LOG_FILE"
    if apt-get update \
        -o Dir::Etc::sourcelist="$test_source_file" \
        -o Dir::Etc::sourceparts="-" \
        -o APT::Get::List-Cleanup="0" \
        >> "$LOG_FILE" 2>&1; then
        log_info "Repository test successful"
        rm -f "$test_source_file"
        return 0
    else
        log_warn "Repository test failed - see log for details"
        rm -f "$test_source_file"
        return 1
    fi
}

# Check repository availability and select appropriate one
select_repository() {
    log_info "Selecting appropriate repository..."
    
    # Try public repository
    log_info "Testing public repository: $PUBLIC_REPO_URL"
    if curl -s --head --connect-timeout 10 "$PUBLIC_REPO_URL" > /dev/null 2>&1; then
        log_info "Public repository URL is accessible"
        
        # Install GPG key first for testing
        if install_gpg_key_for_test; then
            # Test if repository works with apt
            if test_repository "$PUBLIC_REPO_URL" "true"; then
                SELECTED_REPO_URL="$PUBLIC_REPO_URL"
                USE_SIGNED_REPO=true
                log_info "Selected: PUBLIC SIGNED REPOSITORY"
                return 0
            else
                log_warn "Public repository is accessible but doesn't have valid Debian structure"
            fi
        else
            log_warn "Could not install GPG key for public repository testing"
        fi
    else
        log_warn "Public repository URL is not accessible"
    fi
    
    log_error "No valid repository found"
    log_error "Public repo: $PUBLIC_REPO_URL"
    return 1
}

# Cleanup function
cleanup_old_configs() {
    log_info "Cleaning up old repository configurations..."
    
    # Ensure backup directory exists
    mkdir -p "$BACKUP_DIR"
    chmod 755 "$BACKUP_DIR"
    
    local cleaned=0
    
    if [[ -f /etc/apt/sources.list.d/starwind-proxmox.list ]]; then
        local backup_file="$BACKUP_DIR/starwind-proxmox.list.backup.$(date +%Y%m%d_%H%M%S)"
        cp /etc/apt/sources.list.d/starwind-proxmox.list "$backup_file"
        log_info "Backed up legacy .list file to: $backup_file"
        rm -f /etc/apt/sources.list.d/starwind-proxmox.list && cleaned=1
        log_info "Removed legacy .list file"
    fi
    
    if [[ -f /etc/apt/trusted.gpg.d/starwind-proxmox.gpg ]]; then
        local backup_file="$BACKUP_DIR/starwind-proxmox.gpg.backup.$(date +%Y%m%d_%H%M%S)"
        cp /etc/apt/trusted.gpg.d/starwind-proxmox.gpg "$backup_file"
        log_info "Backed up legacy GPG key to: $backup_file"
        rm -f /etc/apt/trusted.gpg.d/starwind-proxmox.gpg && cleaned=1
        log_info "Removed legacy GPG key"
    fi
    
    if [[ $cleaned -eq 0 ]]; then
        log_info "No legacy configurations found"
    fi
    
    return 0
}

# Uninstall old plugin
uninstall_old_plugin() {
    log_info "Checking for old plugin installation (PVE 8 version)..."
    
    local installed=0
    local installed_packages=()
    
    for pkg in "${OLD_PACKAGES[@]}"; do
        if dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "install ok installed"; then
            installed=1
            installed_packages+=("$pkg")
            log_info "Found old package: $pkg"
        fi
    done
    
    if [[ $installed -eq 1 ]]; then
        log_info "Removing old plugin version(s): ${installed_packages[*]}"
        if log_command "Running apt remove for old packages" apt remove -y "${installed_packages[@]}"; then
            log_info "Old plugin(s) removed successfully"
        else
            log_warn "Failed to remove old plugin(s), continuing anyway..."
            return 0
        fi
    else
        log_info "No old plugin installation found"
    fi
    
    return 0
}

# Install GPG key (only if using signed repository)
install_gpg_key() {
    if [[ "$USE_SIGNED_REPO" == false ]]; then
        log_info "Skipping GPG key installation (using unsigned repository)"
        return 0
    fi
    
    # Key may already be installed from testing phase
    if [[ -f "$KEYRING_PATH" ]]; then
        log_info "GPG key already installed from testing phase"
        return 0
    fi
    
    log_info "Installing StarWind repository GPG key..."
    
    # Check if custom key exists (offline mode)
    if [[ -f "$GPG_KEY_LOCAL_PATH" ]]; then
        log_info "Using local GPG key: $GPG_KEY_LOCAL_PATH"
        if cp "$GPG_KEY_LOCAL_PATH" "$KEYRING_PATH"; then
            chmod 0644 "$KEYRING_PATH"
            log_info "Local GPG key installed successfully"
            return 0
        else
            log_error "Failed to copy local GPG key from $GPG_KEY_LOCAL_PATH"
            return 1
        fi
    fi
    
    # Try to download key from URL
    log_info "Downloading GPG key from $KEY_URL..."
    if curl -fsSL --connect-timeout 10 "$KEY_URL" 2>> "$LOG_FILE" | gpg --dearmor --yes --output "$KEYRING_PATH" 2>> "$LOG_FILE"; then
        chmod 0644 "$KEYRING_PATH"
        log_info "GPG key downloaded and installed successfully"
        return 0
    else
        log_error "Failed to download GPG key from $KEY_URL"
        log_error "Please ensure the key is available at $GPG_KEY_LOCAL_PATH"
        return 1
    fi
}

# Configure repository
configure_repository() {
    log_info "Configuring Proxmox VE 9 (trixie) repository..."
    
    # Ensure backup directory exists
    mkdir -p "$BACKUP_DIR"
    chmod 755 "$BACKUP_DIR"
    
    # Backup existing source file if present
    if [[ -f "$SOURCE_FILE" ]]; then
        local backup_file="$BACKUP_DIR/starwind-proxmox.sources.backup.$(date +%Y%m%d_%H%M%S)"
        cp "$SOURCE_FILE" "$backup_file"
        log_info "Backed up existing sources file to: $backup_file"
    fi
    
    if [[ "$USE_SIGNED_REPO" == false ]]; then
        log_warn "Configuring UNSIGNED repository (trusted=yes) - FOR INTERNAL TESTING ONLY"
        cat > "$SOURCE_FILE" <<EOF
Types: deb
URIs: $SELECTED_REPO_URL
Suites: trixie
Components: main
Trusted: yes
EOF
    else
        log_info "Configuring signed repository with GPG verification"
        cat > "$SOURCE_FILE" <<EOF
Types: deb
URIs: $SELECTED_REPO_URL
Suites: trixie
Components: main
Signed-By: $KEYRING_PATH
EOF
    fi
    
    if [[ $? -eq 0 ]]; then
        log_info "Repository configuration written successfully to: $SOURCE_FILE"
        echo "[CONFIG] $(date '+%Y-%m-%d %H:%M:%S') - Repository configuration:" >> "$LOG_FILE"
        cat "$SOURCE_FILE" >> "$LOG_FILE"
        return 0
    else
        log_error "Failed to write repository configuration"
        return 1
    fi
}

# Update APT
update_apt() {
    log_info "Updating APT metadata..."
    
    # Run apt update and capture output
    local apt_output
    echo "[CMD] $(date '+%Y-%m-%d %H:%M:%S') - Running: apt update" >> "$LOG_FILE"
    apt_output=$(apt update 2>&1) || true
    echo "$apt_output" >> "$LOG_FILE"
    
    # Check if StarWind repository was successfully updated
    if echo "$apt_output" | grep -q "repo.starwind.com/proxmox.*InRelease"; then
        log_info "APT metadata updated successfully"
        log_info "StarWind repository is accessible and working"
        
        # Warn about other repository failures if present
        if echo "$apt_output" | grep -q "Error:"; then
            log_warn "Some other repositories failed to update (not StarWind)"
            log_warn "This is normal if you don't have Proxmox Enterprise subscription"
        fi
        
        return 0
    else
        log_error "Failed to update StarWind repository"
        log_error "Check $LOG_FILE for details"
        return 1
    fi
}

# Install packages
install_packages() {
    log_info "Installing/upgrading StarWind packages for PVE 9..."
    
    for pkg in "${NEW_PACKAGES[@]}"; do
        log_info "Package to install: $pkg"
    done
    
    if log_command "Running apt install" apt install -y "${NEW_PACKAGES[@]}"; then
        log_info "Packages installed successfully"
        return 0
    else
        log_error "Failed to install packages"
        log_error "Check $LOG_FILE for details"
        return 1
    fi
}

# Verify installation
verify_installation() {
    log_info "Verifying installation..."
    
    local all_installed=1
    
    # Check that old packages are removed
    log_info "Checking old packages are removed..."
    for pkg in "${OLD_PACKAGES[@]}"; do
        if dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "install ok installed"; then
            log_warn "⚠ Old package $pkg is still installed"
        else
            log_info "Old package $pkg is removed"
        fi
    done
    
    # Check that new packages are installed
    log_info "Checking new packages are installed..."
    for pkg in "${NEW_PACKAGES[@]}"; do
        if dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "install ok installed"; then
            local version=$(dpkg-query -W -f='${Version}' "$pkg" 2>/dev/null)
            log_info "$pkg is installed (version: $version)"
        else
            log_error "$pkg is NOT installed"
            all_installed=0
        fi
    done
    
    return $((1 - all_installed))
}

# Finalize logging
finalize_logging() {
    echo "========================================" >> "$LOG_FILE"
    echo "Installation completed: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
    echo "Repository used: $SELECTED_REPO_URL" >> "$LOG_FILE"
    echo "Signed repository: $USE_SIGNED_REPO" >> "$LOG_FILE"
    echo "========================================" >> "$LOG_FILE"
    echo "" >> "$LOG_FILE"
}

# Main execution
main() {
    # Initialize logging first
    init_logging
    
    log_info "Starting StarWind Proxmox VE 9 plugin installation"
    log_info "================================================"
    log_info "Old package(s) to remove: ${OLD_PACKAGES[*]}"
    log_info "New package(s) to install: ${NEW_PACKAGES[*]}"
    log_info "Log file: $LOG_FILE"
    log_info "Backup directory: $BACKUP_DIR"
    
    check_root
    check_proxmox
    
    # Select appropriate repository
    if ! select_repository; then
        log_error "Failed to select a valid repository - cannot continue"
        finalize_logging
        exit 1
    fi
    
    cleanup_old_configs || log_warn "Cleanup had issues, continuing..."
    uninstall_old_plugin || log_warn "Uninstall had issues, continuing..."
    
    if ! install_gpg_key; then
        log_error "GPG key installation failed - cannot continue"
        finalize_logging
        exit 1
    fi
    
    if ! configure_repository; then
        log_error "Repository configuration failed - cannot continue"
        finalize_logging
        exit 1
    fi
    
    if ! update_apt; then
        log_error "APT update failed - cannot continue"
        finalize_logging
        exit 1
    fi
    
    if ! install_packages; then
        log_error "Package installation failed"
        finalize_logging
        exit 1
    fi
    
    if verify_installation; then
        log_info "================================================"
        log_info "StarWind plugin successfully updated for Proxmox VE 9"
        log_info "Repository used: $SELECTED_REPO_URL"
        log_info "Signed: $USE_SIGNED_REPO"
        log_info "================================================"
        log_info "Full installation log available at: $LOG_FILE"
    else
        log_warn "Installation completed but verification failed"
        log_warn "Please check the installation manually"
        log_warn "Full log available at: $LOG_FILE"
        finalize_logging
        exit 1
    fi
    
    finalize_logging
}

# Run main function
main