"""
aicontract - Context Generator
Tüm adaptörlerin bilgisini toplayıp YZ için tek bir bağlam bloğuna dönüştürür.

Bu, projenin "yıldız" parçası:
  - SQL şeması
  - Mimari kararlar (session memory)
  - Impact analizi
  - Migration tehlikeleri
  - Mevcut dosya bağlamı

→ Hepsini birleştirip prompt'un başına ekler.

Kullanım:
    from aicontract.context_gen import ContextGenerator
    gen = ContextGenerator(".")
    prompt = gen.wrap("login fonksiyonunu JWT'ye geçir", target_fn="login")
    # → prompt artık tüm bağlamı içeriyor
"""

import os
import yaml
from typing import Optional

# Try relative imports first, fall back to absolute
try:
    from ..adapters.sql_adapter import SQLAdapter
    from ..adapters.migration_guard import MigrationGuard
    from .session_memory import SessionMemory
    from .impact import ImpactAnalyzer
    from ..core.registry import Registry
except ImportError:
    try:
        from aicontract.adapters.sql_adapter import SQLAdapter
        from aicontract.adapters.migration_guard import MigrationGuard
        from aicontract.utils.session_memory import SessionMemory
        from aicontract.utils.impact import ImpactAnalyzer
        from aicontract.core.registry import Registry
    except ImportError:
        from session_memory import SessionMemory
        from sql_adapter import SQLAdapter
        from migration_guard import MigrationGuard
        from impact import ImpactAnalyzer

        try:
            from registry import Registry
        except ImportError:
            Registry = None


