"""
Network Configuration Types for Network IO Operations.

Provides type definitions for all network builtin configurations
matching the TypeScript CLM_Network_IO_Specification.
"""

from dataclasses import dataclass, field
from typing import Any, Dict, List, Literal, Optional, Union
from enum import Enum


# ============ HTTP Configuration ============

class HttpMethod(Enum):
    """HTTP methods supported by the runtime."""
    GET = "GET"
    POST = "POST"
    PUT = "PUT"
    DELETE = "DELETE"
    PATCH = "PATCH"
    HEAD = "HEAD"
    OPTIONS = "OPTIONS"


class ResponseType(Enum):
    """Response body parsing type."""
    JSON = "json"
    TEXT = "text"
    BINARY = "binary"
    STREAM = "stream"


class BackoffStrategy(Enum):
    """Retry backoff strategy."""
    EXPONENTIAL = "exponential"
    LINEAR = "linear"
    CONSTANT = "constant"


class SyncMode(Enum):
    """MCard sync mode."""
    PUSH = "push"
    PULL = "pull"
    BOTH = "both"
    BIDIRECTIONAL = "bidirectional"


@dataclass
class RetryConfig:
    """Retry configuration for HTTP requests."""
    max_attempts: int = 1
    backoff: BackoffStrategy = BackoffStrategy.EXPONENTIAL
    base_delay: int = 1000  # ms
    max_delay: Optional[int] = 30000  # ms
    retry_on: Optional[List[int]] = None  # HTTP status codes to retry


@dataclass
class CacheConfig:
    """Response caching configuration."""
    enabled: bool = False
    ttl: int = 300  # seconds
    key: Optional[str] = None  # Custom cache key
    storage: Literal["mcard", "memory"] = "memory"


@dataclass
class TimeoutConfig:
    """Timeout configuration for HTTP requests."""
    connect: Optional[int] = None  # Connection timeout (ms)
    read: Optional[int] = None  # Read timeout (ms)
    total: Optional[int] = 30000  # Total request timeout (ms)


@dataclass
class HttpRequestConfig:
    """Full HTTP request configuration."""
    url: str
    method: HttpMethod = HttpMethod.GET
    headers: Optional[Dict[str, str]] = None
    body: Optional[Union[str, Dict]] = None
    query_params: Optional[Dict[str, str]] = None
    timeout: Optional[Union[int, TimeoutConfig]] = None
    response_type: ResponseType = ResponseType.JSON
    retry: Optional[RetryConfig] = None
    cache: Optional[CacheConfig] = None
    validate_ssl: bool = True
    follow_redirects: bool = True
    max_redirects: int = 5


# ============ HTTP Response ============

@dataclass
class HttpTiming:
    """HTTP request timing metrics."""
    dns: int = 0  # DNS lookup (ms)
    connect: int = 0  # Connection time (ms)
    ttfb: int = 0  # Time to first byte (ms)
    total: int = 0  # Total request time (ms)


@dataclass
class HttpError:
    """HTTP error details."""
    code: Literal["TIMEOUT", "CONNECTION_REFUSED", "SSL_ERROR", "HTTP_ERROR", "UNKNOWN"]
    message: str
    status: Optional[int] = None
    retries_attempted: int = 0


@dataclass
class HttpSuccessResponse:
    """Successful HTTP response."""
    success: Literal[True]
    status: int
    headers: Dict[str, str]
    body: Any
    timing: HttpTiming
    mcard_hash: Optional[str] = None
    cached: bool = False


@dataclass
class HttpErrorResponse:
    """Failed HTTP response."""
    success: Literal[False]
    error: HttpError


# ============ MCard Transfer ============

@dataclass
class MCardPayload:
    """MCard serialization payload for network transfer."""
    hash: str
    content: str  # Base64 encoded
    g_time: str
    content_type: str
    hash_function: str


@dataclass
class MCardSendConfig:
    """MCard send configuration."""
    url: str
    hash: str  # Hash of MCard to send (supports ${} interpolation)
    headers: Optional[Dict[str, str]] = None


@dataclass
class ListenHttpConfig:
    """HTTP listener configuration."""
    port: int = 3000
    path: str = "/mcard"


# ============ Sync Protocol ============

@dataclass
class MCardSyncConfig:
    """MCard synchronization configuration."""
    url: str  # Base URL for sync server
    mode: SyncMode = SyncMode.PULL
    headers: Optional[Dict[str, str]] = None


@dataclass
class ListenSyncConfig:
    """Sync server listener configuration."""
    port: int = 3000
    base_path: str = "/sync"


