#!/usr/bin/env bash
# Local Development Environment Cleanup Script
# This script removes all resources created by the local development example

set -euo pipefail

# 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
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SETTINGS_FILE="${SCRIPT_DIR}/settings.ncl"
FORCE_CLEANUP=false
KEEP_DATA=false

# Function to print colored output
print_status() {
    local color=$1
    local message=$2
    echo -e "${color}${message}${NC}"
}

print_step() {
    print_status $BLUE "🔄 $1"
}

print_success() {
    print_status $GREEN "✅ $1"
}

print_warning() {
    print_status $YELLOW "⚠️  $1"
}

print_error() {
    print_status $RED "❌ $1"
}

# Function to show usage information
show_usage() {
    cat << EOF
Local Development Environment Cleanup Script

Usage: $0 [OPTIONS]

OPTIONS:
    --force, -f         Force cleanup without confirmation
    --keep-data, -k     Keep data volumes and databases
    --help, -h          Show this help message

EXAMPLES:
    $0                      Clean up with confirmation prompts
    $0 --force              Clean up everything without asking
    $0 --keep-data          Clean up but preserve databases and files
    $0 -f -k                Force cleanup but keep data

WHAT WILL BE CLEANED UP:
    • All servers (web-dev-01, db-dev-01)
    • All installed task services
    • Network configuration
    • Temporary files and caches
    • Container images (if using containers)

DATA PRESERVATION:
    With --keep-data flag:
    • Database files will be preserved
    • Web content in /var/www will be preserved
    • User data in home directories will be preserved

For more information, see README.md
EOF
}

# Function to confirm cleanup
confirm_cleanup() {
    if [ "$FORCE_CLEANUP" = true ]; then
        return 0
    fi

    echo
    print_warning "This will remove all resources created by the local development example:"
    echo "   • Servers: web-dev-01, db-dev-01"
    echo "   • Services: nginx, postgresql, redis, nodejs, containerd"
    echo "   • Network configuration"
    echo "   • Temporary files"

    if [ "$KEEP_DATA" = false ]; then
        print_warning "Data will be PERMANENTLY DELETED:"
        echo "   • Database files and content"
        echo "   • Web server files"
        echo "   • Application data"
    else
        print_status $GREEN "Data will be preserved (--keep-data flag specified)"
    fi

    echo
    read -p "Are you sure you want to proceed? (y/N): " -n 1 -r
    echo

    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        print_status $BLUE "Cleanup cancelled by user"
        exit 0
    fi
}

# Function to check if environment exists
check_environment_exists() {
    print_step "Checking if environment exists..."

    if ! provisioning server list --settings "$SETTINGS_FILE" &>/dev/null; then
        print_warning "No servers found or environment doesn't exist"
        return 1
    fi

    local server_count
    server_count=$(provisioning server list --settings "$SETTINGS_FILE" --out json 2>/dev/null | jq '. | length' 2>/dev/null || echo "0")

    if [ "$server_count" -eq 0 ]; then
        print_warning "No servers found in this environment"
        return 1
    fi

    print_success "Found $server_count servers to clean up"
    return 0
}

# Function to backup data before cleanup
backup_data() {
    if [ "$KEEP_DATA" = false ]; then
        return 0
    fi

    print_step "Creating data backup before cleanup..."

    local backup_dir="${SCRIPT_DIR}/backup-$(date +%Y%m%d_%H%M%S)"
    mkdir -p "$backup_dir"

    # Backup database data
    print_step "Backing up database data..."
    if provisioning server ssh db-dev-01 --settings "$SETTINGS_FILE" --command "pg_dumpall -U postgres" > "$backup_dir/databases.sql" 2>/dev/null; then
        print_success "Database backup created: $backup_dir/databases.sql"
    else
        print_warning "Could not backup databases"
    fi

    # Backup web content
    print_step "Backing up web content..."
    if provisioning server copy db-dev-01:/var/www/ "$backup_dir/www/" --settings "$SETTINGS_FILE" &>/dev/null; then
        print_success "Web content backup created: $backup_dir/www/"
    else
        print_warning "Could not backup web content"
    fi

    print_success "Backup completed in: $backup_dir"
}