class ContextGenerator:
    """
    Tüm aicontract bilgisini bir araya getirip
    YZ'ye verilecek bağlam bloğunu üretir.
    """

    def __init__(
        self,
        project_dir: str = ".",
        memory: Optional[SessionMemory] = None,
        sql_adapter: Optional[SQLAdapter] = None,
        migration_guard: Optional[MigrationGuard] = None,
        aicontract_yaml: str = "aicontract.yaml",
    ):
        self.project_dir = project_dir
        memory_file = os.path.join(project_dir, ".aicontract_memory.yaml")
        self.memory = memory or SessionMemory(memory_file)
        self.sql_adapter = sql_adapter
        self.migration_guard = migration_guard
        self.aicontract_yaml = aicontract_yaml

        self._load_config()

    def _load_config(self):
        """aicontract.yaml'i yükle."""
        config_path = os.path.join(self.project_dir, self.aicontract_yaml)
        if os.path.exists(config_path):
            with open(config_path) as f:
                self.config = yaml.safe_load(f) or {}
        else:
            self.config = {}

        self.domains = self.config.get("database", {})
        self.memory_config = self.config.get("memory", {})
        self.context_config = self.config.get("context", {})

    def wrap(
        self,
        user_prompt: str,
        target_fn: Optional[str] = None,
        mode: str = "change",
    ) -> str:
        """
        Prompt'u alır, tüm bağlamla zenginleştirir.

        Args:
            user_prompt: Kullanıcının asıl isteği
            target_fn: Hedef fonksiyon ismi (opsiyonel)
            mode: change | add | delete

        Returns:
            Zenginleştirilmiş prompt
        """
        blocks = []

        # 1. Header
        blocks.append(self._build_header(user_prompt))

        # 2. Target function bilgisi
        if target_fn:
            blocks.append(self._build_target_context(target_fn, mode))

        # 3. SQL/DB bilgisi
        if self.sql_adapter:
            blocks.append(self._build_sql_context())

        # 4. Migration tehlikeleri
        if self.migration_guard:
            blocks.append(self._build_migration_context())

        # 5. Session memory (mimari kararlar)
        blocks.append(self._build_memory_context(target_fn))

        # 6. User prompt
        blocks.append(self._build_user_prompt(user_prompt))

        return "\n\n".join([b for b in blocks if b])

    def _build_header(self, user_prompt: str) -> str:
        """Header bloğu."""
        return f"""# aicontract Context
# Bu bağlam, kod yazmadan önce otomatik üretildi.

## User Request
{user_prompt}
"""

    def _build_target_context(self, target_fn: str, mode: str) -> str:
        """Hedef fonksiyon bağlamı."""
        # Impact analizi
        registry = Registry(self.project_dir)
        analyzer = ImpactAnalyzer(registry)
        impact = analyzer.analyze(target_fn, depth=3)

        # Contract bilgisi
        contract = registry.get(target_fn)

        lines = [
            "## Target Function Analysis",
            f"**Function:** `{target_fn}`",
            f"**Mode:** {mode}",
            f"**Risk:** {impact['risk'].upper()}",
            f"**Impact:** {impact['total_impact']} functions",
            f"**Files:** {', '.join(impact['files_affected'][:5])}",
        ]

        if impact["layers"]:
            lines.append("\n**Call Hierarchy:**")
            for i, layer in enumerate(impact["layers"], 1):
                lines.append(f"  Depth {i}: {', '.join(layer[:3])}")

        if contract:
            lines.extend(
                [
                    f"**Domain:** {contract.domain}",
                    f"**Touches:** {', '.join(contract.touches) if contract.touches else 'none'}",
                ]
            )

        return "\n".join(lines)

    def _build_sql_context(self) -> str:
        """SQL/DB bağlamı."""
        try:
            sql_context = self.sql_adapter.build_context()
            return f"\n## Database Schema\n{sql_context}"
        except Exception as e:
            return f"\n## Database Schema\n[Not available: {e}]"

    def _build_migration_context(self) -> str:
        """Migration bağlamı."""
        try:
            mg_context = self.migration_guard.build_context()
            return f"\n## Migration Warnings\n{mg_context}"
        except Exception as e:
            return f"\n## Migration Warnings\n[Not available: {e}]"

    def _build_memory_context(self, target_fn: Optional[str]) -> str:
        """Session memory bağlamı."""
        try:
            # Mimari kararlar
            decisions = self.memory.list_decisions()[:5]

            lines = ["## Architectural Decisions"]
            if decisions:
                for d in decisions:
                    lines.append(f"- **{d.category}**: {d.rule}")
            else:
                lines.append("- No previous decisions recorded")

            # Target ile ilgili kararlar
            if target_fn:
                all_decisions = self.memory.list_decisions()
                fn_decisions = [
                    d for d in all_decisions if target_fn.lower() in d.rule.lower()
                ]
                if fn_decisions:
                    lines.append(f"\n### Related to `{target_fn}`:")
                    for d in fn_decisions[:3]:
                        lines.append(f"- {d.rule}")

            return "\n".join(lines)
        except Exception as e:
            return f"\n## Architectural Decisions\n[Not available: {e}]"

    def _build_user_prompt(self, user_prompt: str) -> str:
        """User prompt'u."""
        return f"""
## Your Task
{user_prompt}

---
IMPORTANT: Before writing code, check the context above.
Make sure your code doesn't break existing functionality.
"""

    def quick_wrap(self, target_fn: str) -> str:
        """Basit wrap - sadece target function."""
        try:
            from registry import Registry
        except ImportError:
            from .registry import Registry

        registry = Registry(self.project_dir)
        analyzer = ImpactAnalyzer(registry)
        impact = analyzer.analyze(target_fn, depth=3)

        return f"""# Context for {target_fn}

Risk: {impact["risk"]}
Impact: {impact["total_impact"]} functions
Files: {", ".join(impact["files_affected"][:3])}

Layers: {impact["layers"]}
"""


# Kolay kullanım için
def quick_context(target_fn: str, project_dir: str = ".") -> str:
    """Hızlı bağlam oluştur."""
    gen = ContextGenerator(project_dir)
    return gen.quick_wrap(target_fn)


if __name__ == "__main__":
    import sys

    if len(sys.argv) > 1:
        fn = sys.argv[1]
        print(ContextGenerator(".").wrap(f"Change {fn}", target_fn=fn))
    else:
        print("Usage: python context_gen.py <function_name>")