@dataclass
class SyncStats:
    """Synchronization statistics."""
    mode: str
    local_total: int
    remote_total: int
    synced: int
    pushed: Optional[int] = None
    pulled: Optional[int] = None


@dataclass
class SyncResult:
    """Synchronization result."""
    success: bool
    stats: SyncStats


# ============ URL Loading ============

@dataclass
class LoadUrlExtractConfig:
    """URL content extraction configuration."""
    mode: Literal["auto", "html", "pdf", "raw"] = "auto"
    selector: Optional[str] = None  # CSS selector for HTML
    remove: Optional[List[str]] = None  # Elements to remove


@dataclass
class LoadUrlProcessConfig:
    """URL content processing configuration."""
    clean_html: bool = False
    normalize_whitespace: bool = False
    max_length: Optional[int] = None


@dataclass 
class LoadUrlConfig:
    """URL loading configuration."""
    url: str
    extract: Optional[LoadUrlExtractConfig] = None
    process: Optional[LoadUrlProcessConfig] = None
    cache: Optional[CacheConfig] = None


@dataclass
class LoadUrlResult:
    """URL loading result."""
    url: str
    content: str
    status: int
    headers: Dict[str, str]
    mcard_hash: Optional[str] = None


# ============ Security Configuration ============

@dataclass
class NetworkSecurityConfig:
    """Network security policy configuration.
    
    Environment Variables:
    - CLM_ALLOWED_DOMAINS: Comma-separated list of allowed domains
    - CLM_BLOCKED_DOMAINS: Comma-separated list of blocked domains (takes precedence)
    - CLM_ALLOWED_PROTOCOLS: Comma-separated protocols (default: "https,http")
    - CLM_BLOCK_PRIVATE_IPS: Set to "true" to block private IP ranges
    - CLM_BLOCK_LOCALHOST: Set to "true" to block localhost/127.0.0.1
    """
    allowed_domains: Optional[List[str]] = None
    blocked_domains: Optional[List[str]] = None
    allowed_protocols: Optional[List[str]] = None
    block_private_ips: bool = False
    block_localhost: bool = False


@dataclass
class SecurityViolationError:
    """Security policy violation error."""
    code: Literal[
        "DOMAIN_BLOCKED",
        "DOMAIN_NOT_ALLOWED", 
        "PROTOCOL_NOT_ALLOWED",
        "PRIVATE_IP_BLOCKED",
        "LOCALHOST_BLOCKED"
    ]
    message: str
    url: str


# ============ WebRTC Configuration ============

@dataclass
class IceServer:
    """ICE server configuration for WebRTC."""
    urls: Union[str, List[str]]
    username: Optional[str] = None
    credential: Optional[str] = None


@dataclass
class WebRTCConfig:
    """Base WebRTC configuration."""
    signaling_url: str
    ice_servers: Optional[List[IceServer]] = None
    peer_id: Optional[str] = None


@dataclass
class WebRTCConnectConfig(WebRTCConfig):
    """WebRTC connection initiator configuration."""
    target_peer_id: str = ""
    message: Optional[Union[str, Dict]] = None
    await_response: bool = True
    timeout: int = 30000  # ms


@dataclass
class WebRTCListenConfig(WebRTCConfig):
    """WebRTC listener configuration."""
    allowed_peers: Optional[List[str]] = None
    on_message: Optional[str] = None  # Handler name


# ============ Session Recording ============

@dataclass
class SessionRecordConfig:
    """P2P session recording configuration."""
    operation: Literal["init", "add", "flush", "batch", "summarize"]
    session_id: str
    sender: Optional[str] = None
    content: Optional[str] = None
    max_buffer_size: int = 5
    initial_head_hash: Optional[str] = None
    operations: Optional[List["SessionRecordConfig"]] = None
    keep_originals: bool = True


@dataclass
class MCardReadConfig:
    """MCard read operation configuration."""
    hash: str
    parse_json: bool = True


# ============ CLM Boundary Types ============

class BoundaryType(Enum):
    """CLM execution boundary type.
    
    Intrinsic: Process runs within the same execution context
    Extrinsic: Process runs in a separate process/container/network
    """
    INTRINSIC = "intrinsic"
    EXTRINSIC = "extrinsic"


@dataclass
class ProcessBoundary:
    """Process boundary configuration for CLM execution."""
    boundary_type: BoundaryType = BoundaryType.INTRINSIC
    timeout: int = 30000  # ms
    env: Optional[Dict[str, str]] = None
    working_dir: Optional[str] = None

