#!/bin/bash
# Linux Patch API - Interactive Installation Script
# For manual deployment on systems without package manager
# Supports Debian/Ubuntu, RHEL/CentOS/Fedora, Alpine, Arch

set -e

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

# Configuration
APP_NAME="linux-patch-api"
VERSION="1.0.0"
INSTALL_DIR="/usr/bin"
CONFIG_DIR="/etc/linux_patch_api"
CERTS_DIR="${CONFIG_DIR}/certs"
DATA_DIR="/var/lib/linux_patch_api"
LOG_DIR="/var/log/linux_patch_api"
SERVICE_FILE="/lib/systemd/system/linux-patch-api.service"
SYSTEM_USER="linux-patch-api"
SYSTEM_GROUP="linux-patch-api"

# Logging functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Check if running as root
check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        log_error "This script must be run as root"
        exit 1
    fi
    log_info "Running as root - OK"
}

# Detect OS and package manager
detect_os() {
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        OS_ID=$ID
        OS_VERSION=$VERSION_ID
        log_info "Detected OS: ${OS_ID} ${OS_VERSION}"
    else
        log_error "Cannot detect operating system"
        exit 1
    fi
}

# Check prerequisites
check_prerequisites() {
    log_info "Checking prerequisites..."
    
    # Check for systemd
    if ! command -v systemctl &> /dev/null; then
        log_error "systemd is required but not found"
        exit 1
    fi
    log_info "  - systemd: OK"
    
    # Check for required directories
    log_info "  - Checking directory structure..."
    
    # Check if binary exists
    if [ -f "target/x86_64-unknown-linux-gnu/release/${APP_NAME}" ]; then
        BINARY_PATH="target/x86_64-unknown-linux-gnu/release/${APP_NAME}"
        log_info "  - Binary found: ${BINARY_PATH}"
    elif [ -f "target/release/${APP_NAME}" ]; then
        BINARY_PATH="target/release/${APP_NAME}"
        log_info "  - Binary found: ${BINARY_PATH}"
    else
        log_error "Binary not found. Please build first with: cargo build --release"
        exit 1
    fi
    
    log_success "Prerequisites check passed"
}

# Create system user and group
create_system_user() {
    log_info "Creating system user and group..."
    
    # Create group if it doesn't exist
    if ! getent group ${SYSTEM_GROUP} > /dev/null 2>&1; then
        groupadd --system ${SYSTEM_GROUP}
        log_info "  - Created group: ${SYSTEM_GROUP}"
    else
        log_info "  - Group already exists: ${SYSTEM_GROUP}"
    fi
    
    # Create user if it doesn't exist
    if ! getent passwd ${SYSTEM_USER} > /dev/null 2>&1; then
        useradd --system \
            --gid ${SYSTEM_GROUP} \
            --home-dir ${DATA_DIR} \
            --no-create-home \
            --shell /usr/sbin/nologin \
            --comment "Linux Patch API Service" \
            ${SYSTEM_USER}
        log_info "  - Created user: ${SYSTEM_USER}"
    else
        log_info "  - User already exists: ${SYSTEM_USER}"
    fi
}

# Create directory structure
create_directories() {
    log_info "Creating directory structure..."
    
    mkdir -p ${CONFIG_DIR}
    mkdir -p ${CERTS_DIR}
    mkdir -p ${DATA_DIR}
    mkdir -p ${LOG_DIR}
    
    # Set ownership
    chown -R ${SYSTEM_USER}:${SYSTEM_GROUP} ${DATA_DIR}
    chown -R ${SYSTEM_USER}:${SYSTEM_GROUP} ${LOG_DIR}
    chown -R ${SYSTEM_USER}:${SYSTEM_GROUP} ${CONFIG_DIR}
    
    # Set permissions
    chmod 750 ${CONFIG_DIR}
    chmod 750 ${CERTS_DIR}
    chmod 755 ${DATA_DIR}
    chmod 755 ${LOG_DIR}
    
    log_success "Directory structure created"
}

# Install binary
install_binary() {
    log_info "Installing binary to ${INSTALL_DIR}..."
    
    cp ${BINARY_PATH} ${INSTALL_DIR}/${APP_NAME}
    chmod 755 ${INSTALL_DIR}/${APP_NAME}
    
    log_success "Binary installed: ${INSTALL_DIR}/${APP_NAME}"
}

# Install configuration files
install_config() {
    log_info "Installing configuration files..."
    
    # Copy example configs if they don't exist
    if [ ! -f "${CONFIG_DIR}/config.yaml" ]; then
        if [ -f "configs/config.yaml.example" ]; then
            cp configs/config.yaml.example ${CONFIG_DIR}/config.yaml
            chmod 640 ${CONFIG_DIR}/config.yaml
            log_info "  - Created default config.yaml"
        else
            log_warning "  - config.yaml.example not found"
        fi
    else
        log_info "  - config.yaml already exists"
    fi
    
    if [ ! -f "${CONFIG_DIR}/whitelist.yaml" ]; then
        if [ -f "configs/whitelist.yaml.example" ]; then
            cp configs/whitelist.yaml.example ${CONFIG_DIR}/whitelist.yaml
            chmod 640 ${CONFIG_DIR}/whitelist.yaml
            log_info "  - Created default whitelist.yaml"
        else
            log_warning "  - whitelist.yaml.example not found"
        fi
    else
        log_info "  - whitelist.yaml already exists"
    fi
    
    log_success "Configuration files installed"
}

