---
- name: Tailscale Network Management
  hosts: all
  gather_facts: yes
  vars:
    tailscale_timestamp: "{{ ansible_date_time.iso8601 }}"
    tailscale_report_dir: "/tmp/tailscale_reports"

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

    - name: Check if Tailscale is installed
      shell: command -v tailscale >/dev/null 2>&1
      register: tailscale_available
      changed_when: false
      ignore_errors: yes

    - name: Skip Tailscale tasks if not available
      set_fact:
        skip_tailscale: "{{ tailscale_available.rc != 0 }}"

    - name: Get Tailscale status
      shell: |
        if ! command -v tailscale >/dev/null 2>&1; then
          echo "Tailscale not installed"
          exit 0
        fi

        echo "=== TAILSCALE STATUS ==="
        tailscale status --json 2>/dev/null || tailscale status 2>/dev/null || echo "Tailscale not accessible"
      register: tailscale_status
      changed_when: false
      when: not skip_tailscale

    - name: Get Tailscale network information
      shell: |
        if ! command -v tailscale >/dev/null 2>&1; then
          echo "Tailscale not installed"
          exit 0
        fi

        echo "=== TAILSCALE NETWORK INFO ==="

        # Get IP addresses
        echo "Tailscale IPs:"
        tailscale ip -4 2>/dev/null || echo "IPv4 not available"
        tailscale ip -6 2>/dev/null || echo "IPv6 not available"
        echo ""

        # Get peer information
        echo "Peer Status:"
        tailscale status --peers 2>/dev/null || echo "Peer status not available"
        echo ""

        # Get routes
        echo "Routes:"
        tailscale status --self=false 2>/dev/null | grep -E "^[0-9]" | head -10 || echo "Route information not available"
        echo ""

        # Check connectivity to key peers
        echo "Connectivity Tests:"
        key_peers="100.83.230.112 100.103.48.78 100.125.0.20"  # atlantis, calypso, setillo
        for peer in $key_peers; do
          if ping -c 1 -W 2 "$peer" >/dev/null 2>&1; then
            echo "✅ $peer - reachable"
          else
            echo "❌ $peer - unreachable"
          fi
        done
      register: tailscale_network
      changed_when: false
      when: not skip_tailscale
      ignore_errors: yes

    - name: Check Tailscale service health
      shell: |
        if ! command -v tailscale >/dev/null 2>&1; then
          echo "Tailscale not installed"
          exit 0
        fi

        echo "=== TAILSCALE SERVICE HEALTH ==="

        # Check daemon status
        if command -v systemctl >/dev/null 2>&1; then
          echo "Service Status:"
          systemctl is-active tailscaled 2>/dev/null || echo "tailscaled service status unknown"
          systemctl is-enabled tailscaled 2>/dev/null || echo "tailscaled service enablement unknown"
          echo ""
        fi

        # Check authentication status
        echo "Authentication:"
        if tailscale status --json 2>/dev/null | grep -q '"BackendState":"Running"'; then
          echo "✅ Authenticated and running"
        elif tailscale status 2>/dev/null | grep -q "Logged out"; then
          echo "❌ Not logged in"
        else
          echo "⚠️  Status unclear"
        fi
        echo ""

        # Check for exit node status
        echo "Exit Node Status:"
        if tailscale status --json 2>/dev/null | grep -q '"ExitNodeID"'; then
          echo "Using exit node"
        else
          echo "Not using exit node"
        fi
        echo ""

        # Check MagicDNS
        echo "MagicDNS:"
        if tailscale status --json 2>/dev/null | grep -q '"MagicDNSSuffix"'; then
          suffix=$(tailscale status --json 2>/dev/null | grep -o '"MagicDNSSuffix":"[^"]*"' | cut -d'"' -f4)
          echo "✅ Enabled (suffix: $suffix)"
        else
          echo "❌ Disabled or not available"
        fi
      register: tailscale_health
      changed_when: false
      when: not skip_tailscale

    - name: Analyze Tailscale configuration
      shell: |
        if ! command -v tailscale >/dev/null 2>&1; then
          echo "Tailscale not installed"
          exit 0
        fi

        echo "=== TAILSCALE CONFIGURATION ==="

        # Get preferences
        echo "Preferences:"
        tailscale debug prefs 2>/dev/null | head -20 || echo "Preferences not accessible"
        echo ""

        # Check for subnet routes
        echo "Subnet Routes:"
        tailscale status --json 2>/dev/null | grep -o '"AdvertiseRoutes":\[[^\]]*\]' || echo "No advertised routes"
        echo ""

        # Check ACL status (if accessible)
        echo "ACL Information:"
        tailscale debug netmap 2>/dev/null | grep -i acl | head -5 || echo "ACL information not accessible"
        echo ""

        # Check for Tailscale SSH
        echo "Tailscale SSH:"
        if tailscale status --json 2>/dev/null | grep -q '"SSH"'; then
          echo "SSH feature available"
        else
          echo "SSH feature not detected"
        fi
      register: tailscale_config
      changed_when: false
      when: not skip_tailscale
      ignore_errors: yes

    - name: Tailscale network diagnostics
      shell: |
        if ! command -v tailscale >/dev/null 2>&1; then
          echo "Tailscale not installed"
          exit 0
        fi

        echo "=== NETWORK DIAGNOSTICS ==="

        # Check DERP (relay) connectivity
        echo "DERP Connectivity:"
        tailscale netcheck 2>/dev/null | head -10 || echo "Network check not available"
        echo ""

        # Check for direct connections
        echo "Direct Connections:"
        tailscale status --json 2>/dev/null | grep -o '"CurAddr":"[^"]*"' | head -5 || echo "Connection info not available"
        echo ""

        # Interface information
        echo "Network Interfaces:"
        ip addr show tailscale0 2>/dev/null || echo "Tailscale interface not found"
        echo ""

        # Routing table
        echo "Tailscale Routes:"
        ip route show | grep tailscale0 2>/dev/null || echo "No Tailscale routes found"
      register: tailscale_diagnostics
      changed_when: false
      when: not skip_tailscale
      ignore_errors: yes

    - name: Create Tailscale report
      set_fact:
        tailscale_report:
          timestamp: "{{ tailscale_timestamp }}"
          hostname: "{{ inventory_hostname }}"
          tailscale_available: "{{ not skip_tailscale }}"
          status: "{{ tailscale_status.stdout if not skip_tailscale else 'Not available' }}"
          network: "{{ tailscale_network.stdout if not skip_tailscale else 'Not available' }}"
          health: "{{ tailscale_health.stdout if not skip_tailscale else 'Not available' }}"
          configuration: "{{ tailscale_config.stdout if not skip_tailscale else 'Not available' }}"
          diagnostics: "{{ tailscale_diagnostics.stdout if not skip_tailscale else 'Not available' }}"

    - name: Display Tailscale report
      debug:
        msg: |

          ==========================================
          🌐 TAILSCALE REPORT - {{ inventory_hostname }}
          ==========================================

          📊 AVAILABILITY: {{ 'Available' if tailscale_report.tailscale_available else 'Not Available' }}

          📡 STATUS:
          {{ tailscale_report.status }}

          🔗 NETWORK INFO:
          {{ tailscale_report.network }}

          🏥 HEALTH CHECK:
          {{ tailscale_report.health }}

          ⚙️  CONFIGURATION:
          {{ tailscale_report.configuration }}

          🔍 DIAGNOSTICS:
          {{ tailscale_report.diagnostics }}

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

    - name: Generate JSON Tailscale report
      copy:
        content: |
          {
            "timestamp": "{{ tailscale_report.timestamp }}",
            "hostname": "{{ tailscale_report.hostname }}",
            "tailscale_available": {{ tailscale_report.tailscale_available | lower }},
            "status": {{ tailscale_report.status | to_json }},
            "network": {{ tailscale_report.network | to_json }},
            "health": {{ tailscale_report.health | to_json }},
            "configuration": {{ tailscale_report.configuration | to_json }},
            "diagnostics": {{ tailscale_report.diagnostics | to_json }},
            "recommendations": [
              {% if not tailscale_report.tailscale_available %}
              "Install Tailscale for network connectivity",
              {% endif %}
              {% if 'Not logged in' in tailscale_report.health %}
              "Authenticate Tailscale client",
              {% endif %}
              {% if 'unreachable' in tailscale_report.network %}
              "Investigate network connectivity issues",
              {% endif %}
              "Regular Tailscale health monitoring recommended"
            ]
          }
        dest: "{{ tailscale_report_dir }}/{{ inventory_hostname }}_tailscale_{{ ansible_date_time.epoch }}.json"
      delegate_to: localhost

    - name: Tailscale management operations (when action is specified)
      block:
        - name: Validate action parameter
          fail:
            msg: "Invalid action. Supported actions: status, login, logout, up, down, ping"
          when: tailscale_action not in ['status', 'login', 'logout', 'up', 'down', 'ping']

        - name: Execute Tailscale action
          shell: |
            case "{{ tailscale_action }}" in
              "status")
                tailscale status --peers
                ;;
              "login")
                echo "Login requires interactive authentication"
                tailscale login --timeout=30s
                ;;
              "logout")
                tailscale logout
                ;;
              "up")
                tailscale up {{ tailscale_args | default('') }}
                ;;
              "down")
                tailscale down
                ;;
              "ping")
                if [ -n "{{ tailscale_target | default('') }}" ]; then
                  tailscale ping "{{ tailscale_target }}"
                else
                  echo "Error: tailscale_target required for ping action"
                  exit 1
                fi
                ;;
            esac
          register: tailscale_action_result
          when: not skip_tailscale

        - name: Display action result
          debug:
            msg: |

              🔧 Tailscale action '{{ tailscale_action }}' completed on {{ inventory_hostname }}

              Result:
              {{ tailscale_action_result.stdout }}

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

      when: tailscale_action is defined and not skip_tailscale

    - name: Generate network topology map (run once)
      shell: |
        cd "{{ tailscale_report_dir }}"

        echo "# Tailscale Network Topology" > network_topology.md
        echo "" >> network_topology.md
        echo "**Generated:** {{ tailscale_timestamp }}" >> network_topology.md
        echo "" >> network_topology.md

        # Process all Tailscale JSON reports
        for json_file in *_tailscale_*.json; do
          if [ -f "$json_file" ]; then
            hostname=$(basename "$json_file" | cut -d'_' -f1)
            echo "## 🖥️ $hostname" >> network_topology.md
            echo "" >> network_topology.md

            # Extract key information
            if command -v jq >/dev/null 2>&1; then
              available=$(jq -r '.tailscale_available' "$json_file" 2>/dev/null || echo "unknown")
              echo "- **Tailscale:** $available" >> network_topology.md

              # Try to extract IP if available
              if [ "$available" = "true" ]; then
                echo "- **Status:** Connected" >> network_topology.md
              else
                echo "- **Status:** Not available" >> network_topology.md
              fi
            fi

            echo "- **Report:** [$json_file](./$json_file)" >> network_topology.md
            echo "" >> network_topology.md
          fi
        done

        echo "---" >> network_topology.md
        echo "*Auto-generated by Ansible tailscale_management.yml playbook*" >> network_topology.md
      delegate_to: localhost
      run_once: true

    - name: Summary message
      debug:
        msg: |

          🌐 Tailscale management complete for {{ inventory_hostname }}
          📄 Report saved to: {{ tailscale_report_dir }}/{{ inventory_hostname }}_tailscale_{{ ansible_date_time.epoch }}.json
          🗺️  Network topology: {{ tailscale_report_dir }}/network_topology.md

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

          💡 Use -e tailscale_action=<action> for management operations
          💡 Supported actions: status, login, logout, up, down, ping
          💡 Use -e tailscale_target=<ip> with ping action
