"""
Configuration Management Module for KG QA

This module provides centralized configuration management for knowledge graph quality
assurance operations, supporting multiple configuration sources including environment
variables, config files, and programmatic configuration.

Supported Configuration Sources:
    - Environment variables: KG_QA_QUALITY_THRESHOLD, KG_QA_CONSISTENCY_THRESHOLD, etc.
    - Config files: YAML, JSON, TOML formats
    - Programmatic: Python API for setting QA configurations

Algorithms Used:
    - Environment Variable Parsing: OS-level environment variable access
    - YAML Parsing: YAML parser for configuration file loading
    - JSON Parsing: JSON parser for configuration file loading
    - TOML Parsing: TOML parser for configuration file loading
    - Fallback Chain: Priority-based configuration resolution
    - Dictionary Merging: Deep merge algorithms for configuration updates

Key Features:
    - Environment variable support for QA parameters
    - Config file support (YAML, JSON, TOML formats)
    - Programmatic configuration via Python API
    - Method-specific configuration management
    - Automatic fallback chain (config file -> environment -> defaults)
    - Global config instance for easy access

Main Classes:
    - KGQAConfig: Main configuration manager class for kg_qa module

Example Usage:
    >>> from semantica.kg_qa.config import kg_qa_config
    >>> threshold = kg_qa_config.get("quality_threshold", default=0.7)
    >>> kg_qa_config.set("quality_threshold", 0.8)
    >>> method_config = kg_qa_config.get_method_config("assess")
"""

import os
from typing import Optional, Dict, Any
from pathlib import Path

from ..utils.logging import get_logger


class KGQAConfig:
    """Configuration manager for KG QA module - supports .env files, environment variables, and programmatic config."""
    
    def __init__(self, config_file: Optional[str] = None):
        self.logger = get_logger("kg_qa_config")
        self._configs: Dict[str, Any] = {}
        self._method_configs: Dict[str, Dict] = {}
        self._load_config_file(config_file)
        self._load_env_vars()
    
    def _load_config_file(self, config_file: Optional[str]):
        if config_file and Path(config_file).exists():
            try:
                if config_file.endswith('.yaml') or config_file.endswith('.yml'):
                    import yaml
                    with open(config_file, 'r') as f:
                        data = yaml.safe_load(f) or {}
                        self._configs.update(data.get("kg_qa", {}))
                        self._method_configs.update(data.get("kg_qa_methods", {}))
                elif config_file.endswith('.json'):
                    import json
                    with open(config_file, 'r') as f:
                        data = json.load(f) or {}
                        self._configs.update(data.get("kg_qa", {}))
                        self._method_configs.update(data.get("kg_qa_methods", {}))
                elif config_file.endswith('.toml'):
                    import toml
                    with open(config_file, 'r') as f:
                        data = toml.load(f) or {}
                        if "kg_qa" in data:
                            self._configs.update(data["kg_qa"])
                        if "kg_qa_methods" in data:
                            self._method_configs.update(data["kg_qa_methods"])
                self.logger.info(f"Loaded KG QA config from {config_file}")
            except Exception as e:
                self.logger.warning(f"Failed to load config file {config_file}: {e}")
    
    def _load_env_vars(self):
        env_mappings = {
            "KG_QA_QUALITY_THRESHOLD": ("quality_threshold", float),
            "KG_QA_CONSISTENCY_THRESHOLD": ("consistency_threshold", float),
            "KG_QA_COMPLETENESS_THRESHOLD": ("completeness_threshold", float),
            "KG_QA_ENABLE_AUTO_FIX": ("enable_auto_fix", bool),
            "KG_QA_REPORT_FORMAT": ("report_format", str),
        }
        
        for env_key, (config_key, type_func) in env_mappings.items():
            value = os.getenv(env_key)
            if value:
                try:
                    if type_func == bool:
                        self._configs[config_key] = value.lower() in ("true", "1", "yes", "on")
                    else:
                        self._configs[config_key] = type_func(value)
                except (ValueError, TypeError):
                    self.logger.warning(f"Failed to parse {env_key}={value}")
        
        env_prefix = "KG_QA_"
        for key, value in os.environ.items():
            if key.startswith(env_prefix) and key not in env_mappings:
                config_key = key[len(env_prefix):].lower()
                if value.lower() in ('true', 'false'):
                    self._configs[config_key] = value.lower() == 'true'
                elif value.isdigit():
                    self._configs[config_key] = int(value)
                else:
                    try:
                        self._configs[config_key] = float(value)
                    except ValueError:
                        self._configs[config_key] = value
    
    def set(self, key: str, value: Any):
        """Set configuration value programmatically."""
        self._configs[key] = value
    
    def get(self, key: str, default: Any = None) -> Any:
        """Get configuration value with fallback chain: config -> env -> default."""
        if key in self._configs:
            return self._configs[key]
        
        env_key = f"KG_QA_{key.upper()}"
        value = os.getenv(env_key)
        if value:
            try:
                if isinstance(default, int):
                    return int(value)
                elif isinstance(default, float):
                    return float(value)
                elif isinstance(default, bool):
                    return value.lower() in ("true", "1", "yes", "on")
                return value
            except (ValueError, TypeError):
                pass
        
        return default
    
    def set_method_config(self, method: str, **config):
        """Set method-specific configuration."""
        self._method_configs[method] = config
    
    def get_method_config(self, method: str) -> Dict:
        """Get method-specific configuration."""
        return self._method_configs.get(method, {})
    
    def get_all(self) -> Dict[str, Any]:
        """Get all configuration."""
        return {
            "config": self._configs.copy(),
            "method_configs": self._method_configs.copy()
        }


# Global config instance
kg_qa_config = KGQAConfig()

