"""
aicontract - Configuration System

Kullanım:
    from aicontract.config import Config, load_config

    # Default config
    cfg = Config()

    # Dosyadan yükle
    cfg = load_config("aicontract.yaml")

    # Inline override
    cfg = Config(
        ignore_functions=["_private_helper", "setup_*"],
        ignore_rules=["ARCH001", "STYLE001"],
        thresholds={"max_lines": 60, "max_complexity": 10},
    )

YAML Örneği (aicontract.yaml):
    aicontract:
      ignore_functions:
        - _private
        - setup_*
      ignore_rules:
        - STYLE001
        - ARCH004
      thresholds:
        max_lines: 60
        max_complexity: 10
      score_thresholds:
        clean: 20
        caution: 40
        warning: 70
      severity_overrides:
        ARCH001: error
        STYLE001: info
      ai_rules_enabled: true
      domains:
        auth:
          require_mfa: true
        payment:
          require_validation: true
"""

import yaml
from pathlib import Path
from typing import Optional, Any
from dataclasses import dataclass, field, asdict


DEFAULT_CONFIG = {
    "ignore_functions": [],
    "ignore_rules": [],
    "ignore_files": [],
    "thresholds": {
        "max_lines": 40,
        "max_complexity": 7,
        "max_params": 5,
        "max_nested_depth": 4,
    },
    "score_thresholds": {
        "clean": 20,
        "caution": 40,
        "warning": 70,
        "danger": 100,
    },
    "severity_overrides": {},
    "exclude_patterns": [
        "__pycache__",
        ".git",
        ".venv",
        "venv",
        "env",
        "node_modules",
        "dist",
        "build",
    ],
    "enabled_rules": None,
    "ai_rules_enabled": True,
    "domains": {},
}


@dataclass
class DomainConfig:
    """Domain-specific configuration."""

    require_mfa: bool = False
    require_validation: bool = False
    allowed_operations: list[str] = field(default_factory=list)
    blocked_operations: list[str] = field(default_factory=list)


@dataclass
class Config:
    """aicontract configuration."""

    ignore_functions: list[str] = field(default_factory=list)
    ignore_rules: list[str] = field(default_factory=list)
    ignore_files: list[str] = field(default_factory=list)
    thresholds: dict[str, int] = field(default_factory=dict)
    score_thresholds: dict[str, int] = field(default_factory=dict)
    severity_overrides: dict[str, str] = field(default_factory=dict)
    exclude_patterns: list[str] = field(default_factory=list)
    enabled_rules: Optional[list[str]] = None
    ai_rules_enabled: bool = True
    domains: dict[str, Any] = field(default_factory=dict)

    def __post_init__(self):
        if not self.thresholds:
            self.thresholds = DEFAULT_CONFIG["thresholds"].copy()
        if not self.exclude_patterns:
            self.exclude_patterns = DEFAULT_CONFIG["exclude_patterns"].copy()
        if not self.score_thresholds:
            self.score_thresholds = DEFAULT_CONFIG["score_thresholds"].copy()

    def should_ignore_function(self, func_name: str) -> bool:
        """Check if function should be ignored."""
        for pattern in self.ignore_functions:
            if func_name.startswith(pattern.rstrip("*")) or pattern in func_name:
                return True
        return False

    def should_ignore_rule(self, rule_id: str) -> bool:
        """Check if rule should be ignored."""
        if self.enabled_rules and rule_id not in self.enabled_rules:
            return True
        if rule_id in self.ignore_rules:
            return True
        return False

    def should_ignore_file(self, filepath: str) -> bool:
        """Check if file should be ignored."""
        path = Path(filepath)
        for pattern in self.exclude_patterns:
            if pattern in path.parts:
                return True
        for pattern in self.ignore_files:
            if pattern in filepath:
                return True
        return False

    def get_threshold(self, key: str, default: int = 40) -> int:
        """Get threshold value."""
        return self.thresholds.get(key, default)

    def get_severity(self, rule_id: str, default: str = "warning") -> str:
        """Get severity with override."""
        return self.severity_overrides.get(rule_id, default)

    def get_score_level(self, score: int) -> str:
        """Get score level based on thresholds."""
        if score >= self.score_thresholds.get("danger", 100):
            return "danger"
        if score >= self.score_thresholds.get("warning", 70):
            return "warning"
        if score >= self.score_thresholds.get("caution", 40):
            return "caution"
        return "clean"

    def get_domain_config(self, domain: str) -> Optional[DomainConfig]:
        """Get domain-specific config."""
        if domain in self.domains:
            data = self.domains[domain]
            if isinstance(data, dict):
                return DomainConfig(**data)
        return None

    def to_dict(self) -> dict:
        """Convert to dictionary."""
        return asdict(self)

    @classmethod
    def from_dict(cls, data: dict) -> "Config":
        """Create from dictionary."""
        return cls(
            **{
                k: v
                for k, v in data.items()
                if k in DEFAULT_CONFIG or k in cls.__dataclass_fields__
            }
        )


def load_config(path: str = "aicontract.yaml", project_dir: str = ".") -> Config:
    """
    Load configuration from YAML file.

    Args:
        path: Config file path (relative to project_dir if not absolute)
        project_dir: Project root directory

    Returns:
        Config instance
    """
    config_path = Path(path)
    if not config_path.is_absolute():
        config_path = Path(project_dir) / config_path

    if not config_path.exists():
        return Config()

    try:
        with open(config_path) as f:
            data = yaml.safe_load(f) or {}
    except Exception:
        return Config()

    if "aicontract" in data:
        data = data["aicontract"]

    return Config.from_dict(data)


def save_config(config: Config, path: str = "aicontract.yaml", project_dir: str = "."):
    """Save configuration to YAML file."""
    config_path = Path(path)
    if not config_path.is_absolute():
        config_path = Path(project_dir) / config_path

    with open(config_path, "w") as f:
        yaml.dump({"aicontract": config.to_dict()}, f, default_flow_style=False)


_default_config: Optional[Config] = None


def get_config() -> Config:
    """Get global default config."""
    global _default_config
    if _default_config is None:
        _default_config = load_config()
    return _default_config


def set_config(config: Config):
    """Set global default config."""
    global _default_config
    _default_config = config


def create_sample_config(path: str = "aicontract.yaml"):
    """Create a sample configuration file."""
    sample = {
        "aicontract": {
            "ignore_functions": [
                "_private",
                "setup_*",
                "test_*",
            ],
            "ignore_rules": [
                "STYLE001",  # docstring
                "ARCH004",  # return type
            ],
            "thresholds": {
                "max_lines": 60,
                "max_complexity": 10,
                "max_params": 6,
            },
            "score_thresholds": {
                "clean": 25,
                "caution": 50,
                "warning": 75,
                "danger": 100,
            },
            "severity_overrides": {
                "SEC001": "error",
                "SEC002": "error",
            },
            "ai_rules_enabled": True,
            "exclude_patterns": [
                "__pycache__",
                ".git",
                ".venv",
                "venv",
                "env",
                "node_modules",
                "dist",
                "build",
            ],
        }
    }
    with open(path, "w") as f:
        yaml.dump(sample, f, default_flow_style=False, sort_keys=False)
    print(f"Created sample config: {path}")


__all__ = [
    "Config",
    "DomainConfig",
    "load_config",
    "save_config",
    "get_config",
    "set_config",
    "create_sample_config",
    "DEFAULT_CONFIG",
]
