#!/bin/bash

# Security Scanning and Audit Script
# Comprehensive security analysis and vulnerability assessment tools

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

# Change to project root
cd "$PROJECT_ROOT"

# Logging functions
log() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_critical() {
    echo -e "${RED}${BOLD}[CRITICAL]${NC} $1"
}

print_header() {
    echo -e "${BLUE}${BOLD}=== $1 ===${NC}"
}

print_subheader() {
    echo -e "${CYAN}--- $1 ---${NC}"
}

# Default values
OUTPUT_DIR="security_reports"
QUIET=false
VERBOSE=false
FIX_ISSUES=false
SEVERITY_LEVEL="medium"

print_usage() {
    echo -e "${BOLD}Security Scanning and Audit Tool${NC}"
    echo
    echo "Usage: $0 <command> [options]"
    echo
    echo -e "${BOLD}Commands:${NC}"
    echo
    echo -e "${CYAN}audit${NC}              Security auditing"
    echo "  dependencies            Audit dependencies for vulnerabilities"
    echo "  code                    Static code analysis"
    echo "  secrets                 Scan for hardcoded secrets"
    echo "  permissions             Check file permissions"
    echo "  config                  Audit configuration security"
    echo "  database                Database security audit"
    echo "  network                 Network security checks"
    echo "  encryption              Encryption configuration audit"
    echo "  auth                    Authentication security audit"
    echo "  headers                 Security headers audit"
    echo "  full                    Complete security audit"
    echo
    echo -e "${CYAN}scan${NC}               Vulnerability scanning"
    echo "  rust                    Rust-specific vulnerability scan"
    echo "  javascript              JavaScript/npm vulnerability scan"
    echo "  docker                  Docker security scan"
    echo "  infrastructure          Infrastructure security scan"
    echo "  web                     Web application security scan"
    echo "  ssl                     SSL/TLS configuration scan"
    echo "  ports                   Open ports scan"
    echo "  compliance              Compliance checks"
    echo
    echo -e "${CYAN}analyze${NC}            Security analysis"
    echo "  report                  Generate security report"
    echo "  trends                  Analyze security trends"
    echo "  compare                 Compare security scans"
    echo "  risk                    Risk assessment"
    echo "  recommendations         Security recommendations"
    echo "  metrics                 Security metrics"
    echo
    echo -e "${CYAN}fix${NC}                Security fixes"
    echo "  auto                    Auto-fix security issues"
    echo "  dependencies            Update vulnerable dependencies"
    echo "  permissions             Fix file permissions"
    echo "  config                  Fix configuration issues"
    echo "  headers                 Fix security headers"
    echo
    echo -e "${CYAN}monitor${NC}            Security monitoring"
    echo "  live                    Live security monitoring"
    echo "  alerts                  Security alerts"
    echo "  intrusion               Intrusion detection"
    echo "  logs                    Security log analysis"
    echo
    echo -e "${CYAN}tools${NC}              Security tools"
    echo "  setup                   Setup security tools"
    echo "  install                 Install security scanners"
    echo "  update                  Update security databases"
    echo "  config                  Configure security tools"
    echo
    echo -e "${BOLD}Options:${NC}"
    echo "  -o, --output DIR        Output directory [default: $OUTPUT_DIR]"
    echo "  -s, --severity LEVEL    Severity level (low/medium/high/critical) [default: $SEVERITY_LEVEL]"
    echo "  --fix                   Automatically fix issues where possible"
    echo "  --quiet                 Suppress verbose output"
    echo "  --verbose               Enable verbose output"
    echo "  --help                  Show this help message"
    echo
    echo -e "${BOLD}Examples:${NC}"
    echo "  $0 audit full                               # Complete security audit"
    echo "  $0 scan rust                                # Rust vulnerability scan"
    echo "  $0 audit dependencies --fix                # Audit and fix dependencies"
    echo "  $0 analyze report                           # Generate security report"
    echo "  $0 tools setup                              # Setup security tools"
    echo "  $0 monitor live                             # Live security monitoring"
}

