# Provider Interface Specification
# Defines the contract that all providers must implement for provider-agnostic operations
#
# AUTHENTICATION NOTE:
# Provider operations are authenticated at the infrastructure command level.
# All provider implementations can assume authentication has been verified before
# these functions are called. Provider API calls should include authentication
# metadata for audit logging purposes.

# Standard provider interface - all providers must implement these functions
export def get-provider-interface [] {
    {
        # Server query operations
        query_servers: {
            signature: "find?: string, cols?: string -> list"
            description: "Query servers with optional find/column filtering"
        }

        # Server information operations
        server_info: {
            signature: "server: record, check: bool, find?: string, cols?: string -> record"
            description: "Get detailed information about a specific server"
        }

        # Server existence and status operations
        server_exists: {
            signature: "server: record, error_exit: bool -> bool"
            description: "Check if server exists in provider"
        }

        server_is_running: {
            signature: "server: record, error_exit: bool -> bool"
            description: "Check if server is in running state"
        }

        # Server lifecycle operations
        check_server_requirements: {
            signature: "settings: record, server: record, check: bool -> bool"
            description: "Validate server configuration meets provider requirements"
        }

        create_server: {
            signature: "settings: record, server: record, check: bool, wait: bool -> bool"
            description: "Create a new server instance"
        }

        delete_server: {
            signature: "settings: record, server: record, keep_storage: bool, error_exit: bool -> bool"
            description: "Delete server instance"
        }

        delete_server_storage: {
            signature: "settings: record, server: record, error_exit: bool -> bool"
            description: "Delete server storage volumes"
        }

        post_create_server: {
            signature: "settings: record, server: record, check: bool -> bool"
            description: "Post-creation server configuration"
        }

        modify_server: {
            signature: "settings: record, server: record, new_values: list, error_exit: bool -> bool"
            description: "Modify server configuration"
        }

        # Server state management
        server_state: {
            signature: "server: record, new_state: string, error_exit: bool, wait: bool, settings: record -> bool"
            description: "Change server state (start/stop/restart)"
        }

        # Network operations
        get_ip: {
            signature: "settings: record, server: record, ip_type: string, error_exit: bool -> string"
            description: "Get server IP address (public/private)"
        }

        servers_ips: {
            signature: "settings: record, data: list, prov?: string, serverpos?: int -> list"
            description: "Get IP addresses for multiple servers"
        }

        # Infrastructure operations
        load_infra_servers_info: {
            signature: "settings: record, server: record, error_exit: bool -> record"
            description: "Load infrastructure server information"
        }

        load_infra_storages_info: {
            signature: "settings: record, server: record, error_exit: bool -> record"
            description: "Load infrastructure storage information"
        }

        get_infra_storage: {
            signature: "server: record, settings: record, cloud_data: record, error_exit: bool -> list"
            description: "Get infrastructure storage details"
        }

        get_infra_item: {
            signature: "server: record, settings: record, cloud_data: record, error_exit: bool -> record"
            description: "Get infrastructure item details"
        }

        get_infra_price: {
            signature: "server: record, data: record, key: string, error_exit: bool, price_col?: string -> float"
            description: "Get infrastructure pricing information"
        }

        # Cache operations
        start_cache_info: {
            signature: "settings: record, server: record -> nothing"
            description: "Initialize cache information"
        }

        create_cache: {
            signature: "settings: record, server: record, error_exit: bool -> nothing"
            description: "Create server cache"
        }

        read_cache: {
            signature: "settings: record, server: record, error_exit: bool -> nothing"
            description: "Read server cache"
        }

        clean_cache: {
            signature: "settings: record, server: record, error_exit: bool -> nothing"
            description: "Clean server cache"
        }

        ip_from_cache: {
            signature: "settings: record, server: record, error_exit: bool -> nothing"
            description: "Get IP from server cache"
        }

        # Provider metadata operations
        on_prov_server: {
            signature: "server: record -> string"
            description: "Get provider display message for server"
        }
    }
}

