#!/bin/bash

# First-time Setup Script for Custom PHP Framework Deployment
# Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4
# Usage: ./setup.sh [options]

set -euo pipefail

# Script configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../" && pwd)"
DEPLOYMENT_DIR="${SCRIPT_DIR}"

# Default configuration
INSTALL_DEPENDENCIES=true
SETUP_CONFIGS=true
GENERATE_KEYS=true
VERBOSE=false
SKIP_PROMPTS=false

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

# Logging functions
log() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] ✅ INFO: $1${NC}"
}

warn() {
    echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] ⚠️  WARN: $1${NC}"
}

error() {
    echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ❌ ERROR: $1${NC}"
}

debug() {
    if [ "$VERBOSE" = true ]; then
        echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] 🔍 DEBUG: $1${NC}"
    fi
}

success() {
    echo -e "${WHITE}[$(date +'%Y-%m-%d %H:%M:%S')] 🎉 SUCCESS: $1${NC}"
}

section() {
    echo -e "\n${PURPLE}================================${NC}"
    echo -e "${PURPLE}$1${NC}"
    echo -e "${PURPLE}================================${NC}\n"
}

# Usage information
show_usage() {
    cat << EOF
${WHITE}Custom PHP Framework Deployment Setup${NC}
${CYAN}Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4${NC}

${WHITE}Usage:${NC} $0 [options]

${WHITE}Options:${NC}
    ${YELLOW}--skip-dependencies${NC}     Skip dependency installation
    ${YELLOW}--skip-configs${NC}          Skip configuration setup
    ${YELLOW}--skip-keys${NC}             Skip SSH key generation
    ${YELLOW}--skip-prompts${NC}          Skip interactive prompts (use defaults)
    ${YELLOW}--verbose${NC}               Enable verbose output
    ${YELLOW}-h, --help${NC}              Show this help message

${WHITE}What this script does:${NC}
• Installs required dependencies (Docker, Ansible, etc.)
• Sets up configuration files from templates
• Generates SSH keys for deployment
• Validates the deployment environment
• Prepares the system for first deployment

${WHITE}Examples:${NC}
    ${CYAN}$0${NC}                              # Full setup with prompts
    ${CYAN}$0 --skip-prompts${NC}               # Automated setup
    ${CYAN}$0 --skip-dependencies --verbose${NC} # Setup configs only with debug output

EOF
}

# Parse command line arguments
parse_arguments() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            --skip-dependencies)
                INSTALL_DEPENDENCIES=false
                shift
                ;;
            --skip-configs)
                SETUP_CONFIGS=false
                shift
                ;;
            --skip-keys)
                GENERATE_KEYS=false
                shift
                ;;
            --skip-prompts)
                SKIP_PROMPTS=true
                shift
                ;;
            --verbose)
                VERBOSE=true
                shift
                ;;
            -h|--help)
                show_usage
                exit 0
                ;;
            *)
                error "Unknown argument: $1"
                show_usage
                exit 1
                ;;
        esac
    done
}

# Detect operating system
detect_os() {
    if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        if command -v apt-get >/dev/null 2>&1; then
            OS="ubuntu"
        elif command -v yum >/dev/null 2>&1; then
            OS="centos"
        else
            OS="linux"
        fi
    elif [[ "$OSTYPE" == "darwin"* ]]; then
        OS="macos"
    else
        OS="unknown"
    fi
    
    debug "Detected OS: $OS"
}

# Check if running as root
check_root() {
    if [[ $EUID -eq 0 ]]; then
        warn "Running as root. Some operations may require different permissions."
    fi
}

