# AI Agent Interface
# Provides programmatic interface for automated infrastructure validation and fixing

use validator.nu
use report_generator.nu *

# Main function for AI agents to validate infrastructure
export def validate_for_agent [
    infra_path: string
    --auto_fix: bool = false
    --severity_threshold: string = "warning"
]: nothing -> record {

    # Run validation
    let validation_result = (validator main $infra_path
        --fix=$auto_fix
        --report="json"
        --output="/tmp/agent_validation"
        --severity=$severity_threshold
        --ci
    )

    let issues = $validation_result.results.issues
    let summary = $validation_result.results.summary

    # Categorize issues for agent decision making
    let critical_issues = ($issues | where severity == "critical")
    let error_issues = ($issues | where severity == "error")
    let warning_issues = ($issues | where severity == "warning")
    let auto_fixable_issues = ($issues | where auto_fixable == true)
    let manual_fix_issues = ($issues | where auto_fixable == false)

    {
        # Decision making info
        can_proceed_with_deployment: (($critical_issues | length) == 0)
        requires_human_intervention: (($manual_fix_issues | where severity in ["critical", "error"] | length) > 0)
        safe_to_auto_fix: (($auto_fixable_issues | where severity in ["critical", "error"] | length) > 0)

        # Summary stats
        summary: {
            total_issues: ($issues | length)
            critical_count: ($critical_issues | length)
            error_count: ($error_issues | length)
            warning_count: ($warning_issues | length)
            auto_fixable_count: ($auto_fixable_issues | length)
            manual_fix_count: ($manual_fix_issues | length)
            files_processed: ($validation_result.results.files_processed | length)
        }

        # Actionable information
        auto_fixable_issues: ($auto_fixable_issues | each {|issue|
            {
                rule_id: $issue.rule_id
                file: $issue.file
                message: $issue.message
                fix_command: (generate_fix_command $issue)
                estimated_risk: (assess_fix_risk $issue)
            }
        })

        manual_fixes_required: ($manual_fix_issues | each {|issue|
            {
                rule_id: $issue.rule_id
                file: $issue.file
                message: $issue.message
                severity: $issue.severity
                suggested_action: $issue.suggested_fix
                priority: (assess_fix_priority $issue)
            }
        })

        # Enhancement opportunities
        enhancement_suggestions: (generate_enhancement_suggestions $validation_result.results)

        # Next steps for agent
        recommended_actions: (generate_agent_recommendations $validation_result.results)

        # Raw validation data
        raw_results: $validation_result
    }
}

# Generate specific commands for auto-fixing issues
def generate_fix_command [issue: record]: nothing -> string {
    match $issue.rule_id {
        "VAL003" => {
            # Unquoted variables
            $"sed -i 's/($issue.variable_name)/\"($issue.variable_name)\"/g' ($issue.file)"
        }
        "VAL005" => {
            # Naming conventions
            "# Manual review required for naming convention fixes"
        }
        _ => {
            "# Auto-fix command not available for this rule"
        }
    }
}

# Assess risk level of applying an auto-fix
def assess_fix_risk [issue: record]: nothing -> string {
    match $issue.rule_id {
        "VAL001" | "VAL002" => "high"      # Syntax/compilation issues
        "VAL003" => "low"                  # Quote fixes are generally safe
        "VAL005" => "medium"               # Naming changes might affect references
        _ => "medium"
    }
}

# Determine priority for manual fixes
def assess_fix_priority [issue: record]: nothing -> string {
    match $issue.severity {
        "critical" => "immediate"
        "error" => "high"
        "warning" => "medium"
        "info" => "low"
        _ => "medium"
    }
}

# Generate enhancement suggestions specifically for agents
def generate_enhancement_suggestions [results: record]: nothing -> list {
    let issues = $results.issues
    mut suggestions = []

    # Version upgrades
    let version_issues = ($issues | where rule_id == "VAL007")
    for issue in $version_issues {
        $suggestions = ($suggestions | append {
            type: "version_upgrade"
            component: (extract_component_from_issue $issue)
            current_version: (extract_current_version $issue)
            recommended_version: (extract_recommended_version $issue)
            impact: "security_and_features"
            automation_possible: true
        })
    }

    # Security improvements
    let security_issues = ($issues | where rule_id == "VAL006")
    for issue in $security_issues {
        $suggestions = ($suggestions | append {
            type: "security_improvement"
            area: (extract_security_area $issue)
            current_state: "needs_review"
            recommended_action: $issue.suggested_fix
            automation_possible: false
        })
    }

    # Resource optimization
    let resource_issues = ($issues | where severity == "info")
    for issue in $resource_issues {
        $suggestions = ($suggestions | append {
            type: "resource_optimization"
            resource_type: (extract_resource_type $issue)
            optimization: $issue.message
            potential_savings: "unknown"
            automation_possible: true
        })
    }

    $suggestions
}