# Validate that a provider implements the required interface
export def validate-provider-interface [
    provider_name: string
    provider_module: record
] {
    let interface = (get-provider-interface)
    let required_functions = ($interface | columns)

    mut validation_result = {
        provider: $provider_name
        valid: true
        missing_functions: []
        invalid_functions: []
        warnings: []
    }

    # Check each required function
    for function_name in $required_functions {
        let has_function = ($function_name in ($provider_module | columns))
        if not $has_function {
            $validation_result.missing_functions = ($validation_result.missing_functions | append $function_name)
            $validation_result.valid = false
        }
    }

    # Add warnings for extra functions (not required but noted)
    let provider_functions = ($provider_module | columns)
    for function_name in $provider_functions {
        if not ($function_name in $required_functions) {
            $validation_result.warnings = ($validation_result.warnings | append $"Extra function: ($function_name)")
        }
    }

    $validation_result
}

# Get provider interface documentation
export def get-provider-interface-docs [] {
    let interface = (get-provider-interface)

    $interface | transpose function details | each {|row|
        {
            function: $row.function
            signature: $row.details.signature
            description: $row.details.description
        }
    }
}

# Provider capability flags - optional extensions
export def get-provider-capabilities [] {
    {
        # Core capabilities (required for all providers)
        server_management: true
        network_management: true
        storage_management: true

        # Optional capabilities (provider-specific)
        load_balancer: false
        dns_management: false
        cdn: false
        backup_service: false
        monitoring: false
        logging: false

        # Advanced capabilities
        auto_scaling: false
        spot_instances: false
        containers: false
        serverless: false

        # Multi-region support
        multi_region: false

        # Compliance and security
        encryption_at_rest: false
        encryption_in_transit: false
        compliance_certifications: []
    }
}

# Provider interface version
export def get-interface-version [] {
    "1.0.0"
}

# Authentication Guidelines for Provider Implementations
#
# All provider implementations should follow these authentication principles:
#
# 1. **Trust Upstream Authentication**: Provider functions can trust that authentication
#    has been verified at the infrastructure command level before being called.
#
# 2. **Include Auth Metadata**: When making API calls to cloud providers, include
#    authentication metadata in request headers/context for audit trail purposes.
#
# 3. **Log Operations**: Use the auth.nu functions to log operations with user context:
#    ```nushell
#    use ../plugins/auth.nu [log-authenticated-operation, get-auth-metadata]
#
#    def create_server [...] {
#        let auth_metadata = (get-auth-metadata)
#        log-authenticated-operation "provider_create_server" {
#            provider: "aws"
#            server_name: $server.hostname
#            user: $auth_metadata.username
#        }
#        # ... actual implementation
#    }
#    ```
#
# 4. **Provider-Specific Auth**: If the provider has its own authentication system
#    (e.g., AWS credentials, UpCloud API keys), those are configured separately and
#    are independent of the platform authentication system.
#
# 5. **Error Handling**: If a provider operation fails due to provider-specific
#    authentication issues (expired API keys, invalid credentials), return clear
#    error messages that distinguish between platform auth and provider auth:
#    - Platform auth: User not logged into provisioning platform
#    - Provider auth: Cloud provider credentials invalid/expired
#
# Example provider implementation with authentication:
#
# ```nushell
# use ../plugins/auth.nu [log-authenticated-operation, get-auth-metadata]
#
# export def create_server [
#     settings: record
#     server: record
#     check: bool
#     wait: bool
# ] {
#     # Log the operation with user context
#     let auth_metadata = (get-auth-metadata)
#     log-authenticated-operation "aws_create_server" {
#         server_name: $server.hostname
#         region: $server.region
#         instance_type: $server.plan
#         user: $auth_metadata.username
#     }
#
#     # Proceed with AWS-specific implementation
#     # AWS credentials are loaded from AWS config/env (separate from platform auth)
#     # Refactored from try-catch to do/complete for explicit error handling
#     let result = (do { # Create EC2 instance implementation } | complete)
#     if $result.exit_code != 0 {
#         error make {
#             msg: "AWS API error"
#             label: {text: "Check AWS credentials in ~/.aws/credentials"}
#         }
#     }
# }
# ```
