---
- name: Container Resource Optimization
  hosts: all
  gather_facts: yes
  vars:
    optimization_timestamp: "{{ ansible_date_time.iso8601 }}"
    optimization_report_dir: "/tmp/optimization_reports"
    cpu_threshold_warning: 80
    cpu_threshold_critical: 95
    memory_threshold_warning: 85
    memory_threshold_critical: 95

  tasks:
    - name: Create optimization reports directory
      file:
        path: "{{ optimization_report_dir }}"
        state: directory
        mode: '0755'
      delegate_to: localhost
      run_once: true

    - name: Check if Docker is available
      shell: command -v docker >/dev/null 2>&1
      register: docker_available
      changed_when: false
      ignore_errors: yes

    - name: Skip Docker tasks if not available
      set_fact:
        skip_docker: "{{ docker_available.rc != 0 }}"

    - name: Collect container resource usage
      shell: |
        if ! command -v docker >/dev/null 2>&1; then
          echo "Docker not available"
          exit 0
        fi

        echo "=== CONTAINER RESOURCE USAGE ==="

        # Get current resource usage
        echo "Current Resource Usage:"
        docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}" 2>/dev/null || echo "No running containers"
        echo ""

        # Get container limits
        echo "Container Resource Limits:"
        docker ps --format "{{.Names}}" 2>/dev/null | while read container; do
          if [ -n "$container" ]; then
            echo "Container: $container"

            # CPU limits
            cpu_limit=$(docker inspect "$container" --format '{{.HostConfig.CpuQuota}}' 2>/dev/null)
            cpu_period=$(docker inspect "$container" --format '{{.HostConfig.CpuPeriod}}' 2>/dev/null)
            if [ "$cpu_limit" != "0" ] && [ "$cpu_period" != "0" ]; then
              cpu_cores=$(echo "scale=2; $cpu_limit / $cpu_period" | bc 2>/dev/null || echo "N/A")
              echo "  CPU Limit: $cpu_cores cores"
            else
              echo "  CPU Limit: unlimited"
            fi

            # Memory limits
            mem_limit=$(docker inspect "$container" --format '{{.HostConfig.Memory}}' 2>/dev/null)
            if [ "$mem_limit" != "0" ]; then
              mem_mb=$(echo "scale=0; $mem_limit / 1024 / 1024" | bc 2>/dev/null || echo "N/A")
              echo "  Memory Limit: ${mem_mb}MB"
            else
              echo "  Memory Limit: unlimited"
            fi

            # Restart policy
            restart_policy=$(docker inspect "$container" --format '{{.HostConfig.RestartPolicy.Name}}' 2>/dev/null)
            echo "  Restart Policy: $restart_policy"

            echo ""
          fi
        done
      register: resource_usage
      changed_when: false
      when: not skip_docker

    - name: Analyze resource efficiency
      shell: |
        if ! command -v docker >/dev/null 2>&1; then
          echo "Docker not available"
          exit 0
        fi

        echo "=== RESOURCE EFFICIENCY ANALYSIS ==="

        # Identify resource-heavy containers
        echo "High Resource Usage Containers:"
        docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
          if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
            cpu_num=$(echo "$cpu" | sed 's/%//' | cut -d'.' -f1)
            mem_num=$(echo "$mem" | sed 's/%//' | cut -d'.' -f1)

            if [ "$cpu_num" -gt "{{ cpu_threshold_warning }}" ] 2>/dev/null || [ "$mem_num" -gt "{{ memory_threshold_warning }}" ] 2>/dev/null; then
              echo "⚠️  $container - CPU: $cpu, Memory: $mem"
            fi
          fi
        done
        echo ""

        # Check for containers without limits
        echo "Containers Without Resource Limits:"
        docker ps --format "{{.Names}}" 2>/dev/null | while read container; do
          if [ -n "$container" ]; then
            cpu_limit=$(docker inspect "$container" --format '{{.HostConfig.CpuQuota}}' 2>/dev/null)
            mem_limit=$(docker inspect "$container" --format '{{.HostConfig.Memory}}' 2>/dev/null)

            if [ "$cpu_limit" = "0" ] && [ "$mem_limit" = "0" ]; then
              echo "⚠️  $container - No CPU or memory limits"
            elif [ "$cpu_limit" = "0" ]; then
              echo "⚠️  $container - No CPU limit"
            elif [ "$mem_limit" = "0" ]; then
              echo "⚠️  $container - No memory limit"
            fi
          fi
        done
        echo ""

        # Identify idle containers
        echo "Low Usage Containers (potential over-provisioning):"
        docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
          if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
            cpu_num=$(echo "$cpu" | sed 's/%//' | cut -d'.' -f1)
            mem_num=$(echo "$mem" | sed 's/%//' | cut -d'.' -f1)

            if [ "$cpu_num" -lt "5" ] 2>/dev/null && [ "$mem_num" -lt "10" ] 2>/dev/null; then
              echo "💡 $container - CPU: $cpu, Memory: $mem (consider downsizing)"
            fi
          fi
        done
      register: efficiency_analysis
      changed_when: false
      when: not skip_docker

    - name: System resource analysis
      shell: |
        echo "=== SYSTEM RESOURCE ANALYSIS ==="

        # Overall system resources
        echo "System Resources:"
        echo "CPU Cores: $(nproc)"
        echo "Total Memory: $(free -h | awk 'NR==2{print $2}')"
        echo "Available Memory: $(free -h | awk 'NR==2{print $7}')"
        echo "Memory Usage: $(free | awk 'NR==2{printf "%.1f%%", $3*100/$2}')"
        echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
        echo ""

        # Docker system resource usage
        if command -v docker >/dev/null 2>&1; then
          echo "Docker System Usage:"
          docker system df 2>/dev/null || echo "Docker system info not available"
          echo ""

          # Count containers by status
          echo "Container Status Summary:"
          echo "Running: $(docker ps -q 2>/dev/null | wc -l)"
          echo "Stopped: $(docker ps -aq --filter status=exited 2>/dev/null | wc -l)"
          echo "Total: $(docker ps -aq 2>/dev/null | wc -l)"
        fi
        echo ""

        # Disk usage for Docker
        if [ -d "/var/lib/docker" ]; then
          echo "Docker Storage Usage:"
          du -sh /var/lib/docker 2>/dev/null || echo "Docker storage info not accessible"
        fi
      register: system_analysis
      changed_when: false

    - name: Generate optimization recommendations
      shell: |
        echo "=== OPTIMIZATION RECOMMENDATIONS ==="

        # System-level recommendations
        total_mem_mb=$(free -m | awk 'NR==2{print $2}')
        used_mem_mb=$(free -m | awk 'NR==2{print $3}')
        mem_usage_percent=$(echo "scale=1; $used_mem_mb * 100 / $total_mem_mb" | bc 2>/dev/null || echo "0")

        echo "System Recommendations:"
        if [ "$(echo "$mem_usage_percent > 85" | bc 2>/dev/null)" = "1" ]; then
          echo "🚨 High memory usage (${mem_usage_percent}%) - consider adding RAM or optimizing containers"
        elif [ "$(echo "$mem_usage_percent > 70" | bc 2>/dev/null)" = "1" ]; then
          echo "⚠️  Moderate memory usage (${mem_usage_percent}%) - monitor closely"
        else
          echo "✅ Memory usage acceptable (${mem_usage_percent}%)"
        fi

        # Load average check
        load_1min=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | xargs)
        cpu_cores=$(nproc)
        if [ "$(echo "$load_1min > $cpu_cores" | bc 2>/dev/null)" = "1" ]; then
          echo "🚨 High CPU load ($load_1min) exceeds core count ($cpu_cores)"
        else
          echo "✅ CPU load acceptable ($load_1min for $cpu_cores cores)"
        fi
        echo ""

        # Docker-specific recommendations
        if command -v docker >/dev/null 2>&1; then
          echo "Container Recommendations:"

          # Check for containers without health checks
          echo "Containers without health checks:"
          docker ps --format "{{.Names}}" 2>/dev/null | while read container; do
            if [ -n "$container" ]; then
              health_check=$(docker inspect "$container" --format '{{.Config.Healthcheck}}' 2>/dev/null)
              if [ "$health_check" = "<nil>" ] || [ -z "$health_check" ]; then
                echo "💡 $container - Consider adding health check"
              fi
            fi
          done
          echo ""

          # Check for old images
          echo "Image Optimization:"
          old_images=$(docker images --filter "dangling=true" -q 2>/dev/null | wc -l)
          if [ "$old_images" -gt "0" ]; then
            echo "🧹 $old_images dangling images found - run 'docker image prune'"
          fi

          unused_volumes=$(docker volume ls --filter "dangling=true" -q 2>/dev/null | wc -l)
          if [ "$unused_volumes" -gt "0" ]; then
            echo "🧹 $unused_volumes unused volumes found - run 'docker volume prune'"
          fi
        fi
      register: recommendations
      changed_when: false

    - name: Create optimization report
      set_fact:
        optimization_report:
          timestamp: "{{ optimization_timestamp }}"
          hostname: "{{ inventory_hostname }}"
          docker_available: "{{ not skip_docker }}"
          resource_usage: "{{ resource_usage.stdout if not skip_docker else 'Docker not available' }}"
          efficiency_analysis: "{{ efficiency_analysis.stdout if not skip_docker else 'Docker not available' }}"
          system_analysis: "{{ system_analysis.stdout }}"
          recommendations: "{{ recommendations.stdout }}"

    - name: Display optimization report
      debug:
        msg: |

          ==========================================
          ⚡ RESOURCE OPTIMIZATION - {{ inventory_hostname }}
          ==========================================

          📊 DOCKER AVAILABLE: {{ 'Yes' if optimization_report.docker_available else 'No' }}

          🔍 RESOURCE USAGE:
          {{ optimization_report.resource_usage }}

          📈 EFFICIENCY ANALYSIS:
          {{ optimization_report.efficiency_analysis }}

          🖥️  SYSTEM ANALYSIS:
          {{ optimization_report.system_analysis }}

          💡 RECOMMENDATIONS:
          {{ optimization_report.recommendations }}

          ==========================================

    - name: Generate JSON optimization report
      copy:
        content: |
          {
            "timestamp": "{{ optimization_report.timestamp }}",
            "hostname": "{{ optimization_report.hostname }}",
            "docker_available": {{ optimization_report.docker_available | lower }},
            "resource_usage": {{ optimization_report.resource_usage | to_json }},
            "efficiency_analysis": {{ optimization_report.efficiency_analysis | to_json }},
            "system_analysis": {{ optimization_report.system_analysis | to_json }},
            "recommendations": {{ optimization_report.recommendations | to_json }},
            "optimization_actions": [
              "Review containers without resource limits",
              "Monitor high-usage containers for optimization opportunities",
              "Consider downsizing low-usage containers",
              "Implement health checks for better reliability",
              "Regular cleanup of unused images and volumes"
            ]
          }
        dest: "{{ optimization_report_dir }}/{{ inventory_hostname }}_optimization_{{ ansible_date_time.epoch }}.json"
      delegate_to: localhost

    - name: Apply optimizations (when optimize_action is specified)
      block:
        - name: Validate optimization action
          fail:
            msg: "Invalid action. Supported actions: cleanup, restart_high_usage, add_limits"
          when: optimize_action not in ['cleanup', 'restart_high_usage', 'add_limits']

        - name: Execute optimization action
          shell: |
            case "{{ optimize_action }}" in
              "cleanup")
                echo "Performing Docker cleanup..."
                docker image prune -f 2>/dev/null || echo "Image prune failed"
                docker volume prune -f 2>/dev/null || echo "Volume prune failed"
                docker container prune -f 2>/dev/null || echo "Container prune failed"
                echo "Cleanup completed"
                ;;
              "restart_high_usage")
                echo "Restarting high CPU/memory usage containers..."
                docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemPerc}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
                  if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
                    cpu_num=$(echo "$cpu" | sed 's/%//' | cut -d'.' -f1)
                    mem_num=$(echo "$mem" | sed 's/%//' | cut -d'.' -f1)

                    if [ "$cpu_num" -gt "{{ cpu_threshold_critical }}" ] 2>/dev/null || [ "$mem_num" -gt "{{ memory_threshold_critical }}" ] 2>/dev/null; then
                      echo "Restarting high-usage container: $container (CPU: $cpu, Memory: $mem)"
                      docker restart "$container" 2>/dev/null || echo "Failed to restart $container"
                    fi
                  fi
                done
                ;;
              "add_limits")
                echo "Adding resource limits requires manual Docker Compose file updates"
                echo "Recommended limits based on current usage:"
                docker stats --no-stream --format "{{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" 2>/dev/null | while IFS=$'\t' read container cpu mem; do
                  if [ -n "$container" ] && [ "$container" != "CONTAINER" ]; then
                    echo "$container:"
                    echo "  deploy:"
                    echo "    resources:"
                    echo "      limits:"
                    echo "        cpus: '1.0'  # Adjust based on usage: $cpu"
                    echo "        memory: 512M  # Adjust based on usage: $mem"
                    echo ""
                  fi
                done
                ;;
            esac
          register: optimization_action_result
          when: not skip_docker

        - name: Display optimization action result
          debug:
            msg: |

              ⚡ Optimization action '{{ optimize_action }}' completed on {{ inventory_hostname }}

              Result:
              {{ optimization_action_result.stdout }}

              {% if optimization_action_result.stderr %}
              Errors:
              {{ optimization_action_result.stderr }}
              {% endif %}

      when: optimize_action is defined and not skip_docker

    - name: Summary message
      debug:
        msg: |

          ⚡ Resource optimization analysis complete for {{ inventory_hostname }}
          📄 Report saved to: {{ optimization_report_dir }}/{{ inventory_hostname }}_optimization_{{ ansible_date_time.epoch }}.json

          {% if optimize_action is defined %}
          🔧 Action performed: {{ optimize_action }}
          {% endif %}

          💡 Use -e optimize_action=<action> for optimization operations
          💡 Supported actions: cleanup, restart_high_usage, add_limits
          💡 Monitor resource usage regularly for optimal performance