# Install dependencies based on OS
install_dependencies() {
    if [ "$INSTALL_DEPENDENCIES" = false ]; then
        debug "Skipping dependency installation"
        return 0
    fi
    
    section "INSTALLING DEPENDENCIES"
    
    log "Installing required dependencies for $OS"
    
    case $OS in
        ubuntu)
            log "Updating package lists"
            sudo apt-get update
            
            log "Installing required packages"
            sudo apt-get install -y \
                curl \
                wget \
                git \
                python3 \
                python3-pip \
                software-properties-common \
                apt-transport-https \
                ca-certificates \
                gnupg \
                lsb-release
            
            # Install Docker
            if ! command -v docker >/dev/null 2>&1; then
                log "Installing Docker"
                curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
                echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
                sudo apt-get update
                sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
                
                # Add user to docker group
                sudo usermod -aG docker "$USER"
                warn "You need to log out and back in for Docker permissions to take effect"
            else
                debug "Docker already installed"
            fi
            
            # Install Docker Compose (standalone)
            if ! command -v docker-compose >/dev/null 2>&1; then
                log "Installing Docker Compose"
                sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
                sudo chmod +x /usr/local/bin/docker-compose
            else
                debug "Docker Compose already installed"
            fi
            
            # Install Ansible
            if ! command -v ansible-playbook >/dev/null 2>&1; then
                log "Installing Ansible"
                sudo apt-get install -y ansible
            else
                debug "Ansible already installed"
            fi
            ;;
            
        centos)
            log "Installing required packages for CentOS/RHEL"
            sudo yum update -y
            sudo yum install -y curl wget git python3 python3-pip
            
            # Install Docker
            if ! command -v docker >/dev/null 2>&1; then
                log "Installing Docker"
                sudo yum install -y yum-utils
                sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
                sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
                sudo systemctl start docker
                sudo systemctl enable docker
                sudo usermod -aG docker "$USER"
            else
                debug "Docker already installed"
            fi
            
            # Install Ansible
            if ! command -v ansible-playbook >/dev/null 2>&1; then
                log "Installing Ansible"
                sudo yum install -y epel-release
                sudo yum install -y ansible
            else
                debug "Ansible already installed"
            fi
            ;;
            
        macos)
            if ! command -v brew >/dev/null 2>&1; then
                error "Homebrew not found. Please install Homebrew first:"
                error "https://brew.sh/"
                exit 1
            fi
            
            log "Installing required packages for macOS"
            
            # Install Docker Desktop
            if ! command -v docker >/dev/null 2>&1; then
                log "Installing Docker Desktop"
                brew install --cask docker
                warn "Please start Docker Desktop application manually"
            else
                debug "Docker already installed"
            fi
            
            # Install Docker Compose
            if ! command -v docker-compose >/dev/null 2>&1; then
                log "Installing Docker Compose"
                brew install docker-compose
            else
                debug "Docker Compose already installed"
            fi
            
            # Install Ansible
            if ! command -v ansible-playbook >/dev/null 2>&1; then
                log "Installing Ansible"
                brew install ansible
            else
                debug "Ansible already installed"
            fi
            ;;
            
        *)
            error "Unsupported operating system: $OS"
            error "Please install dependencies manually:"
            error "- Docker (docker.com)"
            error "- Docker Compose"
            error "- Ansible (ansible.com)"
            exit 1
            ;;
    esac
    
    success "Dependencies installation completed"
}

# Verify installations
verify_dependencies() {
    section "VERIFYING DEPENDENCIES"
    
    local all_good=true
    
    # Check Docker
    if command -v docker >/dev/null 2>&1; then
        local docker_version=$(docker --version)
        log "✓ Docker: $docker_version"
        
        # Test Docker without sudo
        if docker ps >/dev/null 2>&1; then
            debug "✓ Docker permissions configured correctly"
        else
            warn "Docker requires sudo. You may need to log out and back in."
        fi
    else
        error "❌ Docker not found"
        all_good=false
    fi
    
    # Check Docker Compose
    if command -v docker-compose >/dev/null 2>&1; then
        local compose_version=$(docker-compose --version)
        log "✓ Docker Compose: $compose_version"
    else
        error "❌ Docker Compose not found"
        all_good=false
    fi
    
    # Check Ansible
    if command -v ansible-playbook >/dev/null 2>&1; then
        local ansible_version=$(ansible --version | head -n1)
        log "✓ Ansible: $ansible_version"
    else
        error "❌ Ansible not found"
        all_good=false
    fi
    
    # Check Python
    if command -v python3 >/dev/null 2>&1; then
        local python_version=$(python3 --version)
        log "✓ Python: $python_version"
    else
        warn "Python3 not found (may be required for some Ansible modules)"
    fi
    
    if [ "$all_good" = false ]; then
        error "Some dependencies are missing. Please install them and run setup again."
        exit 1
    fi
    
    success "All dependencies verified"
}

# Setup configuration files
setup_configuration() {
    if [ "$SETUP_CONFIGS" = false ]; then
        debug "Skipping configuration setup"
        return 0
    fi
    
    section "SETTING UP CONFIGURATION"
    
    # Create environment files from templates
    log "Creating environment configuration files"
    
    local environments=("development" "staging" "production")
    
    for env in "${environments[@]}"; do
        local env_file="${DEPLOYMENT_DIR}/applications/environments/.env.${env}"
        local template_file="${env_file}.template"
        
        if [[ -f "$template_file" ]]; then
            if [[ ! -f "$env_file" ]]; then
                log "Creating .env.${env} from template"
                cp "$template_file" "$env_file"
                
                # Basic substitutions
                if [ "$SKIP_PROMPTS" = false ]; then
                    echo -e "${CYAN}Configuring $env environment:${NC}"
                    
                    # Domain configuration
                    if [ "$env" = "production" ]; then
                        sed -i 's/your-domain\.com/michaelschiemer.de/g' "$env_file"
                        sed -i 's/your-email@example\.com/kontakt@michaelschiemer.de/g' "$env_file"
                    else
                        read -p "Domain for $env (default: ${env}.michaelschiemer.de): " domain
                        domain=${domain:-"${env}.michaelschiemer.de"}
                        sed -i "s/your-domain\.com/$domain/g" "$env_file"
                        sed -i 's/your-email@example\.com/kontakt@michaelschiemer.de/g' "$env_file"
                    fi
                    
                    # Generate random passwords
                    if command -v openssl >/dev/null 2>&1; then
                        local db_password=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
                        local app_key=$(openssl rand -base64 32)
                        
                        sed -i "s/changeme/$db_password/g" "$env_file"
                        sed -i "s/*** REQUIRED - Generate random key ***/$app_key/g" "$env_file"
                        
                        debug "Generated secure passwords for $env"
                    fi
                else
                    # Non-interactive: use defaults
                    if [ "$env" = "production" ]; then
                        sed -i 's/your-domain\.com/michaelschiemer.de/g' "$env_file"
                    else
                        sed -i "s/your-domain\.com/${env}.michaelschiemer.de/g" "$env_file"
                    fi
                    sed -i 's/your-email@example\.com/kontakt@michaelschiemer.de/g' "$env_file"
                    
                    warn "Using default configuration for $env. Review and update manually."
                fi
            else
                debug ".env.${env} already exists"
            fi
        else
            warn "Template not found: $template_file"
        fi
    done
    
    # Set proper permissions
    log "Setting configuration file permissions"
    find "${DEPLOYMENT_DIR}/applications/environments" -name ".env.*" -type f -exec chmod 600 {} \;
    
    # Create necessary directories
    log "Creating necessary directories"
    mkdir -p "${PROJECT_ROOT}/storage/backups"
    mkdir -p "${PROJECT_ROOT}/storage/logs"
    mkdir -p "${DEPLOYMENT_DIR}/infrastructure/logs"
    
    success "Configuration setup completed"
}

# Generate SSH keys for deployment
generate_ssh_keys() {
    if [ "$GENERATE_KEYS" = false ]; then
        debug "Skipping SSH key generation"
        return 0
    fi
    
    section "SETTING UP SSH KEYS"
    
    local ssh_dir="$HOME/.ssh"
    local key_name="michaelschiemer_deploy"
    local private_key="${ssh_dir}/${key_name}"
    local public_key="${private_key}.pub"
    
    if [[ ! -f "$private_key" ]]; then
        log "Generating SSH key pair for deployment"
        
        mkdir -p "$ssh_dir"
        chmod 700 "$ssh_dir"
        
        ssh-keygen -t ed25519 -C "deployment@michaelschiemer.de" -f "$private_key" -N ""
        
        log "SSH key pair generated:"
        log "Private key: $private_key"
        log "Public key: $public_key"
        
        echo -e "\n${YELLOW}📋 IMPORTANT: Add the following public key to your deployment servers:${NC}\n"
        cat "$public_key"
        echo -e "\n${YELLOW}Copy this key to ~/.ssh/authorized_keys on your deployment servers${NC}"
        
        if [ "$SKIP_PROMPTS" = false ]; then
            echo
            read -p "Press Enter when you have added the public key to your servers..."
        fi
    else
        debug "SSH key already exists: $private_key"
        log "Using existing SSH key: $private_key"
    fi
    
    # Add to SSH agent if running
    if pgrep -x "ssh-agent" > /dev/null; then
        log "Adding SSH key to agent"
        ssh-add "$private_key" 2>/dev/null || debug "Key may already be in agent"
    fi
    
    success "SSH key setup completed"
}

