---
- name: Backup Verification and Testing
  hosts: all
  gather_facts: yes
  vars:
    verification_timestamp: "{{ ansible_date_time.iso8601 }}"
    verification_report_dir: "/tmp/backup_verification"
    backup_base_dir: "/opt/backups"
    test_restore_dir: "/tmp/restore_test"
    max_backup_age_days: 7

  tasks:
    - name: Create verification directories
      file:
        path: "{{ item }}"
        state: directory
        mode: '0755'
      loop:
        - "{{ verification_report_dir }}"
        - "{{ test_restore_dir }}"
      delegate_to: localhost
      run_once: true

    - name: Discover backup locations
      shell: |
        echo "=== BACKUP LOCATION DISCOVERY ==="

        # Common backup directories
        backup_dirs="/opt/backups /home/backups /var/backups /volume1/backups /mnt/backups"

        echo "Searching for backup directories:"
        for dir in $backup_dirs; do
          if [ -d "$dir" ]; then
            echo "✅ Found: $dir"
            ls -la "$dir" 2>/dev/null | head -5
            echo ""
          fi
        done

        # Look for backup files in common locations
        echo "Searching for backup files:"
        find /opt /home /var -name "*.sql" -o -name "*.dump" -o -name "*.tar.gz" -o -name "*.zip" -o -name "*backup*" 2>/dev/null | head -20 | while read backup_file; do
          if [ -f "$backup_file" ]; then
            size=$(du -h "$backup_file" 2>/dev/null | cut -f1)
            date=$(stat -c %y "$backup_file" 2>/dev/null | cut -d' ' -f1)
            echo "📁 $backup_file ($size, $date)"
          fi
        done
      register: backup_discovery
      changed_when: false

    - name: Analyze backup integrity
      shell: |
        echo "=== BACKUP INTEGRITY ANALYSIS ==="

        # Check for recent backups
        echo "Recent backup files (last {{ max_backup_age_days }} days):"
        find /opt /home /var -name "*backup*" -o -name "*.sql" -o -name "*.dump" -mtime -{{ max_backup_age_days }} 2>/dev/null | while read backup_file; do
          if [ -f "$backup_file" ]; then
            size=$(du -h "$backup_file" 2>/dev/null | cut -f1)
            date=$(stat -c %y "$backup_file" 2>/dev/null | cut -d' ' -f1)

            # Basic integrity checks
            integrity_status="✅ OK"

            # Check if file is empty
            if [ ! -s "$backup_file" ]; then
              integrity_status="❌ EMPTY"
            fi

            # Check file extension and try basic validation
            case "$backup_file" in
              *.sql)
                if ! head -1 "$backup_file" 2>/dev/null | grep -q "SQL\|CREATE\|INSERT\|--"; then
                  integrity_status="⚠️  SUSPICIOUS"
                fi
                ;;
              *.tar.gz)
                if ! tar -tzf "$backup_file" >/dev/null 2>&1; then
                  integrity_status="❌ CORRUPT"
                fi
                ;;
              *.zip)
                if command -v unzip >/dev/null 2>&1; then
                  if ! unzip -t "$backup_file" >/dev/null 2>&1; then
                    integrity_status="❌ CORRUPT"
                  fi
                fi
                ;;
            esac

            echo "$integrity_status $backup_file ($size, $date)"
          fi
        done
        echo ""

        # Check for old backups
        echo "Old backup files (older than {{ max_backup_age_days }} days):"
        old_backups=$(find /opt /home /var -name "*backup*" -o -name "*.sql" -o -name "*.dump" -mtime +{{ max_backup_age_days }} 2>/dev/null | wc -l)
        echo "Found $old_backups old backup files"

        if [ "$old_backups" -gt "0" ]; then
          echo "Oldest 5 backup files:"
          find /opt /home /var -name "*backup*" -o -name "*.sql" -o -name "*.dump" -mtime +{{ max_backup_age_days }} 2>/dev/null | head -5 | while read old_file; do
            date=$(stat -c %y "$old_file" 2>/dev/null | cut -d' ' -f1)
            size=$(du -h "$old_file" 2>/dev/null | cut -f1)
            echo "  $old_file ($size, $date)"
          done
        fi
      register: integrity_analysis
      changed_when: false

    - name: Test database backup restoration
      shell: |
        echo "=== DATABASE BACKUP RESTORATION TEST ==="

        # Find recent database backups
        db_backups=$(find /opt /home /var -name "*.sql" -o -name "*.dump" -mtime -{{ max_backup_age_days }} 2>/dev/null | head -5)

        if [ -z "$db_backups" ]; then
          echo "No recent database backups found for testing"
          exit 0
        fi

        echo "Testing database backup restoration:"

        for backup_file in $db_backups; do
          echo "Testing: $backup_file"

          # Determine database type from filename or content
          db_type="unknown"
          if echo "$backup_file" | grep -qi "postgres\|postgresql"; then
            db_type="postgresql"
          elif echo "$backup_file" | grep -qi "mysql\|mariadb"; then
            db_type="mysql"
          elif head -5 "$backup_file" 2>/dev/null | grep -qi "postgresql"; then
            db_type="postgresql"
          elif head -5 "$backup_file" 2>/dev/null | grep -qi "mysql"; then
            db_type="mysql"
          fi

          echo "  Detected type: $db_type"

          # Basic syntax validation
          case "$db_type" in
            "postgresql")
              if command -v psql >/dev/null 2>&1; then
                # Test PostgreSQL backup syntax
                if psql --set ON_ERROR_STOP=1 -f "$backup_file" -d template1 --dry-run 2>/dev/null; then
                  echo "  ✅ PostgreSQL syntax valid"
                else
                  echo "  ⚠️  PostgreSQL syntax check failed (may require specific database)"
                fi
              else
                echo "  ⚠️  PostgreSQL client not available for testing"
              fi
              ;;
            "mysql")
              if command -v mysql >/dev/null 2>&1; then
                # Test MySQL backup syntax
                if mysql --execute="source $backup_file" --force --dry-run 2>/dev/null; then
                  echo "  ✅ MySQL syntax valid"
                else
                  echo "  ⚠️  MySQL syntax check failed (may require specific database)"
                fi
              else
                echo "  ⚠️  MySQL client not available for testing"
              fi
              ;;
            *)
              # Generic SQL validation
              if grep -q "CREATE\|INSERT\|UPDATE" "$backup_file" 2>/dev/null; then
                echo "  ✅ Contains SQL statements"
              else
                echo "  ❌ No SQL statements found"
              fi
              ;;
          esac

          echo ""
        done
      register: db_restore_test
      changed_when: false
      ignore_errors: yes

    - name: Test file backup restoration
      shell: |
        echo "=== FILE BACKUP RESTORATION TEST ==="

        # Find recent archive backups
        archive_backups=$(find /opt /home /var -name "*.tar.gz" -o -name "*.zip" -mtime -{{ max_backup_age_days }} 2>/dev/null | head -3)

        if [ -z "$archive_backups" ]; then
          echo "No recent archive backups found for testing"
          exit 0
        fi

        echo "Testing file backup restoration:"

        for backup_file in $archive_backups; do
          echo "Testing: $backup_file"

          # Create test extraction directory
          test_dir="{{ test_restore_dir }}/$(basename "$backup_file" | sed 's/\.[^.]*$//')_test"
          mkdir -p "$test_dir"

          case "$backup_file" in
            *.tar.gz)
              if tar -tzf "$backup_file" >/dev/null 2>&1; then
                echo "  ✅ Archive is readable"

                # Test partial extraction
                if tar -xzf "$backup_file" -C "$test_dir" --strip-components=1 2>/dev/null | head -5; then
                  extracted_files=$(find "$test_dir" -type f 2>/dev/null | wc -l)
                  echo "  ✅ Extracted $extracted_files files successfully"
                else
                  echo "  ❌ Extraction failed"
                fi
              else
                echo "  ❌ Archive is corrupted or unreadable"
              fi
              ;;
            *.zip)
              if command -v unzip >/dev/null 2>&1; then
                if unzip -t "$backup_file" >/dev/null 2>&1; then
                  echo "  ✅ ZIP archive is valid"

                  # Test partial extraction
                  if unzip -q "$backup_file" -d "$test_dir" 2>/dev/null; then
                    extracted_files=$(find "$test_dir" -type f 2>/dev/null | wc -l)
                    echo "  ✅ Extracted $extracted_files files successfully"
                  else
                    echo "  ❌ Extraction failed"
                  fi
                else
                  echo "  ❌ ZIP archive is corrupted"
                fi
              else
                echo "  ⚠️  unzip command not available"
              fi
              ;;
          esac

          # Cleanup test directory
          rm -rf "$test_dir" 2>/dev/null
          echo ""
        done
      register: file_restore_test
      changed_when: false
      ignore_errors: yes

    - name: Check backup automation status
      shell: |
        echo "=== BACKUP AUTOMATION STATUS ==="

        # Check for cron jobs related to backups
        echo "Cron jobs (backup-related):"
        if command -v crontab >/dev/null 2>&1; then
          crontab -l 2>/dev/null | grep -i backup || echo "No backup cron jobs found"
        else
          echo "Crontab not available"
        fi
        echo ""

        # Check systemd timers
        if command -v systemctl >/dev/null 2>&1; then
          echo "Systemd timers (backup-related):"
          systemctl list-timers --no-pager 2>/dev/null | grep -i backup || echo "No backup timers found"
          echo ""
        fi

        # Check for Docker containers that might be doing backups
        if command -v docker >/dev/null 2>&1; then
          echo "Docker containers (backup-related):"
          docker ps --format "{{.Names}}\t{{.Image}}" 2>/dev/null | grep -i backup || echo "No backup containers found"
          echo ""
        fi

        # Check for backup scripts
        echo "Backup scripts:"
        find /opt /home /usr/local -name "*backup*" -type f -executable 2>/dev/null | head -10 | while read script; do
          echo "  $script"
        done
      register: automation_status
      changed_when: false

    - name: Generate backup health score
      shell: |
        echo "=== BACKUP HEALTH SCORE ==="

        score=100
        issues=0

        # Check for recent backups
        recent_backups=$(find /opt /home /var -name "*backup*" -o -name "*.sql" -o -name "*.dump" -mtime -{{ max_backup_age_days }} 2>/dev/null | wc -l)
        if [ "$recent_backups" -eq "0" ]; then
          echo "❌ No recent backups found (-30 points)"
          score=$((score - 30))
          issues=$((issues + 1))
        elif [ "$recent_backups" -lt "3" ]; then
          echo "⚠️  Few recent backups found (-10 points)"
          score=$((score - 10))
          issues=$((issues + 1))
        else
          echo "✅ Recent backups found (+0 points)"
        fi

        # Check for automation
        cron_backups=$(crontab -l 2>/dev/null | grep -i backup | wc -l)
        if [ "$cron_backups" -eq "0" ]; then
          echo "⚠️  No automated backup jobs found (-20 points)"
          score=$((score - 20))
          issues=$((issues + 1))
        else
          echo "✅ Automated backup jobs found (+0 points)"
        fi

        # Check for old backups (retention policy)
        old_backups=$(find /opt /home /var -name "*backup*" -mtime +30 2>/dev/null | wc -l)
        if [ "$old_backups" -gt "10" ]; then
          echo "⚠️  Many old backups found - consider cleanup (-5 points)"
          score=$((score - 5))
          issues=$((issues + 1))
        else
          echo "✅ Backup retention appears managed (+0 points)"
        fi

        # Determine health status
        if [ "$score" -ge "90" ]; then
          health_status="EXCELLENT"
        elif [ "$score" -ge "70" ]; then
          health_status="GOOD"
        elif [ "$score" -ge "50" ]; then
          health_status="FAIR"
        else
          health_status="POOR"
        fi

        echo ""
        echo "BACKUP HEALTH SCORE: $score/100 ($health_status)"
        echo "ISSUES FOUND: $issues"
      register: health_score
      changed_when: false

    - name: Create verification report
      set_fact:
        verification_report:
          timestamp: "{{ verification_timestamp }}"
          hostname: "{{ inventory_hostname }}"
          backup_discovery: "{{ backup_discovery.stdout }}"
          integrity_analysis: "{{ integrity_analysis.stdout }}"
          db_restore_test: "{{ db_restore_test.stdout }}"
          file_restore_test: "{{ file_restore_test.stdout }}"
          automation_status: "{{ automation_status.stdout }}"
          health_score: "{{ health_score.stdout }}"

    - name: Display verification report
      debug:
        msg: |

          ==========================================
          🔍 BACKUP VERIFICATION - {{ inventory_hostname }}
          ==========================================

          📁 BACKUP DISCOVERY:
          {{ verification_report.backup_discovery }}

          🔒 INTEGRITY ANALYSIS:
          {{ verification_report.integrity_analysis }}

          🗄️  DATABASE RESTORE TEST:
          {{ verification_report.db_restore_test }}

          📦 FILE RESTORE TEST:
          {{ verification_report.file_restore_test }}

          🤖 AUTOMATION STATUS:
          {{ verification_report.automation_status }}

          📊 HEALTH SCORE:
          {{ verification_report.health_score }}

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

    - name: Generate JSON verification report
      copy:
        content: |
          {
            "timestamp": "{{ verification_report.timestamp }}",
            "hostname": "{{ verification_report.hostname }}",
            "backup_discovery": {{ verification_report.backup_discovery | to_json }},
            "integrity_analysis": {{ verification_report.integrity_analysis | to_json }},
            "db_restore_test": {{ verification_report.db_restore_test | to_json }},
            "file_restore_test": {{ verification_report.file_restore_test | to_json }},
            "automation_status": {{ verification_report.automation_status | to_json }},
            "health_score": {{ verification_report.health_score | to_json }},
            "recommendations": [
              {% if 'No recent backups found' in verification_report.integrity_analysis %}
              "Implement regular backup procedures",
              {% endif %}
              {% if 'No backup cron jobs found' in verification_report.automation_status %}
              "Set up automated backup scheduling",
              {% endif %}
              {% if 'CORRUPT' in verification_report.integrity_analysis %}
              "Investigate and fix corrupted backup files",
              {% endif %}
              {% if 'old backup files' in verification_report.integrity_analysis %}
              "Implement backup retention policy",
              {% endif %}
              "Regular backup verification testing recommended"
            ]
          }
        dest: "{{ verification_report_dir }}/{{ inventory_hostname }}_backup_verification_{{ ansible_date_time.epoch }}.json"
      delegate_to: localhost

    - name: Cleanup test files
      file:
        path: "{{ test_restore_dir }}"
        state: absent
      ignore_errors: yes

    - name: Summary message
      debug:
        msg: |

          🔍 Backup verification complete for {{ inventory_hostname }}
          📄 Report saved to: {{ verification_report_dir }}/{{ inventory_hostname }}_backup_verification_{{ ansible_date_time.epoch }}.json

          💡 Regular backup verification ensures data recovery capability
          💡 Test restore procedures periodically to validate backup integrity
          💡 Monitor backup automation to ensure continuous protection
