#!/bin/bash

# stack-assignment-helper.sh - Helper script to analyze and assign Docker stacks to servers
# Author: Shell Repository
# Description: Analyze Docker stacks and suggest server assignments based on patterns

set -e

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

# Configuration
DOCKER_DIR="$HOME/docker"
DEPLOYMENT_CONFIG_DIR="$HOME/.docker-deployment"

# Stack classification patterns
declare -A MEDIA_PATTERNS=(
    ["plex"]="media-server"
    ["jellyfin"]="media-server"
    ["emby"]="media-server"
    ["kodi"]="media-server"
    ["photoprism"]="media-server"
    ["immich"]="media-server"
    ["nextcloud"]="media-server"
)

# Multi-server patterns - stacks that should run on ALL servers
declare -A MULTI_SERVER_PATTERNS=(
    ["dozzle"]="monitoring"
    ["dockge"]="management"
    ["diun"]="monitoring"
    ["watchtower"]="monitoring"
    ["portainer"]="management"
)

declare -A DOWNLOAD_PATTERNS=(
    ["radarr"]="download-server"
    ["sonarr"]="download-server"
    ["lidarr"]="download-server"
    ["readarr"]="download-server"
    ["prowlarr"]="download-server"
    ["sabnzbd"]="download-server"
    ["nzbget"]="download-server"
    ["qbittorrent"]="download-server"
    ["transmission"]="download-server"
    ["deluge"]="download-server"
    ["overseerr"]="download-server"
    ["ombi"]="download-server"
    ["requestrr"]="download-server"
    ["jackett"]="download-server"
    ["metube"]="download-server"
    ["pinchflat"]="download-server"
    ["pdf"]="download-server"
)

declare -A UTILITY_PATTERNS=(
    ["traefik"]="reverse-proxy"
    ["nginx"]="reverse-proxy"
    ["caddy"]="reverse-proxy"
    ["nginxproxymanager"]="reverse-proxy"
    ["grafana"]="monitoring"
    ["prometheus"]="monitoring"
    ["uptime-kuma"]="monitoring"
    ["gatus"]="monitoring"
    ["ntfy"]="monitoring"
    ["adguard"]="security"
    ["portainer"]="management"
    ["watchtower"]="management"
    ["vaultwarden"]="security"
    ["authelia"]="security"
    ["authentik"]="security"
    ["duplicati"]="backup"
    ["restic"]="backup"
    ["database"]="infrastructure"
    ["cloudflare"]="infrastructure"
    ["tclip"]="utility"
    ["opengist"]="utility"
    ["newt"]="utility"
    ["pangolin"]="utility"
    ["omni-tools"]="utility"
    ["golinks"]="utility"
    ["hoarder"]="productivity"
    ["paperless-ng"]="productivity"
    ["docmost"]="productivity"
    ["wiki"]="productivity"
    ["filebrowser"]="productivity"
    ["n8n"]="automation"
)

