"""
Decorators — AI'ın kod yazarken kullandığı tek interface.
Kullanım:

    @ai_func(domain="authentication", touches=["users_table"])
    def login(username, password):
        ...

Fonksiyon çalışmadan önce valide edilir.
Violation varsa ConsoleReporter ile gösterilir.
"""

import inspect
import os
import functools
from typing import Optional

try:
    from .registry import Registry, FunctionContract
    from ..rules.validator import Validator
    from ..tools.reporter import ConsoleReporter
except ImportError:
    from registry import Registry, FunctionContract
    from validator import Validator
    from reporter import ConsoleReporter

# Global registry instance — proje boyunca tek
_registry: Optional[Registry] = None
_validator: Optional[Validator] = None
_reporter: Optional[ConsoleReporter] = None


def _get_registry() -> Registry:
    global _registry, _validator, _reporter
    if _registry is None:
        root = os.environ.get("AICONTRACT_ROOT", ".")
        _registry = Registry(root)
        _validator = Validator(_registry)
        _reporter = ConsoleReporter()
    return _registry


def ai_func(
    domain: str,
    touches: list = None,
    replaces: Optional[str] = None,
    risk: str = "low",
):
    """
    AI'ın yazdığı her fonksiyona eklenen decorator.

    Args:
        domain:   Bu fonksiyon hangi sorumluluğa ait?
        touches:  Hangi resource'lara dokunuyor? (db tabloları, servisler)
        replaces: Hangi eski fonksiyonun yerine geçiyor?
        risk:     Tahmini değişim riski (low/medium/high)
    """
    touches = touches or []

    def decorator(func):
        registry = _get_registry()

        # Fonksiyon bilgilerini topla
        frame = inspect.stack()[1]
        filepath = frame.filename
        lineno = frame.lineno
        is_async = inspect.iscoroutinefunction(func)

        contract = FunctionContract(
            name=func.__name__,
            file=filepath,
            domain=domain,
            touches=touches,
            replaces=replaces,
            line=lineno,
            is_async=is_async,
            risk=risk,
        )

        # Kaydet ve valide et
        registry.register(contract)

        try:
            source = inspect.getsource(func)
        except Exception:
            source = ""

        violations = _validator.validate(contract, source)

        if violations:
            _reporter.report(violations, context=f"@ai_func > {func.__name__}()")

        # Fonksiyonu olduğu gibi bırak
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)

        @functools.wraps(func)
        async def async_wrapper(*args, **kwargs):
            return await func(*args, **kwargs)

        return async_wrapper if is_async else wrapper

    return decorator


def ai_module(
    responsibility: str,
    owns: list = None,
):
    """
    Modül seviyesi beyan.
    Dosyanın başına eklenir, o dosyanın ne yaptığını tanımlar.

    Kullanım:
        ai_module(responsibility="user_authentication", owns=["login","logout"])
    """
    owns = owns or []
    registry = _get_registry()

    frame = inspect.stack()[1]
    filepath = frame.filename

    from .registry import DomainContract

    if responsibility not in registry.domains:
        registry.domains[responsibility] = DomainContract(
            name=responsibility,
            owner=filepath,
            owns=owns,
        )
    else:
        d = registry.domains[responsibility]
        d.owner = d.owner or filepath
        for fn in owns:
            if fn not in d.owns:
                d.owns.append(fn)

    registry.save()
