# Validation Rules Engine
# Defines and manages validation rules for infrastructure configurations

use config_loader.nu *

# Main function to get all validation rules (now config-driven)
export def get_all_validation_rules [
    context?: record
]: nothing -> list {
    let config = (load_validation_config)
    load_rules_from_config $config $context
}

# YAML Syntax Validation Rule
export def get_yaml_syntax_rule []: nothing -> record {
    {
        id: "VAL001"
        category: "syntax"
        severity: "critical"
        name: "YAML Syntax Validation"
        description: "Validate YAML files have correct syntax and can be parsed"
        files_pattern: '.*\.ya?ml$'
        validator: "validate_yaml_syntax"
        auto_fix: true
        fix_function: "fix_yaml_syntax"
        tags: ["syntax", "yaml", "critical"]
    }
}

# KCL Compilation Rule
export def get_kcl_compilation_rule []: nothing -> record {
    {
        id: "VAL002"
        category: "compilation"
        severity: "critical"
        name: "KCL Compilation Check"
        description: "Validate KCL files compile successfully"
        files_pattern: '.*\.k$'
        validator: "validate_kcl_compilation"
        auto_fix: false
        fix_function: null
        tags: ["kcl", "compilation", "critical"]
    }
}

# Unquoted Variables Rule
export def get_unquoted_variables_rule []: nothing -> record {
    {
        id: "VAL003"
        category: "syntax"
        severity: "error"
        name: "Unquoted Variable References"
        description: "Check for unquoted variable references in YAML that cause parsing errors"
        files_pattern: '.*\.ya?ml$'
        validator: "validate_quoted_variables"
        auto_fix: true
        fix_function: "fix_unquoted_variables"
        tags: ["yaml", "variables", "syntax"]
    }
}

# Missing Required Fields Rule
export def get_missing_required_fields_rule []: nothing -> record {
    {
        id: "VAL004"
        category: "schema"
        severity: "error"
        name: "Required Fields Validation"
        description: "Validate that all required fields are present in configuration files"
        files_pattern: '.*\.(k|ya?ml)$'
        validator: "validate_required_fields"
        auto_fix: false
        fix_function: null
        tags: ["schema", "required", "fields"]
    }
}

# Resource Naming Convention Rule
export def get_resource_naming_rule []: nothing -> record {
    {
        id: "VAL005"
        category: "best_practices"
        severity: "warning"
        name: "Resource Naming Conventions"
        description: "Validate resource names follow established conventions"
        files_pattern: '.*\.(k|ya?ml)$'
        validator: "validate_naming_conventions"
        auto_fix: true
        fix_function: "fix_naming_conventions"
        tags: ["naming", "conventions", "best_practices"]
    }
}

# Security Basics Rule
export def get_security_basics_rule []: nothing -> record {
    {
        id: "VAL006"
        category: "security"
        severity: "error"
        name: "Basic Security Checks"
        description: "Validate basic security configurations like SSH keys, exposed ports"
        files_pattern: '.*\.(k|ya?ml)$'
        validator: "validate_security_basics"
        auto_fix: false
        fix_function: null
        tags: ["security", "ssh", "ports"]
    }
}

# Version Compatibility Rule
export def get_version_compatibility_rule []: nothing -> record {
    {
        id: "VAL007"
        category: "compatibility"
        severity: "warning"
        name: "Version Compatibility Check"
        description: "Check for deprecated versions and compatibility issues"
        files_pattern: '.*\.(k|ya?ml|toml)$'
        validator: "validate_version_compatibility"
        auto_fix: false
        fix_function: null
        tags: ["versions", "compatibility", "deprecation"]
    }
}

# Network Configuration Rule
export def get_network_validation_rule []: nothing -> record {
    {
        id: "VAL008"
        category: "networking"
        severity: "error"
        name: "Network Configuration Validation"
        description: "Validate network configurations, CIDR blocks, and IP assignments"
        files_pattern: '.*\.(k|ya?ml)$'
        validator: "validate_network_config"
        auto_fix: false
        fix_function: null
        tags: ["networking", "cidr", "ip"]
    }
}

# Rule execution functions

export def execute_rule [
    rule: record
    file: string
    context: record
]: nothing -> record {
    let function_name = $rule.validator_function

    # Create rule-specific context
    let rule_context = (create_rule_context $rule $context)

    # Execute the validation function based on the rule configuration
    match $function_name {
        "validate_yaml_syntax" => (validate_yaml_syntax $file)
        "validate_kcl_compilation" => (validate_kcl_compilation $file)
        "validate_quoted_variables" => (validate_quoted_variables $file)
        "validate_required_fields" => (validate_required_fields $file)
        "validate_naming_conventions" => (validate_naming_conventions $file)
        "validate_security_basics" => (validate_security_basics $file)
        "validate_version_compatibility" => (validate_version_compatibility $file)
        "validate_network_config" => (validate_network_config $file)
        _ => {
            {
                passed: false
                issue: {
                    rule_id: $rule.id
                    severity: "error"
                    file: $file
                    line: null
                    message: $"Unknown validation function: ($function_name)"
                    details: $"Rule ($rule.id) references unknown validator function"
                    suggested_fix: "Check rule configuration and validator function name"
                    auto_fixable: false
                }
            }
        }
    }
}

