# Override Utilities for Layered Template System
# Provides utilities for managing configuration overrides across layers

import workspace_templates.lib.compose as comp

# Layer resolution utilities
schema LayerResolution {
    # Layer priority levels
    CORE_LAYER: int = 100
    WORKSPACE_LAYER: int = 200
    INFRA_LAYER: int = 300

    # Resolve configuration through layer hierarchy
    resolve_layers: def [
        core_config: any = {},
        workspace_config: any = {},
        infra_config: any = {}
    ] -> any {
        comp.compose_templates $core_config $workspace_config $infra_config
    }

    # Apply selective overrides (only specified fields)
    selective_override: def [
        base: any,
        overrides: any,
        allowed_fields: list<str>
    ] -> any {
        let filtered_overrides = $overrides | select ...$allowed_fields
        comp.deep_merge $base $filtered_overrides
    }

    # Conditional override based on infrastructure name
    infra_conditional: def [
        base: any,
        infra_name: str,
        conditions: {str: any}
    ] -> any {
        let override_config = if $infra_name in $conditions {
            $conditions.($infra_name)
        } else if "default" in $conditions {
            $conditions.default
        } else {
            {}
        }
        comp.deep_merge $base $override_config
    }
}

# Override patterns for common use cases
schema OverridePatterns {
    # Network override pattern
    network_override: def [
        base_network: any,
        infra_name: str,
        network_overrides: any = {}
    ] -> any {
        let default_overrides = {
            network_private_name: $"($infra_name)-network"
            network_private_id: "CREATE"
        }

        comp.deep_merge $base_network $default_overrides | comp.deep_merge $network_overrides
    }

    # Cluster naming override pattern
    cluster_override: def [
        base_config: any,
        cluster_name: str,
        node_overrides: any = {}
    ] -> any {
        let cluster_overrides = {
            cluster_name: $cluster_name
            cp_name: $"($cluster_name)-cp-0"
        }

        comp.deep_merge $base_config $cluster_overrides | comp.deep_merge $node_overrides
    }

    # Version override pattern
    version_override: def [
        base_config: any,
        version_config: {str: str}
    ] -> any {
        comp.deep_merge $base_config $version_config
    }

    # Environment-specific override pattern
    env_override: def [
        base_config: any,
        environment: str,
        env_configs: {str: any}
    ] -> any {
        let env_config = if $environment in $env_configs {
            $env_configs.($environment)
        } else if "default" in $env_configs {
            $env_configs.default
        } else {
            {}
        }

        comp.deep_merge $base_config $env_config
    }
}

# Infrastructure-specific override helpers
schema InfrastructureOverrides {
    # Create infrastructure-specific configuration
    create_infra_config: def [
        template_config: any,
        infra_name: str,
        provider: str,
        domain: str,
        custom_overrides: any = {}
    ] -> any {
        let infra_defaults = {
            # Common infrastructure naming
            cluster_name: $infra_name
            cp_name: $"($infra_name)-cp-0"

            # Network naming
            network_private_name: $"($infra_name)-network"

            # Domain configuration
            main_domain: $domain
            domains_search: $domain
        }

        let provider_specific = match $provider {
            "upcloud" => {
                zone: "es-mad1"
                priv_cidr_block: "10.11.0.0/24"
            },
            "aws" => {
                region: "us-west-2"
                vpc_cidr: "10.0.0.0/16"
            },
            _ => {}
        }

        # Compose: template -> infra_defaults -> provider_specific -> custom
        comp.compose_templates $template_config $infra_defaults $provider_specific $custom_overrides
    }

    # Apply taskserv-specific overrides
    taskserv_override: def [
        base_taskserv: any,
        infra_name: str,
        taskserv_type: str,
        custom_config: any = {}
    ] -> any {
        let taskserv_defaults = match $taskserv_type {
            "kubernetes" => {
                cluster_name: $infra_name
                cp_name: $"($infra_name)-cp-0"
            },
            "rook-ceph" => {
                cluster_name: $infra_name
                namespace: $"($infra_name)-storage"
            },
            "cilium" => {
                cluster_name: $infra_name
                helm_namespace: "kube-system"
            },
            _ => {}
        }

        comp.deep_merge $base_taskserv $taskserv_defaults | comp.deep_merge $custom_config
    }
}

# Export override utilities
layer_resolution = LayerResolution {}
override_patterns = OverridePatterns {}
infrastructure_overrides = InfrastructureOverrides {}