# Analyze Docker directory structure
analyze_stacks() {
    echo -e "${BLUE}=== Analyzing Docker Stacks ===${NC}"
    echo ""

    if [ ! -d "$DOCKER_DIR" ]; then
        echo -e "${RED}Docker directory not found: $DOCKER_DIR${NC}"
        exit 1
    fi

    local total_stacks=0
    local classified_stacks=0

    # Arrays to store classifications
    local media_stacks=()
    local download_stacks=()
    local utility_stacks=()
    local unclassified_stacks=()

    # Analyze each directory in docker folder
    for stack_dir in "$DOCKER_DIR"/*; do
        if [ -d "$stack_dir" ]; then
            local stack_name=$(basename "$stack_dir")
            total_stacks=$((total_stacks + 1))

            local classification=""
            local suggested_server=""

            # Check against patterns - prioritize multi-server patterns first
            if [[ -n "${MULTI_SERVER_PATTERNS[$stack_name]}" ]]; then
                classification="Multi-Server Tool"
                suggested_server="all-servers"
                utility_stacks+=("$stack_name")
                classified_stacks=$((classified_stacks + 1))
            elif [[ -n "${MEDIA_PATTERNS[$stack_name]}" ]]; then
                classification="Media Server"
                suggested_server="europa"
                media_stacks+=("$stack_name")
                classified_stacks=$((classified_stacks + 1))
            elif [[ -n "${DOWNLOAD_PATTERNS[$stack_name]}" ]]; then
                classification="Download/Acquisition"
                suggested_server="io"
                download_stacks+=("$stack_name")
                classified_stacks=$((classified_stacks + 1))
            elif [[ -n "${UTILITY_PATTERNS[$stack_name]}" ]]; then
                classification="Utility/Monitoring"
                case "${UTILITY_PATTERNS[$stack_name]}" in
                    "reverse-proxy"|"productivity")
                        suggested_server="europa"
                        ;;
                    "monitoring"|"backup"|"security"|"infrastructure")
                        suggested_server="racknerd"
                        ;;
                    "automation"|"utility")
                        suggested_server="io"
                        ;;
                    *)
                        suggested_server="racknerd"
                        ;;
                esac
                utility_stacks+=("$stack_name")
                classified_stacks=$((classified_stacks + 1))
            else
                # Try to classify based on docker-compose.yml content
                local compose_file="$stack_dir/docker-compose.yml"
                if [ -f "$compose_file" ]; then
                    if grep -qi "plex\|jellyfin\|emby\|photoprism\|immich" "$compose_file"; then
                        classification="Media Server (detected)"
                        suggested_server="europa"
                        media_stacks+=("$stack_name")
                        classified_stacks=$((classified_stacks + 1))
                    elif grep -qi "radarr\|sonarr\|sabnzbd\|qbittorrent\|transmission" "$compose_file"; then
                        classification="Download/Acquisition (detected)"
                        suggested_server="io"
                        download_stacks+=("$stack_name")
                        classified_stacks=$((classified_stacks + 1))
                    elif grep -qi "grafana\|prometheus\|monitoring\|uptime" "$compose_file"; then
                        classification="Monitoring (detected)"
                        suggested_server="racknerd"
                        utility_stacks+=("$stack_name")
                        classified_stacks=$((classified_stacks + 1))
                    else
                        classification="Unknown"
                        suggested_server="manual-review"
                        unclassified_stacks+=("$stack_name")
                    fi
                else
                    classification="No compose file"
                    suggested_server="manual-review"
                    unclassified_stacks+=("$stack_name")
                fi
            fi

            # Display analysis
            local status_icon=""
            local server_color=""
            case "$suggested_server" in
                "europa")
                    status_icon="🎬"
                    server_color="$GREEN"
                    ;;
                "io")
                    status_icon="📥"
                    server_color="$BLUE"
                    ;;
                "racknerd")
                    status_icon="🔧"
                    server_color="$YELLOW"
                    ;;
                "all")
                    status_icon="🌐"
                    server_color="$GREEN"
                    ;;
                *)
                    status_icon="❓"
                    server_color="$RED"
                    ;;
            esac

            printf "%-20s %-25s ${server_color}%-10s${NC} %s\n" \
                "$status_icon $stack_name" \
                "$classification" \
                "$suggested_server" \
                "$(check_stack_health "$stack_dir")"
        fi
    done

    echo ""
    echo -e "${BLUE}=== Classification Summary ===${NC}"
    echo "Total stacks found: $total_stacks"
    echo "Classified stacks: $classified_stacks"
    echo "Unclassified stacks: $((total_stacks - classified_stacks))"
    echo ""

    # Show server assignments
    if [ ${#media_stacks[@]} -gt 0 ]; then
        echo -e "${GREEN}🎬 Europa (Media Server):${NC}"
        printf '%s\n' "${media_stacks[@]}" | sed 's/^/  - /'
        echo ""
    fi

    if [ ${#download_stacks[@]} -gt 0 ]; then
        echo -e "${BLUE}📥 IO (Download Server):${NC}"
        printf '%s\n' "${download_stacks[@]}" | sed 's/^/  - /'
        echo ""
    fi

    if [ ${#utility_stacks[@]} -gt 0 ]; then
        echo -e "${YELLOW}🔧 Racknerd (Utility/Backup):${NC}"
        printf '%s\n' "${utility_stacks[@]}" | sed 's/^/  - /'
        echo ""
    fi

    if [ ${#unclassified_stacks[@]} -gt 0 ]; then
        echo -e "${RED}❓ Manual Review Required:${NC}"
        printf '%s\n' "${unclassified_stacks[@]}" | sed 's/^/  - /'
        echo ""
    fi
}

# Check stack health indicators
check_stack_health() {
    local stack_dir="$1"
    local health_indicators=()

    # Check for docker-compose.yml
    if [ -f "$stack_dir/docker-compose.yml" ]; then
        health_indicators+=("compose")
    fi

    # Check for .env files
    if find "$stack_dir" -name "*.env" -o -name ".env*" | grep -q .; then
        health_indicators+=("env")
    fi

    # Check for data/config directories
    if [ -d "$stack_dir/data" ] || [ -d "$stack_dir/config" ]; then
        health_indicators+=("data")
    fi

    # Format output
    if [ ${#health_indicators[@]} -eq 0 ]; then
        echo "⚠️  Incomplete"
    else
        echo "✅ $(IFS=,; echo "${health_indicators[*]}")"
    fi
}

# Generate deployment configuration
generate_deployment_config() {
    echo -e "${YELLOW}Generating deployment configuration...${NC}"

    # Ensure deployment config directory exists
    mkdir -p "$DEPLOYMENT_CONFIG_DIR/stacks"

    # Create individual stack configurations
    for stack_dir in "$DOCKER_DIR"/*; do
        if [ -d "$stack_dir" ]; then
            local stack_name=$(basename "$stack_dir")
            local config_file="$DEPLOYMENT_CONFIG_DIR/stacks/${stack_name}.yml"

            # Determine server assignment
            local server=""
            if [[ -n "${MEDIA_PATTERNS[$stack_name]}" ]]; then
                server="europa"
            elif [[ -n "${DOWNLOAD_PATTERNS[$stack_name]}" ]]; then
                server="io"
            elif [[ -n "${UTILITY_PATTERNS[$stack_name]}" ]]; then
                case "${UTILITY_PATTERNS[$stack_name]}" in
                    "reverse-proxy"|"management")
                        server="europa"
                        ;;
                    *)
                        server="racknerd"
                        ;;
                esac
            elif [[ -n "${MULTI_SERVER_PATTERNS[$stack_name]}" ]]; then
                server="all"
            else
                server="manual-assignment-required"
            fi

            # Generate stack configuration
            cat > "$config_file" << EOF
# Auto-generated stack configuration for $stack_name
name: "$stack_name"
description: "Docker stack for $stack_name"

deployment:
  servers: ["$server"]
  priority: "medium"
  dependencies: []
  restart_policy: "unless-stopped"

health_check:
  enabled: false
  timeout: 30
  retries: 3

backup:
  enabled: true
  schedule: "0 2 * * *"
  retention_days: 7

# Review and customize this configuration as needed
EOF

            echo -e "${GREEN}✓ Generated: $stack_name.yml${NC}"
        fi
    done

    echo ""
    echo -e "${BLUE}Configuration files generated in: $DEPLOYMENT_CONFIG_DIR/stacks/${NC}"
    echo -e "${YELLOW}Please review and customize the generated configurations before deployment.${NC}"
}

# Show resource usage estimates
show_resource_estimates() {
    echo -e "${BLUE}=== Resource Usage Estimates ===${NC}"
    echo ""

    # Define resource estimates for common stacks
    declare -A CPU_ESTIMATES=(
        ["plex"]="2-4"
        ["jellyfin"]="1-3"
        ["radarr"]="0.5-1"
        ["sonarr"]="0.5-1"
        ["sabnzbd"]="1-2"
        ["qbittorrent"]="0.5-2"
        ["grafana"]="0.5-1"
        ["prometheus"]="1-2"
        ["traefik"]="0.5-1"
        ["nextcloud"]="1-2"
    )

    declare -A MEMORY_ESTIMATES=(
        ["plex"]="2-4GB"
        ["jellyfin"]="1-2GB"
        ["radarr"]="256-512MB"
        ["sonarr"]="256-512MB"
        ["sabnzbd"]="512MB-1GB"
        ["qbittorrent"]="256-512MB"
        ["grafana"]="256-512MB"
        ["prometheus"]="512MB-1GB"
        ["traefik"]="128-256MB"
        ["nextcloud"]="512MB-1GB"
    )

    # Aggregate by server
    local europa_cpu=0
    local io_cpu=0
    local racknerd_cpu=0

    for stack_dir in "$DOCKER_DIR"/*; do
        if [ -d "$stack_dir" ]; then
            local stack_name=$(basename "$stack_dir")
            local cpu_est="${CPU_ESTIMATES[$stack_name]:-0.5}"
            local mem_est="${MEMORY_ESTIMATES[$stack_name]:-256MB}"

            # Extract numeric part for aggregation (use lower bound)
            local cpu_num=$(echo "$cpu_est" | cut -d'-' -f1)

            printf "%-20s CPU: %-8s Memory: %-10s\n" "$stack_name" "$cpu_est cores" "$mem_est"
        fi
    done

    echo ""
    echo -e "${YELLOW}Note: These are rough estimates. Actual usage depends on workload and configuration.${NC}"
}

# Suggest optimization opportunities
suggest_optimizations() {
    echo -e "${BLUE}=== Optimization Suggestions ===${NC}"
    echo ""

    echo -e "${GREEN}💡 Recommendations:${NC}"
    echo "1. Co-locate Traefik with media services (Europa) for efficient reverse proxy"
    echo "2. Keep download services (IO) on fast storage for temporary files"
    echo "3. Place monitoring/backup services (Racknerd) on cost-effective hardware"
    echo "4. Consider resource limits in docker-compose.yml files"
    echo "5. Use shared volumes for media access across containers"
    echo ""

    echo -e "${YELLOW}🔧 Integration Points:${NC}"
    echo "1. Integrate with existing backup-env-files.sh for environment management"
    echo "2. Use existing crontab system for deployment automation"
    echo "3. Leverage ntfy notifications for deployment status"
    echo "4. Consider using existing logging infrastructure"
    echo ""
}

# Main function
main() {
    case "${1:-analyze}" in
        analyze|--analyze|-a)
            analyze_stacks
            ;;
        generate|--generate|-g)
            generate_deployment_config
            ;;
        resources|--resources|-r)
            show_resource_estimates
            ;;
        optimize|--optimize|-o)
            suggest_optimizations
            ;;
        all|--all)
            analyze_stacks
            echo ""
            show_resource_estimates
            echo ""
            suggest_optimizations
            ;;
        help|--help|-h)
            echo "Usage: $0 [COMMAND]"
            echo ""
            echo "Commands:"
            echo "  analyze    Analyze and classify Docker stacks (default)"
            echo "  generate   Generate deployment configuration files"
            echo "  resources  Show resource usage estimates"
            echo "  optimize   Show optimization suggestions"
            echo "  all        Run all analysis commands"
            echo "  help       Show this help message"
            ;;
        *)
            echo -e "${RED}Unknown command: $1${NC}"
            echo "Use '$0 help' for usage information"
            exit 1
            ;;
    esac
}

# Run main function
main "$@"
