# Info: KCL Polkadot Node task schemas for provisioning (Provisioning)
# Author: Provisioning System
# Release: 0.0.1
# Date: 2025-07-24

import regex

schema User:
    """
    User settings for Polkadot node
    """
    name: str
    group: str = name
    home?: str = "/home/${name}"

schema SSL:
    """
    SSL certificate configuration
    """
    enabled: bool = False
    cert_file?: str
    key_file?: str
    ca_file?: str
    
    check:
        not enabled or cert_file != Undefined and len(cert_file) > 0, "cert_file required when SSL enabled"
        not enabled or key_file != Undefined and len(key_file) > 0, "key_file required when SSL enabled"

schema WSS:
    """
    Secure WebSocket configuration
    """
    enabled: bool = False
    port: int = 443
    domain?: str
    proxy_type: "nginx" | "apache" = "nginx"
    rate_limit: int = 100  # requests per minute
    ssl: SSL = {}
    
    check:
        1 <= port <= 65535, "WSS port must be between 1 and 65535"
        not enabled or ssl.enabled, "SSL must be enabled for WSS"
        not enabled or domain != Undefined and len(domain) > 0, "domain required for WSS"

schema Pruning:
    """
    Pruning configuration for Polkadot node
    """
    enabled: bool = True
    mode: "state" | "block" | "both" = "state"
    blocks_to_keep: int = 256
    state_pruning: int = 256
    block_pruning?: int = 256 if mode == "block" else Undefined
    
    check:
        blocks_to_keep > 0, "blocks_to_keep must be positive"
        state_pruning > 0, "state_pruning must be positive" 
        block_pruning == Undefined or block_pruning > 0, "block_pruning must be positive if set"

schema Network:
    """
    Network configuration
    """
    chain: "polkadot" | "kusama" | "westend" = "polkadot"
    listen_addr: str = "/ip4/0.0.0.0/tcp/30333"
    public_addr?: str
    bootnodes: [str] = []
    reserved_nodes: [str] = []
    reserved_only: bool = False
    max_peers: int = 50
    max_peers_light: int = 100
    
    check:
        max_peers > 0, "max_peers must be positive"
        max_peers_light > 0, "max_peers_light must be positive"

schema RPC:
    """
    RPC configuration
    """
    enabled: bool = True
    bind_addr: str = "127.0.0.1"
    port: int = 9944
    ws_port: int = 9944
    http_port: int = 9933
    max_connections: int = 100
    cors: [str] = ["all"]
    methods: [str] = ["safe"]
    rate_limit?: int = 1000  # requests per minute
    
    check:
        1 <= port <= 65535, "RPC port must be between 1 and 65535"
        1 <= ws_port <= 65535, "WebSocket port must be between 1 and 65535"
        1 <= http_port <= 65535, "HTTP port must be between 1 and 65535"
        max_connections > 0, "max_connections must be positive"

schema Telemetry:
    """
    Telemetry configuration
    """
    enabled: bool = True
    url: str = "wss://telemetry.polkadot.io/submit/"
    verbosity: int = 0
    
    check:
        0 <= verbosity <= 9, "verbosity must be between 0 and 9"

schema PolkadotNode:
    """
    Polkadot node configuration
    """
    name: str = "polkadot-node"
    version: str = "latest"
    node_type: "full" | "light" | "validator" = "full"
    sync_mode: "full" | "fast" | "warp" = "warp"
    pruning: Pruning = {}
    archive_mode: bool = False
    run_user: User = {
        name = "polkadot"
    }
    work_path: str = "/var/lib/polkadot"
    config_path: str = "/etc/polkadot"
    bin_path: str = "/usr/local/bin/polkadot"
    base_path: str = "/var/lib/polkadot/data"
    network: Network = {}
    rpc: RPC = {}
    telemetry: Telemetry = {}
    wss: WSS = {}
    log_level: "error" | "warn" | "info" | "debug" | "trace" = "info"
    log_targets: [str] = []
    execution: "native" | "wasm" | "both" = "wasm"
    wasm_execution: "compiled" | "interpreted" = "compiled"
    state_cache_size: int = 67108864  # 64MB
    db_cache: int = 1024  # MB
    
    check:
        len(run_user.name) > 0, "Check run_user name"
        len(work_path) > 0, "Check work_path"
        len(config_path) > 0, "Check config_path"
        len(base_path) > 0, "Check base_path"
        state_cache_size > 0, "state_cache_size must be positive"
        db_cache > 0, "db_cache must be positive"
        not (archive_mode and pruning.enabled), "Cannot enable both archive mode and pruning"