#!/bin/bash

# Two-Factor Authentication Validation Test
# Validates 2FA configuration for SSH, Cockpit, and Webmin

set -euo pipefail

function test_2fa_packages() {
    echo "🔍 Testing 2FA package installation..."
    
    local packages=("libpam-google-authenticator" "qrencode")
    local failed=0
    
    for package in "${packages[@]}"; do
        if dpkg -s "$package" 2>/dev/null | grep -q "^Status:.*installed"; then
            echo "✅ Package installed: $package"
        else
            echo "❌ Package missing: $package"
            ((++failed))
        fi
    done
    
    # Check if google-authenticator command exists
    if command -v google-authenticator >/dev/null 2>&1; then
        echo "✅ Google Authenticator command available"
    else
        echo "❌ Google Authenticator command not found"
        ((++failed))
    fi
    
    return $failed
}

function test_ssh_2fa_config() {
    echo "🔍 Testing SSH 2FA configuration..."
    
    local ssh_config="/etc/ssh/sshd_config"
    local failed=0
    
    # Check required SSH settings
    if grep -q "^ChallengeResponseAuthentication yes" "$ssh_config"; then
        echo "✅ ChallengeResponseAuthentication enabled"
    else
        echo "❌ ChallengeResponseAuthentication not enabled"
        ((++failed))
    fi
    
    if grep -q "^UsePAM yes" "$ssh_config"; then
        echo "✅ UsePAM enabled"
    else
        echo "❌ UsePAM not enabled"
        ((++failed))
    fi
    
    if grep -q "^AuthenticationMethods publickey,keyboard-interactive" "$ssh_config"; then
        echo "✅ AuthenticationMethods configured for 2FA"
    else
        echo "❌ AuthenticationMethods not configured for 2FA"
        ((++failed))
    fi
    
    return $failed
}

function test_pam_2fa_config() {
    echo "🔍 Testing PAM 2FA configuration..."
    
    local pam_sshd="/etc/pam.d/sshd"
    local failed=0
    
    # Check if PAM includes Google Authenticator
    if grep -q "pam_google_authenticator.so" "$pam_sshd"; then
        echo "✅ PAM Google Authenticator module configured"
    else
        echo "❌ PAM Google Authenticator module not configured"
        ((++failed))
    fi
    
    # Check if nullok is present (allows users without 2FA setup)
    if grep -q "pam_google_authenticator.so nullok" "$pam_sshd"; then
        echo "✅ PAM nullok option configured (allows gradual rollout)"
    else
        echo "⚠️  PAM nullok option not configured (immediate enforcement)"
    fi
    
    return $failed
}

function test_cockpit_2fa_config() {
    echo "🔍 Testing Cockpit 2FA configuration..."
    
    local cockpit_config="/etc/cockpit/cockpit.conf"
    local cockpit_pam="/etc/pam.d/cockpit"
    local failed=0
    
    # Check if Cockpit is installed
    if ! command -v cockpit-ws >/dev/null 2>&1; then
        echo "⚠️  Cockpit not installed, skipping test"
        return 0
    fi
    
    # Check Cockpit configuration
    if [[ -f "$cockpit_config" ]]; then
        echo "✅ Cockpit configuration file exists"
    else
        echo "❌ Cockpit configuration file missing"
        ((++failed))
    fi
    
    # Check Cockpit PAM configuration
    if [[ -f "$cockpit_pam" ]] && grep -q "pam_google_authenticator.so" "$cockpit_pam"; then
        echo "✅ Cockpit PAM 2FA configured"
    else
        echo "❌ Cockpit PAM 2FA not configured"
        ((++failed))
    fi
    
    return $failed
}

function test_webmin_2fa_config() {
    echo "🔍 Testing Webmin 2FA configuration..."
    
    local webmin_config="/etc/webmin/miniserv.conf"
    local failed=0
    
    # Check if Webmin is installed
    if [[ ! -f "$webmin_config" ]]; then
        echo "⚠️  Webmin not installed, skipping test"
        return 0
    fi
    
    # Check Webmin 2FA settings
    if grep -q "^twofactor_provider=totp" "$webmin_config"; then
        echo "✅ Webmin TOTP provider configured"
    else
        echo "❌ Webmin TOTP provider not configured"
        ((++failed))
    fi
    
    if grep -q "^twofactor=1" "$webmin_config"; then
        echo "✅ Webmin 2FA enabled"
    else
        echo "❌ Webmin 2FA not enabled"
        ((++failed))
    fi
    
    return $failed
}

