"""Configuration management."""
from __future__ import annotations

import yaml
from pathlib import Path
from dataclasses import dataclass, field


@dataclass
class ModelConfig:
    path: str = ""
    n_ctx: int = 4096
    n_gpu_layers: int = -1
    n_threads: int = 0


@dataclass
class FastModelConfig:
    """Optional small/fast model for immediate preliminary responses."""
    path: str = ""            # Leave empty to disable
    n_ctx: int = 2048
    n_gpu_layers: int = -1
    n_threads: int = 0
    max_tokens: int = 256     # Short answer budget


@dataclass
class CacheConfig:
    enabled: bool = True
    max_entries: int = 10000
    similarity_threshold: float = 0.92


@dataclass
class ApiConfig:
    enabled: bool = True
    host: str = "127.0.0.1"
    port: int = 8420


@dataclass
class TelegramConfig:
    enabled: bool = False
    token: str = ""
    allowed_users: list = field(default_factory=list)


@dataclass
class GatewayConfig:
    telegram: TelegramConfig = field(default_factory=TelegramConfig)
    api: ApiConfig = field(default_factory=ApiConfig)


@dataclass
class NetworkConfig:
    enabled: bool = True
    listen_port: int = 9420
    bootstrap_nodes: list[str] = field(default_factory=list)
    relay_servers: list[str] = field(default_factory=lambda: ["https://hive.1seele.de"])
    marketplace_url: str = ""  # Leer = relay_servers[0]/marketplace wird verwendet


@dataclass
class NodeConfig:
    name: str = ""
    type: str = "auto"
    specialization: str = ""
    expertise_tags: list[str] = field(default_factory=list)


@dataclass
class TrainingConfig:
    enabled: bool = True
    data_dir: str = "data/training"
    lora_path: str = ""


@dataclass
class RAGConfig:
    enabled: bool = True
    data_dir: str = "data/rag"
    chunk_size: int = 512
    top_k: int = 3


@dataclass
class Config:
    node: NodeConfig = field(default_factory=NodeConfig)
    model: ModelConfig = field(default_factory=ModelConfig)
    fast_model: FastModelConfig = field(default_factory=FastModelConfig)
    cache: CacheConfig = field(default_factory=CacheConfig)
    plugins: dict = field(default_factory=lambda: {"enabled": ["chat", "web_search", "pdf_export", "datetime_info", "weather", "news_feed", "link_finder"], "directory": "./plugins"})
    gateway: GatewayConfig = field(default_factory=GatewayConfig)
    network: NetworkConfig = field(default_factory=NetworkConfig)
    training: TrainingConfig = field(default_factory=TrainingConfig)
    rag: RAGConfig = field(default_factory=RAGConfig)

    @classmethod
    def load(cls, path: str | Path = "config.yaml") -> Config:
        path = Path(path)
        if not path.exists():
            return cls()

        with open(path) as f:
            data = yaml.safe_load(f) or {}

        cfg = cls()
        if "model" in data:
            cfg.model = ModelConfig(**data["model"])
        if "fast_model" in data:
            cfg.fast_model = FastModelConfig(**data["fast_model"])
        if "cache" in data:
            cfg.cache = CacheConfig(**data["cache"])
        if "plugins" in data:
            cfg.plugins = data["plugins"]
        if "gateway" in data:
            gw = data["gateway"]
            cfg.gateway = GatewayConfig(
                telegram=TelegramConfig(**gw.get("telegram", {})),
                api=ApiConfig(**gw.get("api", {})),
            )
        if "network" in data:
            import dataclasses as _dc
            _net_fields = {f.name for f in _dc.fields(NetworkConfig)}
            cfg.network = NetworkConfig(**{k: v for k, v in data["network"].items() if k in _net_fields})
        if "training" in data:
            cfg.training = TrainingConfig(**data["training"])
        if "rag" in data:
            cfg.rag = RAGConfig(**data["rag"])
        # Handle extended node fields
        if "node" in data:
            node_data = data["node"]
            cfg.node = NodeConfig(
                name=node_data.get("name", ""),
                type=node_data.get("type", "auto"),
                specialization=node_data.get("specialization", ""),
                expertise_tags=node_data.get("expertise_tags", []),
            )
        return cfg