# Test deployment environment
test_environment() {
    section "TESTING DEPLOYMENT ENVIRONMENT"
    
    log "Running environment validation tests"
    
    # Test Docker
    log "Testing Docker functionality"
    if docker run --rm hello-world >/dev/null 2>&1; then
        log "✓ Docker test passed"
    else
        warn "Docker test failed - you may need to start Docker or check permissions"
    fi
    
    # Test Docker Compose
    log "Testing Docker Compose functionality"
    cd "$PROJECT_ROOT"
    if docker-compose config >/dev/null 2>&1; then
        log "✓ Docker Compose configuration valid"
    else
        warn "Docker Compose configuration test failed"
    fi
    
    # Test Ansible
    log "Testing Ansible functionality"
    if ansible --version >/dev/null 2>&1; then
        log "✓ Ansible test passed"
    else
        warn "Ansible test failed"
    fi
    
    # Test project structure
    log "Validating project structure"
    local required_files=(
        "docker-compose.yml"
        "deployment/deploy.sh"
        "deployment/Makefile"
        "deployment/applications/docker-compose.production.yml"
        "deployment/infrastructure/site.yml"
    )
    
    local missing_files=()
    for file in "${required_files[@]}"; do
        if [[ ! -f "${PROJECT_ROOT}/${file}" ]]; then
            missing_files+=("$file")
        fi
    done
    
    if [ ${#missing_files[@]} -eq 0 ]; then
        log "✓ All required project files found"
    else
        warn "Missing files:"
        for file in "${missing_files[@]}"; do
            warn "  - $file"
        done
    fi
    
    success "Environment testing completed"
}

# Show setup summary
show_setup_summary() {
    section "SETUP SUMMARY"
    
    cat << EOF
${WHITE}🎉 Custom PHP Framework Deployment Setup Complete! 🎉${NC}

${CYAN}What was configured:${NC}
EOF

    if [ "$INSTALL_DEPENDENCIES" = true ]; then
        echo "• ✅ Dependencies installed (Docker, Ansible, etc.)"
    fi
    
    if [ "$SETUP_CONFIGS" = true ]; then
        echo "• ✅ Configuration files created from templates"
    fi
    
    if [ "$GENERATE_KEYS" = true ]; then
        echo "• ✅ SSH keys generated for deployment"
    fi
    
    cat << EOF

${CYAN}Next Steps:${NC}
1. Review and customize environment configurations:
   ${YELLOW}• deployment/applications/environments/.env.development${NC}
   ${YELLOW}• deployment/applications/environments/.env.staging${NC}
   ${YELLOW}• deployment/applications/environments/.env.production${NC}

2. Configure your deployment servers:
   ${YELLOW}• Add your SSH public key to authorized_keys${NC}
   ${YELLOW}• Update Ansible inventory files if needed${NC}

3. Test your deployment:
   ${YELLOW}make deploy-dry ENV=development${NC}

4. Deploy to staging when ready:
   ${YELLOW}make deploy-staging${NC}

${CYAN}Useful Commands:${NC}
• ${YELLOW}make help${NC}                    # Show all available commands
• ${YELLOW}make status ENV=staging${NC}      # Check deployment status
• ${YELLOW}make deploy-dry ENV=production${NC} # Test production deployment
• ${YELLOW}make info${NC}                    # Show deployment information

${GREEN}🌟 Your Custom PHP Framework deployment system is ready!${NC}
${CYAN}Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4${NC}

EOF
}

# Error handling
cleanup() {
    local exit_code=$?
    
    if [ $exit_code -ne 0 ]; then
        error "Setup failed with exit code: $exit_code"
        echo
        echo -e "${RED}Troubleshooting Tips:${NC}"
        echo "• Check the error messages above for specific issues"
        echo "• Ensure you have sufficient permissions"
        echo "• Try running individual setup steps manually"
        echo "• Check the deployment documentation"
        echo "• Use --verbose flag for more detailed output"
    fi
}

trap cleanup EXIT

# Main setup function
main() {
    log "Starting Custom PHP Framework deployment setup"
    
    detect_os
    check_root
    
    # Setup steps
    install_dependencies
    verify_dependencies
    setup_configuration
    generate_ssh_keys
    test_environment
    
    # Summary
    show_setup_summary
    
    success "Deployment setup completed successfully!"
}

# Script execution
parse_arguments "$@"
main