function test_user_2fa_setup() {
    echo "🔍 Testing user 2FA setup preparation..."
    
    local users=("localuser" "root")
    local failed=0
    
    for user in "${users[@]}"; do
        if id "$user" &>/dev/null; then
            local user_home; user_home="$(getent passwd "$user" | cut -d: -f6)"

            # Check if setup script exists
            if [[ -f "/tmp/setup-2fa-$user.sh" ]]; then
                echo "✅ 2FA setup script exists for user: $user"
            else
                echo "❌ 2FA setup script missing for user: $user"
                ((++failed))
            fi
            
            # Check if instructions exist
            if [[ -n "$user_home" && -f "$user_home/2fa-setup-instructions.txt" ]]; then
                echo "✅ 2FA instructions exist for user: $user"
            else
                echo "❌ 2FA instructions missing for user: $user"
                ((++failed))
            fi
        else
            echo "⚠️  User $user not found, skipping"
        fi
    done
    
    return $failed
}

function test_service_status() {
    echo "🔍 Testing service status..."
    
    local failed=0
    
    # Test SSH service
    if systemctl is-active sshd >/dev/null 2>&1; then
        echo "✅ SSH service is running"
    else
        echo "❌ SSH service is not running"
        ((++failed))
    fi
    
    # Test SSH configuration
    if sshd -t 2>/dev/null; then
        echo "✅ SSH configuration is valid"
    else
        echo "❌ SSH configuration is invalid"
        ((++failed))
    fi
    
    # Test Cockpit service if installed
    if systemctl is-enabled cockpit.socket >/dev/null 2>&1; then
        if systemctl is-active cockpit.socket >/dev/null 2>&1; then
            echo "✅ Cockpit service is running"
        else
            echo "❌ Cockpit service is not running"
            ((++failed))
        fi
    fi
    
    # Test Webmin service if installed
    if systemctl is-enabled webmin >/dev/null 2>&1; then
        if systemctl is-active webmin >/dev/null 2>&1; then
            echo "✅ Webmin service is running"
        else
            echo "❌ Webmin service is not running"
            ((++failed))
        fi
    fi
    
    return $failed
}

function test_backup_existence() {
    echo "🔍 Testing backup existence..."
    
    local backup_dir="/root/backup"
    local failed=0
    
    if [[ -d "$backup_dir" ]]; then
        # Look for recent 2FA backups
        local recent_backups
        recent_backups=$(find "$backup_dir" -name "2fa-*" -type d -newer /etc/ssh/sshd_config 2>/dev/null | wc -l)
        
        if [[ $recent_backups -gt 0 ]]; then
            echo "✅ Recent 2FA backup found in $backup_dir"
        else
            echo "⚠️  No recent 2FA backups found"
        fi
    else
        echo "❌ Backup directory does not exist"
        ((++failed))
    fi
    
    return $failed
}

function test_2fa_enforcement() {
    echo "🔍 Testing 2FA enforcement level..."
    
    local pam_sshd="/etc/pam.d/sshd"
    
    # Check if nullok is used (allows users without 2FA)
    if grep -q "pam_google_authenticator.so nullok" "$pam_sshd"; then
        echo "⚠️  2FA enforcement: GRADUAL (nullok allows users without 2FA)"
        echo "    Users can log in without 2FA during setup phase"
    else
        echo "✅ 2FA enforcement: STRICT (all users must have 2FA)"
        echo "    All users must have 2FA configured to log in"
    fi
    
    return 0
}

# Main test execution
function main() {
    echo "🔒 Running Two-Factor Authentication Validation Tests"
    echo "=================================================="
    
    local total_failures=0
    
    # Run all 2FA validation tests
    test_2fa_packages || ((total_failures++))
    test_ssh_2fa_config || ((total_failures++))
    test_pam_2fa_config || ((total_failures++))
    test_cockpit_2fa_config || ((total_failures++))
    test_webmin_2fa_config || ((total_failures++))
    test_user_2fa_setup || ((total_failures++))
    test_service_status || ((total_failures++))
    test_backup_existence || ((total_failures++))
    test_2fa_enforcement || ((total_failures++))
    
    echo "=================================================="
    
    if [[ $total_failures -eq 0 ]]; then
        echo "✅ All 2FA validation tests passed"
        echo ""
        echo "📋 Next Steps:"
        echo "1. Run user setup scripts: /tmp/setup-2fa-*.sh"
        echo "2. Test 2FA login from another terminal"
        echo "3. Remove nullok from PAM config for strict enforcement"
        exit 0
    else
        echo "❌ $total_failures 2FA validation tests failed"
        echo ""
        echo "🔧 Troubleshooting:"
        echo "1. Re-run secharden-2fa.sh script"
        echo "2. Check system logs: journalctl -u sshd"
        echo "3. Verify package installation"
        exit 1
    fi
}

# Run main if executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi