---
# Service Status Check Playbook
# Get comprehensive status of all services across homelab infrastructure
# Usage: ansible-playbook playbooks/service_status.yml
# Usage with specific host: ansible-playbook playbooks/service_status.yml --limit atlantis

- name: Check Service Status Across Homelab
  hosts: all
  gather_facts: yes
  vars:
    portainer_endpoints:
      atlantis: "https://192.168.0.200:9443"
      calypso: "https://192.168.0.201:9443"
      concord_nuc: "https://192.168.0.202:9443"
      homelab_vm: "https://192.168.0.203:9443"
      rpi5_vish: "https://192.168.0.204:9443"

  tasks:
    - name: Detect system type and environment
      set_fact:
        system_type: >-
          {{
            'synology' if (ansible_system_vendor is defined and 'synology' in ansible_system_vendor | lower) or
                         (ansible_distribution is defined and 'dsm' in ansible_distribution | lower) or
                         (ansible_hostname is defined and ('atlantis' in ansible_hostname or 'calypso' in ansible_hostname))
            else 'container' if ansible_virtualization_type is defined and ansible_virtualization_type in ['docker', 'container']
            else 'standard'
          }}

    - name: Check if Docker is running (Standard Linux with systemd)
      systemd:
        name: docker
      register: docker_status_systemd
      when: system_type == "standard"
      ignore_errors: yes

    - name: Check if Docker is running (Synology DSM)
      shell: |
        # Multiple methods to check Docker on Synology
        if command -v synoservice >/dev/null 2>&1; then
          # Method 1: Use synoservice (DSM 6.x/7.x)
          if synoservice --status pkgctl-Docker 2>/dev/null | grep -q "start\|running"; then
            echo "active"
          elif synoservice --status Docker 2>/dev/null | grep -q "start\|running"; then
            echo "active"
          else
            echo "inactive"
          fi
        elif command -v docker >/dev/null 2>&1; then
          # Method 2: Direct Docker check
          if docker info >/dev/null 2>&1; then
            echo "active"
          else
            echo "inactive"
          fi
        elif [ -f /var/packages/Docker/enabled ]; then
          # Method 3: Check package status file
          echo "active"
        else
          echo "not-found"
        fi
      register: docker_status_synology
      when: system_type == "synology"
      changed_when: false
      ignore_errors: yes

    - name: Check if Docker is running (Container/Other environments)
      shell: |
        if command -v docker >/dev/null 2>&1; then
          if docker info >/dev/null 2>&1; then
            echo "active"
          else
            echo "inactive"
          fi
        else
          echo "not-found"
        fi
      register: docker_status_other
      when: system_type == "container"
      changed_when: false
      ignore_errors: yes

    - name: Set unified Docker status
      set_fact:
        docker_running: >-
          {{
            (docker_status_systemd is defined and docker_status_systemd.status is defined and docker_status_systemd.status.ActiveState == "active") or
            (docker_status_synology is defined and docker_status_synology.stdout is defined and docker_status_synology.stdout == "active") or
            (docker_status_other is defined and docker_status_other.stdout is defined and docker_status_other.stdout == "active")
          }}

    - name: Get Docker container status
      shell: |
        if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
          echo "=== DOCKER CONTAINERS ==="
          # Use simpler format to avoid template issues
          {% raw %}
          docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" 2>/dev/null || echo "Permission denied or no containers"
          {% endraw %}
          echo ""
          echo "=== CONTAINER SUMMARY ==="
          running=$(docker ps -q 2>/dev/null | wc -l)
          total=$(docker ps -aq 2>/dev/null | wc -l)
          echo "Running: $running"
          echo "Total: $total"
        else
          echo "Docker not available or not accessible"
        fi
      register: container_status
      when: docker_running | bool
      changed_when: false
      ignore_errors: yes

    - name: Check system resources
      shell: |
        echo "=== SYSTEM RESOURCES ==="
        echo "CPU Usage: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)%"
        echo "Memory: $(free -h | awk 'NR==2{printf "%.1f%% (%s/%s)", $3*100/$2, $3, $2}')"
        echo "Disk: $(df -h / | awk 'NR==2{printf "%s (%s used)", $5, $3}')"
        echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
      register: system_resources

    - name: Check critical services (Standard Linux)
      systemd:
        name: "{{ item }}"
      register: critical_services_systemd
      loop:
        - docker
        - ssh
        - tailscaled
      when: system_type == "standard"
      ignore_errors: yes

    - name: Check critical services (Synology)
      shell: |
        service_name="{{ item }}"
        case "$service_name" in
          "docker")
            if command -v synoservice >/dev/null 2>&1; then
              if synoservice --status pkgctl-Docker 2>/dev/null | grep -q "start\|running"; then
                echo "active"
              else
                echo "inactive"
              fi
            elif command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
              echo "active"
            else
              echo "inactive"
            fi
            ;;
          "ssh")
            if pgrep -f "sshd" >/dev/null 2>&1; then
              echo "active"
            else
              echo "inactive"
            fi
            ;;
          "tailscaled")
            if pgrep -f "tailscaled" >/dev/null 2>&1; then
              echo "active"
            elif command -v tailscale >/dev/null 2>&1 && tailscale status >/dev/null 2>&1; then
              echo "active"
            else
              echo "inactive"
            fi
            ;;
          *)
            echo "unknown"
            ;;
        esac
      register: critical_services_synology
      loop:
        - docker
        - ssh
        - tailscaled
      when: system_type == "synology"
      changed_when: false
      ignore_errors: yes

    - name: Check critical services (Container/Other)
      shell: |
        service_name="{{ item }}"
        case "$service_name" in
          "docker")
            if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
              echo "active"
            else
              echo "inactive"
            fi
            ;;
          "ssh")
            if pgrep -f "sshd" >/dev/null 2>&1; then
              echo "active"
            else
              echo "inactive"
            fi
            ;;
          "tailscaled")
            if pgrep -f "tailscaled" >/dev/null 2>&1; then
              echo "active"
            elif command -v tailscale >/dev/null 2>&1 && tailscale status >/dev/null 2>&1; then
              echo "active"
            else
              echo "inactive"
            fi
            ;;
          *)
            echo "unknown"
            ;;
        esac
      register: critical_services_other
      loop:
        - docker
        - ssh
        - tailscaled
      when: system_type == "container"
      changed_when: false
      ignore_errors: yes

    - name: Set unified critical services status
      set_fact:
        critical_services: >-
          {{
            critical_services_systemd if critical_services_systemd is defined and not critical_services_systemd.skipped
            else critical_services_synology if critical_services_synology is defined and not critical_services_synology.skipped
            else critical_services_other if critical_services_other is defined and not critical_services_other.skipped
            else {'results': []}
          }}

    - name: Check network connectivity
      shell: |
        echo "=== NETWORK STATUS ==="
        echo "Tailscale Status:"
        tailscale status --json | jq -r '.Self.HostName + " - " + .Self.TailscaleIPs[0]' 2>/dev/null || echo "Tailscale not available"
        echo "Internet Connectivity:"
        ping -c 1 8.8.8.8 >/dev/null 2>&1 && echo "✅ Internet OK" || echo "❌ Internet DOWN"
      register: network_status
      ignore_errors: yes

    - name: Display comprehensive status report
      debug:
        msg: |

          ==========================================
          📊 SERVICE STATUS REPORT - {{ inventory_hostname }}
          ==========================================

          🖥️  SYSTEM INFO:
          - Hostname: {{ ansible_hostname }}
          - OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
          - Uptime: {{ ansible_uptime_seconds | int // 86400 }} days, {{ (ansible_uptime_seconds | int % 86400) // 3600 }} hours

          {{ system_resources.stdout }}

          🐳 DOCKER STATUS:
          {% if docker_running %}
          ✅ Docker is running ({{ system_type }} system)
          {% else %}
          ❌ Docker is not running ({{ system_type }} system)
          {% endif %}

          📦 CONTAINER STATUS:
          {% if container_status.stdout is defined %}
          {{ container_status.stdout }}
          {% else %}
          No containers found or Docker not accessible
          {% endif %}

          🔧 CRITICAL SERVICES:
          {% if critical_services.results is defined %}
          {% for service in critical_services.results %}
          {% if system_type == "standard" and service.status is defined %}
          {% if service.status.ActiveState == "active" %}
          ✅ {{ service.item }}: Running
          {% else %}
          ❌ {{ service.item }}: {{ service.status.ActiveState | default('Unknown') }}
          {% endif %}
          {% else %}
          {% if service.stdout is defined and service.stdout == "active" %}
          ✅ {{ service.item }}: Running
          {% else %}
          ❌ {{ service.item }}: {{ service.stdout | default('Unknown') }}
          {% endif %}
          {% endif %}
          {% endfor %}
          {% else %}
          No service status available
          {% endif %}

          {{ network_status.stdout }}

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

    - name: Generate JSON status report
      copy:
        content: |
          {
            "timestamp": "{{ ansible_date_time.iso8601 }}",
            "hostname": "{{ inventory_hostname }}",
            "system_type": "{{ system_type }}",
            "system": {
              "os": "{{ ansible_distribution }} {{ ansible_distribution_version }}",
              "uptime_days": {{ ansible_uptime_seconds | int // 86400 }},
              "cpu_count": {{ ansible_processor_vcpus }},
              "memory_mb": {{ ansible_memtotal_mb }},
              "docker_status": "{{ 'active' if docker_running else 'inactive' }}"
            },
            "containers": {{ (container_status.stdout_lines | default([])) | to_json }},
            "critical_services": [
              {% if critical_services.results is defined %}
              {% for service in critical_services.results %}
              {
                "name": "{{ service.item }}",
                {% if system_type == "standard" and service.status is defined %}
                "status": "{{ service.status.ActiveState | default('unknown') }}",
                "enabled": {{ service.status.UnitFileState == "enabled" if service.status.UnitFileState is defined else false }}
                {% else %}
                "status": "{{ service.stdout | default('unknown') }}",
                "enabled": {{ (service.stdout is defined and service.stdout == "active") | bool }}
                {% endif %}
              }{% if not loop.last %},{% endif %}
              {% endfor %}
              {% endif %}
            ]
          }
        dest: "/tmp/{{ inventory_hostname }}_status_{{ ansible_date_time.epoch }}.json"
      delegate_to: localhost
      ignore_errors: yes

    - name: Summary message
      debug:
        msg: |
          📋 Status check complete for {{ inventory_hostname }}
          📄 JSON report saved to: /tmp/{{ inventory_hostname }}_status_{{ ansible_date_time.epoch }}.json

          Run with --limit to check specific hosts:
          ansible-playbook playbooks/service_status.yml --limit atlantis