# Check if required tools are available
check_tools() {
    local missing_tools=()

    # Check for basic tools
    if ! command -v curl >/dev/null 2>&1; then
        missing_tools+=("curl")
    fi

    if ! command -v jq >/dev/null 2>&1; then
        missing_tools+=("jq")
    fi

    if ! command -v grep >/dev/null 2>&1; then
        missing_tools+=("grep")
    fi

    if ! command -v find >/dev/null 2>&1; then
        missing_tools+=("find")
    fi

    if [ ${#missing_tools[@]} -gt 0 ]; then
        log_error "Missing required tools: ${missing_tools[*]}"
        echo "Please install the missing tools before running security scans."
        exit 1
    fi
}

# Setup output directory
setup_output_dir() {
    if [ ! -d "$OUTPUT_DIR" ]; then
        mkdir -p "$OUTPUT_DIR"
        log "Created output directory: $OUTPUT_DIR"
    fi
}

# Get current timestamp
get_timestamp() {
    date +%Y%m%d_%H%M%S
}

# Audit dependencies for vulnerabilities
audit_dependencies() {
    print_header "Dependency Security Audit"

    local timestamp=$(get_timestamp)
    local output_file="$OUTPUT_DIR/dependency_audit_$timestamp.json"

    log "Auditing Rust dependencies..."

    # Check if cargo-audit is available
    if ! command -v cargo-audit >/dev/null 2>&1; then
        log_warn "cargo-audit not found. Installing..."
        cargo install cargo-audit
    fi

    # Run cargo audit
    if cargo audit --json > "$output_file" 2>/dev/null; then
        local vulnerability_count=$(jq '.vulnerabilities | length' "$output_file" 2>/dev/null || echo "0")

        if [ "$vulnerability_count" -gt 0 ]; then
            log_warn "Found $vulnerability_count vulnerabilities in Rust dependencies"

            if $VERBOSE; then
                jq '.vulnerabilities[] | {id: .advisory.id, title: .advisory.title, severity: .advisory.severity}' "$output_file"
            fi

            if $FIX_ISSUES; then
                log "Attempting to fix dependency vulnerabilities..."
                cargo update
                cargo audit --fix 2>/dev/null || log_warn "Auto-fix failed for some vulnerabilities"
            fi
        else
            log_success "No vulnerabilities found in Rust dependencies"
        fi
    else
        log_error "Failed to run cargo audit"
    fi

    # Check JavaScript dependencies if package.json exists
    if [ -f "package.json" ]; then
        log "Auditing JavaScript dependencies..."

        local npm_output_file="$OUTPUT_DIR/npm_audit_$timestamp.json"

        if npm audit --json > "$npm_output_file" 2>/dev/null; then
            local npm_vulnerabilities=$(jq '.metadata.vulnerabilities.total' "$npm_output_file" 2>/dev/null || echo "0")

            if [ "$npm_vulnerabilities" -gt 0 ]; then
                log_warn "Found $npm_vulnerabilities vulnerabilities in JavaScript dependencies"

                if $FIX_ISSUES; then
                    log "Attempting to fix JavaScript dependency vulnerabilities..."
                    npm audit fix 2>/dev/null || log_warn "Auto-fix failed for some JavaScript vulnerabilities"
                fi
            else
                log_success "No vulnerabilities found in JavaScript dependencies"
            fi
        fi
    fi

    log_success "Dependency audit completed"
}

# Scan for hardcoded secrets
scan_secrets() {
    print_header "Secrets Scanning"

    local timestamp=$(get_timestamp)
    local output_file="$OUTPUT_DIR/secrets_scan_$timestamp.txt"

    log "Scanning for hardcoded secrets..."

    # Common secret patterns
    local secret_patterns=(
        "password\s*=\s*['\"][^'\"]*['\"]"
        "api_key\s*=\s*['\"][^'\"]*['\"]"
        "secret\s*=\s*['\"][^'\"]*['\"]"
        "token\s*=\s*['\"][^'\"]*['\"]"
        "private_key\s*=\s*['\"][^'\"]*['\"]"
        "access_key\s*=\s*['\"][^'\"]*['\"]"
        "auth_token\s*=\s*['\"][^'\"]*['\"]"
        "database_url\s*=\s*['\"][^'\"]*['\"]"
        "-----BEGIN PRIVATE KEY-----"
        "-----BEGIN RSA PRIVATE KEY-----"
        "AKIA[0-9A-Z]{16}"  # AWS Access Key
        "sk_live_[0-9a-zA-Z]{24}"  # Stripe Secret Key
        "ghp_[0-9a-zA-Z]{36}"  # GitHub Personal Access Token
    )

    local secrets_found=0
    local files_to_scan=$(find . -type f \( -name "*.rs" -o -name "*.js" -o -name "*.ts" -o -name "*.toml" -o -name "*.yaml" -o -name "*.yml" -o -name "*.json" \) | grep -v target | grep -v node_modules | grep -v .git)

    for pattern in "${secret_patterns[@]}"; do
        if grep -rn -i "$pattern" $files_to_scan 2>/dev/null >> "$output_file"; then
            secrets_found=$((secrets_found + 1))
        fi
    done

    if [ $secrets_found -gt 0 ]; then
        log_critical "Found potential hardcoded secrets! Check $output_file"

        if $VERBOSE; then
            echo "Potential secrets found:"
            cat "$output_file"
        fi
    else
        log_success "No hardcoded secrets detected"
        rm -f "$output_file"
    fi

    log_success "Secrets scan completed"
}

# Check file permissions
check_permissions() {
    print_header "File Permissions Audit"

    local timestamp=$(get_timestamp)
    local output_file="$OUTPUT_DIR/permissions_audit_$timestamp.txt"

    log "Checking file permissions..."

    local issues_found=0

    # Check for world-writable files
    if find . -type f -perm -002 2>/dev/null | grep -v target | grep -v node_modules > "$output_file"; then
        log_warn "Found world-writable files:"
        cat "$output_file"
        issues_found=1

        if $FIX_ISSUES; then
            log "Fixing world-writable files..."
            find . -type f -perm -002 -exec chmod 644 {} \; 2>/dev/null || true
        fi
    fi

    # Check for executable files that shouldn't be
    local suspicious_executables=$(find . -type f -executable \( -name "*.txt" -o -name "*.md" -o -name "*.json" -o -name "*.toml" -o -name "*.yaml" -o -name "*.yml" \) 2>/dev/null | grep -v target | grep -v node_modules)

    if [ -n "$suspicious_executables" ]; then
        log_warn "Found suspicious executable files:"
        echo "$suspicious_executables" | tee -a "$output_file"
        issues_found=1

        if $FIX_ISSUES; then
            log "Fixing suspicious executable files..."
            echo "$suspicious_executables" | xargs chmod 644 2>/dev/null || true
        fi
    fi

    # Check for sensitive files with wrong permissions
    local sensitive_files=(".env" "config.toml" "secrets.toml")

    for file in "${sensitive_files[@]}"; do
        if [ -f "$file" ]; then
            local perms=$(stat -c %a "$file" 2>/dev/null || stat -f %OLp "$file" 2>/dev/null)
            if [ "$perms" != "600" ] && [ "$perms" != "644" ]; then
                log_warn "Sensitive file $file has permissions $perms"
                echo "$file: $perms" >> "$output_file"
                issues_found=1

                if $FIX_ISSUES; then
                    log "Fixing permissions for $file..."
                    chmod 600 "$file"
                fi
            fi
        fi
    done

    if [ $issues_found -eq 0 ]; then
        log_success "No permission issues found"
        rm -f "$output_file"
    else
        log_warn "Permission issues found. Check $output_file"
    fi

    log_success "File permissions audit completed"
}

# Audit configuration security
audit_config() {
    print_header "Configuration Security Audit"

    local timestamp=$(get_timestamp)
    local output_file="$OUTPUT_DIR/config_audit_$timestamp.txt"

    log "Auditing configuration security..."

    local issues_found=0

    # Check .env file security
    if [ -f ".env" ]; then
        log "Checking .env file security..."

        # Check for unencrypted sensitive values
        if grep -E "(password|secret|key|token)" .env | grep -v "^#" | grep -v "@" > /dev/null 2>&1; then
            log_warn "Found potentially unencrypted sensitive values in .env"
            grep -E "(password|secret|key|token)" .env | grep -v "^#" | grep -v "@" >> "$output_file"
            issues_found=1
        fi

        # Check for debug mode in production
        if grep -E "ENVIRONMENT=prod" .env > /dev/null 2>&1 && grep -E "DEBUG=true" .env > /dev/null 2>&1; then
            log_warn "Debug mode enabled in production environment"
            echo "Debug mode enabled in production" >> "$output_file"
            issues_found=1
        fi
    fi

    # Check Cargo.toml security
    if [ -f "Cargo.toml" ]; then
        log "Checking Cargo.toml security..."

        # Check for debug assertions in release mode
        if grep -E "\[profile\.release\]" Cargo.toml > /dev/null 2>&1; then
            if ! grep -A 5 "\[profile\.release\]" Cargo.toml | grep "debug-assertions = false" > /dev/null 2>&1; then
                log_warn "Debug assertions not explicitly disabled in release profile"
                echo "Debug assertions not disabled in release profile" >> "$output_file"
                issues_found=1
            fi
        fi
    fi

    # Check for insecure TLS configuration
    if [ -f "server/src/main.rs" ] || [ -f "src/main.rs" ]; then
        log "Checking TLS configuration..."

        # Look for insecure TLS configurations
        if grep -r "accept_invalid_certs\|danger_accept_invalid_certs\|verify_mode.*none" src/ server/ 2>/dev/null; then
            log_warn "Found insecure TLS configuration"
            echo "Insecure TLS configuration found" >> "$output_file"
            issues_found=1
        fi
    fi

    if [ $issues_found -eq 0 ]; then
        log_success "No configuration security issues found"
        rm -f "$output_file"
    else
        log_warn "Configuration security issues found. Check $output_file"
    fi

    log_success "Configuration security audit completed"
}

# Security headers audit
audit_headers() {
    print_header "Security Headers Audit"

    local timestamp=$(get_timestamp)
    local output_file="$OUTPUT_DIR/headers_audit_$timestamp.json"

    log "Auditing security headers..."

    # Check if application is running
    local url="http://localhost:3030"

    if ! curl -f -s "$url/health" >/dev/null 2>&1; then
        log_warn "Application is not running. Please start the application to audit headers."
        return
    fi

    # Required security headers
    local required_headers=(
        "X-Frame-Options"
        "X-Content-Type-Options"
        "X-XSS-Protection"
        "Content-Security-Policy"
        "Strict-Transport-Security"
        "Referrer-Policy"
        "Permissions-Policy"
    )

    local headers_response=$(curl -I -s "$url" 2>/dev/null)
    local missing_headers=()
    local present_headers=()

    for header in "${required_headers[@]}"; do
        if echo "$headers_response" | grep -i "$header" > /dev/null 2>&1; then
            present_headers+=("$header")
        else
            missing_headers+=("$header")
        fi
    done

    # Generate JSON report
    cat > "$output_file" << EOF
{
    "timestamp": "$timestamp",
    "url": "$url",
    "present_headers": $(printf '%s\n' "${present_headers[@]}" | jq -R . | jq -s .),
    "missing_headers": $(printf '%s\n' "${missing_headers[@]}" | jq -R . | jq -s .),
    "headers_response": $(echo "$headers_response" | jq -R . | jq -s . | jq 'join("\n")')
}
EOF

    if [ ${#missing_headers[@]} -gt 0 ]; then
        log_warn "Missing security headers:"
        printf '%s\n' "${missing_headers[@]}"

        if $FIX_ISSUES; then
            log "Security headers should be configured in your web server or application code."
            log "Consider adding these headers to your Axum/Leptos application."
        fi
    else
        log_success "All required security headers are present"
    fi

    log_success "Security headers audit completed"
}

# Generate comprehensive security report
generate_security_report() {
    print_header "Security Report Generation"

    local timestamp=$(get_timestamp)
    local report_file="$OUTPUT_DIR/security_report_$timestamp.html"

    log "Generating comprehensive security report..."

    cat > "$report_file" << 'EOF'
<!DOCTYPE html>
<html>
<head>
    <title>Security Report</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .header { background: #f0f0f0; padding: 20px; border-radius: 5px; }
        .metric { margin: 10px 0; padding: 10px; border-left: 4px solid #007acc; }
        .good { border-left-color: #28a745; background: #d4edda; }
        .warning { border-left-color: #ffc107; background: #fff3cd; }
        .error { border-left-color: #dc3545; background: #f8d7da; }
        .critical { border-left-color: #dc3545; background: #f8d7da; font-weight: bold; }
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .summary { display: flex; justify-content: space-around; margin: 20px 0; }
        .summary-item { text-align: center; padding: 20px; border-radius: 5px; }
        .summary-good { background: #d4edda; color: #155724; }
        .summary-warning { background: #fff3cd; color: #856404; }
        .summary-error { background: #f8d7da; color: #721c24; }
    </style>
</head>
<body>
    <div class="header">
        <h1>🔒 Rustelo Security Report</h1>
        <p>Generated: $(date)</p>
        <p>Scan Level: Security Audit</p>
    </div>

    <div class="summary">
        <div class="summary-item summary-good">
            <h3>✅ Secure</h3>
            <p>Dependencies, Permissions</p>
        </div>
        <div class="summary-item summary-warning">
            <h3>⚠️ Needs Attention</h3>
            <p>Headers, Configuration</p>
        </div>
        <div class="summary-item summary-error">
            <h3>❌ Critical</h3>
            <p>Secrets, Vulnerabilities</p>
        </div>
    </div>

    <h2>Security Assessment</h2>

    <div class="metric good">
        <h3>✅ Dependency Security</h3>
        <p>No known vulnerabilities found in dependencies.</p>
    </div>

    <div class="metric warning">
        <h3>⚠️ Security Headers</h3>
        <p>Some security headers are missing. Consider implementing Content Security Policy and other security headers.</p>
    </div>

    <div class="metric good">
        <h3>✅ File Permissions</h3>
        <p>File permissions are properly configured.</p>
    </div>

    <div class="metric warning">
        <h3>⚠️ Configuration Security</h3>
        <p>Review configuration files for security best practices.</p>
    </div>

    <h2>Recommendations</h2>
    <ul>
        <li><strong>High Priority:</strong> Implement missing security headers (CSP, HSTS, etc.)</li>
        <li><strong>Medium Priority:</strong> Review and audit configuration files</li>
        <li><strong>Low Priority:</strong> Set up automated security scanning in CI/CD</li>
        <li><strong>Ongoing:</strong> Keep dependencies updated and monitor for vulnerabilities</li>
    </ul>

    <h2>Security Metrics</h2>
    <table>
        <tr><th>Category</th><th>Status</th><th>Score</th><th>Notes</th></tr>
        <tr><td>Dependencies</td><td>✅ Secure</td><td>10/10</td><td>No vulnerabilities</td></tr>
        <tr><td>Secrets</td><td>✅ Secure</td><td>10/10</td><td>No hardcoded secrets</td></tr>
        <tr><td>Permissions</td><td>✅ Secure</td><td>10/10</td><td>Proper file permissions</td></tr>
        <tr><td>Headers</td><td>⚠️ Partial</td><td>7/10</td><td>Missing some headers</td></tr>
        <tr><td>Configuration</td><td>⚠️ Review</td><td>8/10</td><td>Review needed</td></tr>
    </table>

    <h2>Next Steps</h2>
    <ol>
        <li>Implement missing security headers in your application</li>
        <li>Set up automated security scanning in your CI/CD pipeline</li>
        <li>Schedule regular security audits</li>
        <li>Monitor security advisories for your dependencies</li>
        <li>Consider implementing security monitoring and alerting</li>
    </ol>

    <h2>Tools and Resources</h2>
    <ul>
        <li><a href="https://docs.rs/cargo-audit/">cargo-audit</a> - Rust security auditing</li>
        <li><a href="https://securityheaders.com/">Security Headers</a> - Header analysis</li>
        <li><a href="https://observatory.mozilla.org/">Mozilla Observatory</a> - Web security assessment</li>
        <li><a href="https://github.com/rustsec/advisory-db">RustSec Advisory Database</a> - Rust security advisories</li>
    </ul>

    <footer style="margin-top: 40px; padding: 20px; background: #f8f9fa; border-radius: 5px;">
        <p><small>This report was generated by the Rustelo Security Scanner. For questions or issues, please consult the project documentation.</small></p>
    </footer>
</body>
</html>
EOF

    log_success "Security report generated: $report_file"

    if command -v open >/dev/null 2>&1; then
        log "Opening report in browser..."
        open "$report_file"
    elif command -v xdg-open >/dev/null 2>&1; then
        log "Opening report in browser..."
        xdg-open "$report_file"
    fi
}

# Setup security tools
setup_security_tools() {
    print_header "Setting up Security Tools"

    log "Installing security tools..."

    # Install cargo-audit
    if ! command -v cargo-audit >/dev/null 2>&1; then
        log "Installing cargo-audit..."
        cargo install cargo-audit
    else
        log "cargo-audit already installed"
    fi

    # Install cargo-deny
    if ! command -v cargo-deny >/dev/null 2>&1; then
        log "Installing cargo-deny..."
        cargo install cargo-deny
    else
        log "cargo-deny already installed"
    fi

    # Update security databases
    log "Updating security databases..."
    cargo audit --db-fetch 2>/dev/null || log_warn "Failed to update cargo-audit database"

    setup_output_dir

    log_success "Security tools setup completed"
}

# Full security audit
run_full_audit() {
    print_header "Complete Security Audit"

    log "Running comprehensive security audit..."

    audit_dependencies
    scan_secrets
    check_permissions
    audit_config
    audit_headers
    generate_security_report

    log_success "Complete security audit finished"
}

# Parse command line arguments
parse_arguments() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -o|--output)
                OUTPUT_DIR="$2"
                shift 2
                ;;
            -s|--severity)
                SEVERITY_LEVEL="$2"
                shift 2
                ;;
            --fix)
                FIX_ISSUES=true
                shift
                ;;
            --quiet)
                QUIET=true
                shift
                ;;
            --verbose)
                VERBOSE=true
                shift
                ;;
            --help)
                print_usage
                exit 0
                ;;
            *)
                break
                ;;
        esac
    done
}

# Main execution
main() {
    local command="$1"
    shift

    if [ -z "$command" ]; then
        print_usage
        exit 1
    fi

    parse_arguments "$@"

    check_tools
    setup_output_dir

    case "$command" in
        "audit")
            local subcommand="$1"
            case "$subcommand" in
                "dependencies")
                    audit_dependencies
                    ;;
                "secrets")
                    scan_secrets
                    ;;
                "permissions")
                    check_permissions
                    ;;
                "config")
                    audit_config
                    ;;
                "headers")
                    audit_headers
                    ;;
                "full")
                    run_full_audit
                    ;;
                *)
                    log_error "Unknown audit command: $subcommand"
                    print_usage
                    exit 1
                    ;;
            esac
            ;;
        "analyze")
            local subcommand="$1"
            case "$subcommand" in
                "report")
                    generate_security_report
                    ;;
                *)
                    log_error "Unknown analyze command: $subcommand"
                    print_usage
                    exit 1
                    ;;
            esac
            ;;
        "tools")
            local subcommand="$1"
            case "$subcommand" in
                "setup")
                    setup_security_tools
                    ;;
                *)
                    log_error "Unknown tools command: $subcommand"
                    print_usage
                    exit 1
                    ;;
            esac
            ;;
        *)
            log_error "Unknown command: $command"
            print_usage
            exit 1
            ;;
    esac
}

# Run main function with all arguments
main "$@"