export def execute_fix [
    rule: record
    issue: record
    context: record
]: nothing -> record {
    let function_name = ($rule.fix_function | default "")

    if ($function_name | is-empty) {
        return { success: false, message: "No fix function defined for this rule" }
    }

    # Create rule-specific context
    let rule_context = (create_rule_context $rule $context)

    # Execute the fix function based on the rule configuration
    match $function_name {
        "fix_yaml_syntax" => (fix_yaml_syntax $issue.file $issue)
        "fix_unquoted_variables" => (fix_unquoted_variables $issue.file $issue)
        "fix_naming_conventions" => (fix_naming_conventions $issue.file $issue)
        _ => {
            { success: false, message: $"Unknown fix function: ($function_name)" }
        }
    }
}

export def validate_yaml_syntax [file: string, context?: record]: nothing -> record {
    let content = (open $file --raw)

    # Try to parse as YAML using error handling
    try {
        $content | from yaml | ignore
        { passed: true, issue: null }
    } catch { |error|
        {
            passed: false
            issue: {
                rule_id: "VAL001"
                severity: "critical"
                file: $file
                line: null
                message: "YAML syntax error"
                details: $error.msg
                suggested_fix: "Fix YAML syntax errors"
                auto_fixable: false
            }
        }
    }
}

export def validate_quoted_variables [file: string]: nothing -> record {
    let content = (open $file --raw)
    let lines = ($content | lines | enumerate)

    let unquoted_vars = ($lines | where {|line|
        $line.item =~ '\s+\w+:\s+\$\w+'
    })

    if ($unquoted_vars | length) > 0 {
        let first_issue = ($unquoted_vars | first)
        let variable_name = ($first_issue.item | parse --regex '\s+\w+:\s+(\$\w+)' | get -o 0.capture1 | default "unknown")

        {
            passed: false
            issue: {
                rule_id: "VAL003"
                severity: "error"
                file: $file
                line: ($first_issue.index + 1)
                message: $"Unquoted variable reference: ($variable_name)"
                details: ($first_issue.item | str trim)
                suggested_fix: $"Quote the variable: \"($variable_name)\""
                auto_fixable: true
                variable_name: $variable_name
                all_occurrences: $unquoted_vars
            }
        }
    } else {
        { passed: true, issue: null }
    }
}

export def validate_kcl_compilation [file: string]: nothing -> record {
    # Check if KCL compiler is available
    try {
        ^bash -c "type -P kcl" | ignore

        # Try to compile the KCL file
        try {
            ^kcl $file | ignore
            { passed: true, issue: null }
        } catch { |error|
            {
                passed: false
                issue: {
                    rule_id: "VAL002"
                    severity: "critical"
                    file: $file
                    line: null
                    message: "KCL compilation failed"
                    details: $error.msg
                    suggested_fix: "Fix KCL syntax and compilation errors"
                    auto_fixable: false
                }
            }
        }
    } catch {
        {
            passed: false
            issue: {
                rule_id: "VAL002"
                severity: "critical"
                file: $file
                line: null
                message: "KCL compiler not available"
                details: "kcl command not found in PATH"
                suggested_fix: "Install KCL compiler or add to PATH"
                auto_fixable: false
            }
        }
    }
}

export def validate_required_fields [file: string]: nothing -> record {
    # Basic implementation - will be expanded based on schema definitions
    let content = (open $file --raw)

    # Check for common required fields based on file type
    if ($file | str ends-with ".k") {
        # KCL server configuration checks
        if ($content | str contains "servers") and (not ($content | str contains "hostname")) {
            {
                passed: false
                issue: {
                    rule_id: "VAL004"
                    severity: "error"
                    file: $file
                    line: null
                    message: "Missing required field: hostname"
                    details: "Server definition missing hostname field"
                    suggested_fix: "Add hostname field to server configuration"
                    auto_fixable: false
                }
            }
        } else {
            { passed: true, issue: null }
        }
    } else {
        { passed: true, issue: null }
    }
}

export def validate_naming_conventions [file: string]: nothing -> record {
    # Placeholder implementation
    { passed: true, issue: null }
}

export def validate_security_basics [file: string]: nothing -> record {
    # Placeholder implementation
    { passed: true, issue: null }
}

export def validate_version_compatibility [file: string]: nothing -> record {
    # Placeholder implementation
    { passed: true, issue: null }
}

export def validate_network_config [file: string]: nothing -> record {
    # Placeholder implementation
    { passed: true, issue: null }
}

# Auto-fix functions

export def fix_yaml_syntax [file: string, issue: record]: nothing -> record {
    # Placeholder for YAML syntax fixes
    { success: false, message: "YAML syntax auto-fix not implemented yet" }
}

export def fix_unquoted_variables [file: string, issue: record]: nothing -> record {
    let content = (open $file --raw)

    # Fix unquoted variables by adding quotes
    let fixed_content = ($content | str replace --all $'($issue.variable_name)' $'"($issue.variable_name)"')

    # Save the fixed content
    $fixed_content | save --force $file

    {
        success: true
        message: $"Fixed unquoted variable ($issue.variable_name) in ($file)"
        changes_made: [
            {
                type: "variable_quoting"
                variable: $issue.variable_name
                action: "added_quotes"
            }
        ]
    }
}

export def fix_naming_conventions [file: string, issue: record]: nothing -> record {
    # Placeholder for naming convention fixes
    { success: false, message: "Naming convention auto-fix not implemented yet" }
}