# Enhanced validation utilities for provisioning tool

export def validate-required [
    value: any
    name: string
    context?: string
] {
    if ($value | is-empty) {
        print $"🛑 Required parameter '($name)' is missing or empty"
        if ($context | is-not-empty) {
            print $"Context: ($context)"
        }
        print $"💡 Please provide a value for '($name)'"
        return false
    }
    true
}

export def validate-path [
    path: string
    context?: string
    --must-exist
] {
    if ($path | is-empty) {
        print "🛑 Path parameter is empty"
        if ($context | is-not-empty) {
            print $"Context: ($context)"
        }
        return false
    }

    if $must_exist and not ($path | path exists) {
        print $"🛑 Path '($path)' does not exist"
        if ($context | is-not-empty) {
            print $"Context: ($context)"
        }
        print "💡 Check if the path exists and you have proper permissions"
        return false
    }

    true
}

export def validate-command [
    command: string
    context?: string
] {
    let cmd_exists = (^bash -c $"type -P ($command)" | complete)
    if $cmd_exists.exit_code != 0 {
        print $"🛑 Command '($command)' not found in PATH"
        if ($context | is-not-empty) {
            print $"Context: ($context)"
        }
        print $"💡 Install '($command)' or add it to your PATH"
        return false
    }
    true
}

export def safe-execute [
    command: closure
    context: string
    --fallback: closure
] {
    let result = (do $command | complete)
    if $result.exit_code != 0 {
        print $"⚠️  Warning: Error in ($context): ($result.stderr)"
        if $fallback != null {
            print "🔄 Executing fallback..."
            do $fallback
        } else {
            print $"🛑 Execution failed in ($context)"
            print $"Error: ($result.stderr)"
        }
    } else {
        $result.stdout
    }
}

export def validate-settings [
    settings: record
    required_fields: list
] {
    # Guard: Check for missing required fields (no try-catch)
    let missing_fields = ($required_fields | where {|field|
        not ($field in $settings) or (($settings | get $field) | is-empty)
    })

    if ($missing_fields | length) > 0 {
        print "🛑 Missing required settings fields:"
        $missing_fields | each {|field| print $"  - ($field)"}
        return false
    }
    true
}

# ============================================================================
# NICKEL VALIDATION (TYPE-SAFE CONFIGS)
# ============================================================================

# Check if Nickel is installed and available
export def check-nickel-available [] {
    let nickel_check = (do { which nickel } | complete)

    if ($nickel_check.exit_code == 0) {
        let version_output = (do { nickel --version } | complete).stdout | str trim
        return {
            available: true
            version: $version_output
        }
    }

    {
        available: false
        version: null
        error: "Nickel is not installed or not found in PATH"
    }
}

# Validate Nickel configuration using nickel typecheck
export def validate-nickel-typecheck [
    config_path: path
] {
    if not ($config_path | path exists) {
        print-setup-error $"Config file not found: ($config_path)"
        return false
    }

    # Check if nickel command is available
    let nickel_check = (do { which nickel } | complete)
    if ($nickel_check.exit_code != 0) {
        print-setup-warning "Nickel not installed - typecheck validation skipped"
        return true  # Don't block if Nickel not available
    }

    # Run nickel typecheck
    let validation = (do { nickel typecheck $config_path } | complete)

    if ($validation.exit_code == 0) {
        return true
    } else {
        print-setup-error $"Nickel typecheck failed for ($config_path)"
        if ($validation.stderr | is-not-empty) {
            print-setup-error $"Error: ($validation.stderr)"
        }
        return false
    }
}

# Validate Nickel configuration against schema
export def validate-nickel-schema [
    config_path: path
    schema_path: path
] {
    if not ($config_path | path exists) {
        print-setup-error $"Config file not found: ($config_path)"
        return false
    }

    if not ($schema_path | path exists) {
        print-setup-error $"Schema file not found: ($schema_path)"
        return false
    }

    # Check if nickel command is available
    let nickel_check = (do { which nickel } | complete)
    if ($nickel_check.exit_code != 0) {
        print-setup-warning "Nickel not installed - schema validation skipped"
        return true
    }

    # For schema validation, we need to check the import chain
    # This is a simplified validation that checks typecheck passes
    let validation = (do { nickel typecheck $config_path } | complete)

    if ($validation.exit_code == 0) {
        return true
    } else {
        print-setup-error $"Nickel schema validation failed for ($config_path)"
        if ($validation.stderr | is-not-empty) {
            print-setup-error $"Error: ($validation.stderr)"
        }
        return false
    }
}

# Validate Nickel composition (base + overlay)
export def validate-nickel-composition [
    base_path: path
    overlay_path: path
] {
    if not ($base_path | path exists) {
        print-setup-error $"Base config not found: ($base_path)"
        return false
    }

    if not ($overlay_path | path exists) {
        print-setup-error $"Overlay config not found: ($overlay_path)"
        return false
    }

    # Check if nickel command is available
    let nickel_check = (do { which nickel } | complete)
    if ($nickel_check.exit_code != 0) {
        print-setup-warning "Nickel not installed - composition validation skipped"
        return true
    }

    # Validate both configs individually first
    let base_validation = (do { nickel typecheck $base_path } | complete)
    let overlay_validation = (do { nickel typecheck $overlay_path } | complete)

    if ($base_validation.exit_code != 0) {
        print-setup-error $"Base composition validation failed for ($base_path)"
        return false
    }

    if ($overlay_validation.exit_code != 0) {
        print-setup-error $"Overlay composition validation failed for ($overlay_path)"
        return false
    }

    return true
}

# Validate all Nickel configs in a directory
export def validate-all-nickel-configs [
    config_dir: path
] {
    if not ($config_dir | path exists) {
        print-setup-error $"Config directory not found: ($config_dir)"
        return {
            success: false
            validated: 0
            failed: 0
            errors: ["Config directory not found"]
        }
    }

    # Find all .ncl files in config directory
    let ncl_files = (glob $"($config_dir)/**/*.ncl" | default [])

    if ($ncl_files | is-empty) {
        return {
            success: true
            validated: 0
            failed: 0
            errors: []
        }
    }

    mut validated_count = 0
    mut failed_count = 0
    mut errors = []

    for file in $ncl_files {
        let validation = (validate-nickel-typecheck $file)
        if $validation {
            $validated_count = ($validated_count + 1)
        } else {
            $failed_count = ($failed_count + 1)
            $errors = ($errors | append $file)
        }
    }

    {
        success: ($failed_count == 0)
        validated: $validated_count
        failed: $failed_count
        errors: $errors
    }
}