# Function to stop services gracefully
stop_services() {
    print_step "Stopping services gracefully..."

    local services=("nginx" "postgresql" "redis" "containerd")

    for service in "${services[@]}"; do
        print_step "Stopping $service..."

        # Try to stop service on all servers
        for server in web-dev-01 db-dev-01; do
            if provisioning server ssh "$server" --settings "$SETTINGS_FILE" --command "sudo systemctl stop $service" &>/dev/null; then
                print_success "$service stopped on $server"
            else
                print_warning "$service stop failed or not installed on $server"
            fi
        done
    done

    print_success "Services stopped"
}

# Function to remove task services
remove_task_services() {
    print_step "Removing task services..."

    # Get list of installed services
    local installed_services
    if installed_services=$(provisioning taskserv list --settings "$SETTINGS_FILE" --installed --out json 2>/dev/null); then
        local service_names
        service_names=$(echo "$installed_services" | jq -r '.[].name' 2>/dev/null || echo "")

        if [ -n "$service_names" ]; then
            echo "Removing services: $service_names"

            # Remove each service
            while IFS= read -r service; do
                if [ -n "$service" ]; then
                    print_step "Removing service: $service"

                    local remove_args=(
                        "taskserv" "delete" "$service"
                        "--settings" "$SETTINGS_FILE"
                        "--yes"
                    )

                    if [ "$KEEP_DATA" = false ]; then
                        remove_args+=("--cleanup-data")
                    fi

                    if provisioning "${remove_args[@]}" &>/dev/null; then
                        print_success "Service $service removed"
                    else
                        print_warning "Failed to remove service $service"
                    fi
                fi
            done <<< "$service_names"
        else
            print_success "No services to remove"
        fi
    else
        print_warning "Could not retrieve installed services list"
    fi

    print_success "Task service cleanup completed"
}

# Function to remove servers
remove_servers() {
    print_step "Removing servers..."

    local remove_args=(
        "server" "delete"
        "--settings" "$SETTINGS_FILE"
        "--yes"
    )

    if [ "$KEEP_DATA" = true ]; then
        remove_args+=("--keepstorage")
    fi

    if provisioning "${remove_args[@]}"; then
        print_success "Servers removed successfully"
    else
        print_error "Failed to remove servers"
        return 1
    fi
}

# Function to clean up container resources
cleanup_containers() {
    print_step "Cleaning up container resources..."

    # Only attempt container cleanup if Docker is available
    if command -v docker &>/dev/null && docker ps &>/dev/null 2>&1; then
        print_step "Cleaning up Docker containers and images..."

        # Stop any running containers related to this project
        local containers
        containers=$(docker ps -aq --filter "label=provisioning.project=local-development" 2>/dev/null || echo "")

        if [ -n "$containers" ]; then
            print_step "Stopping development containers..."
            docker stop $containers &>/dev/null || true
            docker rm $containers &>/dev/null || true
            print_success "Development containers cleaned up"
        fi

        # Clean up unused images (optional, only if forced)
        if [ "$FORCE_CLEANUP" = true ]; then
            print_step "Cleaning up unused Docker images..."
            docker image prune -f &>/dev/null || true
            print_success "Unused Docker images cleaned up"
        fi

    elif command -v podman &>/dev/null; then
        print_step "Cleaning up Podman containers..."

        # Similar cleanup for Podman
        local containers
        containers=$(podman ps -aq --filter "label=provisioning.project=local-development" 2>/dev/null || echo "")

        if [ -n "$containers" ]; then
            print_step "Stopping development containers..."
            podman stop $containers &>/dev/null || true
            podman rm $containers &>/dev/null || true
            print_success "Development containers cleaned up"
        fi

    else
        print_success "No container runtime found, skipping container cleanup"
    fi
}

# Function to clean up temporary files
cleanup_temp_files() {
    print_step "Cleaning up temporary files..."

    # Clean up local temporary files
    local temp_patterns=(
        "${SCRIPT_DIR}/.provisioning-*"
        "${SCRIPT_DIR}/infrastructure/.cache"
        "/tmp/provisioning-local-*"
        "/var/tmp/provisioning-local-*"
    )

    for pattern in "${temp_patterns[@]}"; do
        if ls $pattern &>/dev/null; then
            rm -rf $pattern
            print_success "Cleaned up: $pattern"
        fi
    done

    # Clean up SSH known hosts entries for local servers
    if [ -f ~/.ssh/known_hosts ]; then
        sed -i.bak '/^192\.168\.100\./d' ~/.ssh/known_hosts 2>/dev/null || true
        print_success "Cleaned up SSH known hosts"
    fi

    print_success "Temporary files cleaned up"
}