# Generate specific recommendations for AI agents
def generate_agent_recommendations [results: record]: nothing -> list {
    let issues = $results.issues
    let summary = $results.summary
    mut recommendations = []

    # Critical path recommendations
    let critical_count = ($issues | where severity == "critical" | length)
    let error_count = ($issues | where severity == "error" | length)

    if $critical_count > 0 {
        $recommendations = ($recommendations | append {
            action: "block_deployment"
            reason: "Critical issues found that must be resolved"
            details: $"($critical_count) critical issues require immediate attention"
            automated_resolution: false
        })
    }

    if $error_count > 0 and $critical_count == 0 {
        $recommendations = ($recommendations | append {
            action: "attempt_auto_fix"
            reason: "Errors found that may be auto-fixable"
            details: $"($error_count) errors detected, some may be automatically resolved"
            automated_resolution: true
        })
    }

    # Auto-fix recommendations
    let auto_fixable = ($issues | where auto_fixable == true | length)
    if $auto_fixable > 0 {
        $recommendations = ($recommendations | append {
            action: "apply_auto_fixes"
            reason: "Safe automatic fixes available"
            details: $"($auto_fixable) issues can be automatically resolved"
            automated_resolution: true
        })
    }

    # Continuous improvement recommendations
    let warnings = ($issues | where severity == "warning" | length)
    if $warnings > 0 {
        $recommendations = ($recommendations | append {
            action: "schedule_improvement"
            reason: "Enhancement opportunities identified"
            details: $"($warnings) improvements could enhance infrastructure quality"
            automated_resolution: false
        })
    }

    $recommendations
}

# Batch operation for multiple infrastructures
export def validate_batch [
    infra_paths: list
    --parallel: bool = false
    --auto_fix: bool = false
]: nothing -> record {

    mut batch_results = []

    if $parallel {
        # Parallel processing for multiple infrastructures
        $batch_results = ($infra_paths | par-each {|path|
            let result = (validate_for_agent $path --auto_fix=$auto_fix)
            {
                infra_path: $path
                result: $result
                timestamp: (date now)
            }
        })
    } else {
        # Sequential processing
        for path in $infra_paths {
            let result = (validate_for_agent $path --auto_fix=$auto_fix)
            $batch_results = ($batch_results | append {
                infra_path: $path
                result: $result
                timestamp: (date now)
            })
        }
    }

    # Aggregate batch results
    let total_issues = ($batch_results | each {|r| $r.result.summary.total_issues} | math sum)
    let total_critical = ($batch_results | each {|r| $r.result.summary.critical_count} | math sum)
    let total_errors = ($batch_results | each {|r| $r.result.summary.error_count} | math sum)
    let can_all_proceed = ($batch_results | all {|r| $r.result.can_proceed_with_deployment})

    {
        batch_summary: {
            infrastructures_processed: ($infra_paths | length)
            total_issues: $total_issues
            total_critical: $total_critical
            total_errors: $total_errors
            all_safe_for_deployment: $can_all_proceed
            processing_mode: (if $parallel { "parallel" } else { "sequential" })
        }
        individual_results: $batch_results
        recommendations: (generate_batch_recommendations $batch_results)
    }
}

def generate_batch_recommendations [batch_results: list]: nothing -> list {
    mut recommendations = []

    let critical_infrastructures = ($batch_results | where $it.result.summary.critical_count > 0)
    let error_infrastructures = ($batch_results | where $it.result.summary.error_count > 0)

    if ($critical_infrastructures | length) > 0 {
        $recommendations = ($recommendations | append {
            action: "prioritize_critical_fixes"
            affected_infrastructures: ($critical_infrastructures | get infra_path)
            urgency: "immediate"
        })
    }

    if ($error_infrastructures | length) > 0 {
        $recommendations = ($recommendations | append {
            action: "schedule_error_fixes"
            affected_infrastructures: ($error_infrastructures | get infra_path)
            urgency: "high"
        })
    }

    $recommendations
}

# Helper functions for extracting information from issues
def extract_component_from_issue [issue: record]: nothing -> string {
    # Extract component name from issue details
    $issue.details | str replace --regex '.*?(\w+).*' '$1'
}

def extract_current_version [issue: record]: nothing -> string {
    # Extract current version from issue details
    $issue.details | parse --regex 'version (\d+\.\d+\.\d+)' | get -o 0.capture1 | default "unknown"
}

def extract_recommended_version [issue: record]: nothing -> string {
    # Extract recommended version from suggested fix
    $issue.suggested_fix | parse --regex 'to (\d+\.\d+\.\d+)' | get -o 0.capture1 | default "latest"
}

def extract_security_area [issue: record]: nothing -> string {
    # Extract security area from issue message
    if ($issue.message | str contains "SSH") {
        "ssh_configuration"
    } else if ($issue.message | str contains "port") {
        "network_security"
    } else if ($issue.message | str contains "credential") {
        "credential_management"
    } else {
        "general_security"
    }
}

def extract_resource_type [issue: record]: nothing -> string {
    # Extract resource type from issue context
    if ($issue.file | str contains "server") {
        "compute"
    } else if ($issue.file | str contains "network") {
        "networking"
    } else if ($issue.file | str contains "storage") {
        "storage"
    } else {
        "general"
    }
}

# Webhook interface for external systems
export def webhook_validate [
    webhook_data: record
]: nothing -> record {
    let infra_path = ($webhook_data | get -o infra_path | default "")
    let auto_fix = ($webhook_data | get -o auto_fix | default false)
    let callback_url = ($webhook_data | get -o callback_url | default "")

    if ($infra_path | is-empty) {
        return {
            status: "error"
            message: "infra_path is required"
            timestamp: (date now)
        }
    }

    let validation_result = (validate_for_agent $infra_path --auto_fix=$auto_fix)

    let response = {
        status: "completed"
        validation_result: $validation_result
        timestamp: (date now)
        webhook_id: ($webhook_data | get -o webhook_id | default (random uuid))
    }

    # If callback URL provided, send result
    if ($callback_url | is-not-empty) {
        try {
            http post $callback_url $response
        } catch {
            # Log callback failure but don't fail the validation
        }
    }

    $response
}