# Install systemd service
install_service() {
    log_info "Installing systemd service..."
    
    if [ -f "configs/linux-patch-api.service" ]; then
        cp configs/linux-patch-api.service ${SERVICE_FILE}
        chmod 644 ${SERVICE_FILE}
        systemctl daemon-reload
        log_success "Systemd service installed"
    else
        log_error "Service file not found: configs/linux-patch-api.service"
        exit 1
    fi
}

# Generate self-signed certificates (optional)
generate_certificates() {
    log_info "Checking for TLS certificates..."
    
    if [ ! -f "${CERTS_DIR}/server.pem" ] || [ ! -f "${CERTS_DIR}/server.key.pem" ]; then
        echo ""
        echo -e "${YELLOW}No TLS certificates found.${NC}"
        read -p "Generate self-signed certificates for testing? (y/n): " -n 1 -r
        echo ""
        
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            log_info "Generating self-signed certificates..."
            
            # Generate CA
            openssl genrsa -out ${CERTS_DIR}/ca.key.pem 4096
            openssl req -x509 -new -nodes -sha256 -days 3650 \
                -key ${CERTS_DIR}/ca.key.pem \
                -out ${CERTS_DIR}/ca.pem \
                -subj "/CN=Linux Patch API CA"
            
            # Generate server key and CSR
            openssl genrsa -out ${CERTS_DIR}/server.key.pem 2048
            openssl req -new \
                -key ${CERTS_DIR}/server.key.pem \
                -out ${CERTS_DIR}/server.csr.pem \
                -subj "/CN=localhost"
            
            # Sign server certificate
            openssl x509 -req -sha256 -days 365 \
                -in ${CERTS_DIR}/server.csr.pem \
                -CA ${CERTS_DIR}/ca.pem \
                -CAkey ${CERTS_DIR}/ca.key.pem \
                -CAcreateserial \
                -out ${CERTS_DIR}/server.pem
            
            # Set secure permissions
            chmod 600 ${CERTS_DIR}/*.key.pem
            chmod 644 ${CERTS_DIR}/*.pem
            chown -R ${SYSTEM_USER}:${SYSTEM_GROUP} ${CERTS_DIR}
            
            log_success "Self-signed certificates generated"
            log_warning "NOTE: Self-signed certificates are for testing only. Use proper CA-signed certs in production."
        else
            log_warning "Skipping certificate generation. Please place certificates in ${CERTS_DIR} manually."
        fi
    else
        log_info "  - Certificates already exist"
    fi
}

# Enable and start service
enable_service() {
    echo ""
    read -p "Enable and start the service now? (y/n): " -n 1 -r
    echo ""
    
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        log_info "Enabling service..."
        systemctl enable ${APP_NAME}.service
        
        log_info "Starting service..."
        systemctl start ${APP_NAME}.service
        
        # Check service status
        if systemctl is-active --quiet ${APP_NAME}.service; then
            log_success "Service started successfully"
            systemctl status ${APP_NAME}.service --no-pager
        else
            log_error "Service failed to start. Check logs: journalctl -u ${APP_NAME}"
            exit 1
        fi
    else
        log_info "Service not started. You can start it later with: systemctl start ${APP_NAME}"
    fi
}

# Display installation summary
display_summary() {
    echo ""
    echo -e "${GREEN}========================================${NC}"
    echo -e "${GREEN}  Linux Patch API Installation Complete${NC}"
    echo -e "${GREEN}========================================${NC}"
    echo ""
    echo -e "Version:        ${VERSION}"
    echo -e "Binary:         ${INSTALL_DIR}/${APP_NAME}"
    echo -e "Config:         ${CONFIG_DIR}/config.yaml"
    echo -e "Whitelist:      ${CONFIG_DIR}/whitelist.yaml"
    echo -e "Certificates:   ${CERTS_DIR}/"
    echo -e "Data:           ${DATA_DIR}/"
    echo -e "Logs:           ${LOG_DIR}/"
    echo -e "Service:        ${APP_NAME}.service"
    echo ""
    echo -e "${YELLOW}Next Steps:${NC}"
    echo "  1. Review and configure ${CONFIG_DIR}/config.yaml"
    echo "  2. Configure IP whitelist in ${CONFIG_DIR}/whitelist.yaml"
    echo "  3. Replace self-signed certificates with CA-signed certs for production"
    echo "  4. Start service: systemctl start ${APP_NAME}"
    echo "  5. Check status: systemctl status ${APP_NAME}"
    echo "  6. View logs: journalctl -u ${APP_NAME} -f"
    echo ""
    echo -e "API Endpoint:   https://localhost:12443/api/v1/"
    echo ""
}

# Main installation flow
main() {
    echo ""
    echo -e "${BLUE}========================================${NC}"
    echo -e "${BLUE}  Linux Patch API Installer v${VERSION}${NC}"
    echo -e "${BLUE}========================================${NC}"
    echo ""
    
    check_root
    detect_os
    check_prerequisites
    create_system_user
    create_directories
    install_binary
    install_config
    install_service
    generate_certificates
    enable_service
    display_summary
    
    log_success "Installation completed successfully!"
}

# Run main function
main "$@"