# Function to verify cleanup completion
verify_cleanup() {
    print_step "Verifying cleanup completion..."

    local cleanup_issues=0

    # Check if servers still exist
    local remaining_servers
    remaining_servers=$(provisioning server list --settings "$SETTINGS_FILE" --out json 2>/dev/null | jq '. | length' 2>/dev/null || echo "0")

    if [ "$remaining_servers" -eq 0 ]; then
        print_success "All servers removed"
    else
        print_error "$remaining_servers servers still exist"
        ((cleanup_issues++))
    fi

    # Check if services still exist
    local remaining_services
    remaining_services=$(provisioning taskserv list --settings "$SETTINGS_FILE" --installed --out json 2>/dev/null | jq '. | length' 2>/dev/null || echo "0")

    if [ "$remaining_services" -eq 0 ]; then
        print_success "All services removed"
    else
        print_error "$remaining_services services still installed"
        ((cleanup_issues++))
    fi

    # Check container status
    if command -v docker &>/dev/null; then
        local running_containers
        running_containers=$(docker ps -q --filter "label=provisioning.project=local-development" 2>/dev/null | wc -l)

        if [ "$running_containers" -eq 0 ]; then
            print_success "No development containers running"
        else
            print_warning "$running_containers development containers still running"
        fi
    fi

    if [ $cleanup_issues -eq 0 ]; then
        return 0
    else
        return 1
    fi
}

# Function to show cleanup summary
show_cleanup_summary() {
    echo
    print_status $BLUE "🧹 Cleanup Summary"
    print_status $BLUE "=================="

    if [ "$KEEP_DATA" = true ]; then
        print_status $GREEN "✅ Infrastructure removed, data preserved"
        echo "   • Servers and services have been removed"
        echo "   • Database files and web content preserved"
        echo "   • Backup created in: backup-* directory"
    else
        print_status $GREEN "✅ Complete cleanup performed"
        echo "   • All servers and services removed"
        echo "   • All data and temporary files cleaned up"
        echo "   • Container resources cleaned up"
    fi

    echo
    print_status $BLUE "📚 Next steps:"
    echo "   • Try other examples in ../../"
    echo "   • Read about more advanced deployments"
    echo "   • Set up a cloud-based environment"

    if [ "$KEEP_DATA" = true ]; then
        echo "   • Restore data when setting up again: use backup files"
    fi

    echo
    print_status $BLUE "🔄 To redeploy:"
    echo "   • Run ./deploy.sh to create the environment again"
    echo "   • All configurations are preserved in settings.ncl"
    echo
}

# Main cleanup function
main() {
    local start_time=$(date +%s)

    print_status $BLUE "🧹 Local Development Environment Cleanup"
    print_status $BLUE "========================================"
    echo

    # Parse command line arguments
    while [[ $# -gt 0 ]]; do
        case $1 in
            --force|-f)
                FORCE_CLEANUP=true
                shift
                ;;
            --keep-data|-k)
                KEEP_DATA=true
                shift
                ;;
            --help|-h)
                show_usage
                exit 0
                ;;
            *)
                print_error "Unknown option: $1"
                show_usage
                exit 1
                ;;
        esac
    done

    # Set environment
    export PROVISIONING_ENV=development

    # Check if there's anything to clean up
    if ! check_environment_exists; then
        print_status $GREEN "Nothing to clean up - environment doesn't exist or is already clean"
        exit 0
    fi

    # Confirm cleanup unless forced
    confirm_cleanup

    # Backup data if requested
    if [ "$KEEP_DATA" = true ]; then
        backup_data
    fi

    # Perform cleanup steps
    print_step "Starting cleanup process..."

    stop_services
    remove_task_services
    remove_servers
    cleanup_containers
    cleanup_temp_files

    # Verify cleanup
    if verify_cleanup; then
        print_success "Cleanup verification passed"
    else
        print_warning "Some cleanup issues detected - check output above"
    fi

    local end_time=$(date +%s)
    local duration=$((end_time - start_time))

    show_cleanup_summary

    print_success "Cleanup completed in ${duration} seconds"
}

# Error handling
trap 'print_error "Cleanup script encountered an error"; exit 1' ERR

# Run main function
main "$@"
