"""
Oracle Agent - RLM-powered codebase knowledge system

The Oracle has unlimited context and knows everything about the codebase.
"""

from dataclasses import dataclass
from pathlib import Path
from typing import Any, Optional

from groknroll.core.rlm import RLM
from groknroll.oracle.codebase_indexer import CodebaseIndexer


@dataclass
class OracleResponse:
    """Response from the Oracle"""

    question: str
    answer: str
    confidence: str  # high, medium, low
    sources: list[str]  # Files referenced
    execution_time: float

    def __str__(self):
        return f"""
Oracle Response
{"=" * 80}
Question: {self.question}

Answer:
{self.answer}

Confidence: {self.confidence}
Sources: {", ".join(self.sources[:5])}{"..." if len(self.sources) > 5 else ""}
Time: {self.execution_time:.2f}s
{"=" * 80}
"""


class OracleAgent:
    """
    Oracle Agent - Knows everything about the codebase

    Uses RLM's unlimited context to answer questions about:
    - Code structure and architecture
    - Function and class locations
    - Import dependencies
    - Implementation details
    - Best practices in the codebase
    - How to use features
    - Where bugs might be
    - Refactoring suggestions

    Example:
        oracle = OracleAgent("/path/to/project")
        response = oracle.ask("Where is the RLM class defined?")
        print(response.answer)
    """

    def __init__(
        self,
        project_path: Path,
        backend: str = "openai",
        model: str = "gpt-4o-mini",
        verbose: bool = False,
    ):
        """
        Initialize Oracle Agent

        Args:
            project_path: Path to the project root
            backend: LLM backend to use
            model: Model name
            verbose: Whether to show detailed output
        """
        self.project_path = Path(project_path).resolve()
        self.verbose = verbose

        print(f"🔮 Initializing Oracle Agent for: {self.project_path}")

        # Build codebase index
        self.indexer = CodebaseIndexer(self.project_path)
        self.index = self.indexer.build_index(include_content=True)

        # Initialize RLM
        self.rlm = RLM(
            backend=backend,
            backend_kwargs={"model_name": model},
            environment="local",
            max_iterations=10,
            verbose=verbose,
        )

        print(f"✅ Oracle ready - {self.index.total_files} files indexed")

    def ask(self, question: str, context: Optional[dict[str, Any]] = None) -> OracleResponse:
        """
        Ask the Oracle a question about the codebase

        Args:
            question: Question about the codebase
            context: Additional context to provide

        Returns:
            OracleResponse with answer and metadata
        """
        print(f"\n🔮 Oracle processing: {question[:80]}...")

        # Build comprehensive context for RLM
        rlm_context = self._build_context(question, context)

        # Ask RLM
        import time

        start = time.time()

        result = self.rlm.completion(rlm_context)

        execution_time = time.time() - start

        # Extract sources from response
        sources = self._extract_sources(result.response)

        return OracleResponse(
            question=question,
            answer=result.response,
            confidence="high",  # Could be inferred from response
            sources=sources,
            execution_time=execution_time,
        )

    def _build_context(self, question: str, extra_context: Optional[dict] = None) -> str:
        """Build comprehensive context for RLM"""

        parts = [
            "You are the Oracle - an all-knowing agent with complete knowledge of this codebase.",
            "You have unlimited context and can examine any file in detail.",
            "",
            "# Codebase Overview",
            self.indexer.get_summary(),
            "",
            "# Available Files",
        ]

        # Add file listing
        for relative_path in sorted(self.index.files.keys())[:100]:  # Top 100 files
            file_info = self.index.files[relative_path]
            parts.append(f"- {relative_path} ({file_info.language}, {file_info.lines} lines)")

        parts.append("")
        parts.append("# Question")
        parts.append(question)
        parts.append("")

        # Add relevant context based on question
        parts.append("# Relevant Code")
        parts.append("")

        # Try to find relevant files
        relevant_files = self._find_relevant_files(question)

        for file_path in relevant_files[:5]:  # Top 5 most relevant
            file_info = self.index.files.get(file_path)
            if file_info and file_info.content:
                parts.append(f"## File: {file_path}")
                parts.append(f"```{file_info.language}")
                parts.append(file_info.content)
                parts.append("```")
                parts.append("")

        if extra_context:
            parts.append("# Additional Context")
            for key, value in extra_context.items():
                parts.append(f"{key}: {value}")
            parts.append("")

        parts.append("# Instructions")
        parts.append("Answer the question comprehensively using your knowledge of the codebase.")
        parts.append("Reference specific files, functions, and classes when relevant.")
        parts.append("Provide code examples if helpful.")
        parts.append("Use FINAL_VAR(str(your_answer)) to return your answer.")

        return "\n".join(parts)

    def _find_relevant_files(self, question: str) -> list[str]:
        """Find files relevant to the question"""
        relevant = []
        question_lower = question.lower()

        # Check for specific file mentions
        for file_path in self.index.files.keys():
            file_name = Path(file_path).name.lower()
            if file_name in question_lower or file_path in question_lower:
                relevant.append(file_path)

        # Check for class/function mentions
        for class_name, file_paths in self.index.classes.items():
            if class_name.lower() in question_lower:
                relevant.extend(file_paths)

        for func_name, file_paths in self.index.functions.items():
            if func_name.lower() in question_lower:
                relevant.extend(file_paths)

        # Keywords that suggest core files
        if any(kw in question_lower for kw in ["main", "core", "base", "init"]):
            for file_path in self.index.files.keys():
                if any(name in file_path for name in ["__init__.py", "main.py", "core/", "rlm.py"]):
                    relevant.append(file_path)

        # Remove duplicates while preserving order
        seen = set()
        unique_relevant = []
        for item in relevant:
            if item not in seen:
                seen.add(item)
                unique_relevant.append(item)

        return unique_relevant if unique_relevant else list(self.index.files.keys())[:10]

    def _extract_sources(self, response: str) -> list[str]:
        """Extract file references from response"""
        sources = set()

        for file_path in self.index.files.keys():
            if file_path in response or Path(file_path).name in response:
                sources.add(file_path)

        return list(sources)

    def find_function(self, function_name: str) -> OracleResponse:
        """Ask Oracle where a function is defined"""
        return self.ask(f"Where is the function '{function_name}' defined? Show me the code.")

    def find_class(self, class_name: str) -> OracleResponse:
        """Ask Oracle where a class is defined"""
        return self.ask(
            f"Where is the class '{class_name}' defined? Show me the code and explain what it does."
        )

    def explain_file(self, file_path: str) -> OracleResponse:
        """Ask Oracle to explain a file"""
        return self.ask(
            f"Explain what {file_path} does and how it fits into the overall architecture."
        )

    def find_usage(self, item_name: str) -> OracleResponse:
        """Ask Oracle how something is used"""
        return self.ask(f"Show me examples of how '{item_name}' is used in the codebase.")

    def suggest_refactoring(self, description: str) -> OracleResponse:
        """Ask Oracle for refactoring suggestions"""
        return self.ask(f"Suggest how to refactor: {description}")

    def find_bugs(self, area: Optional[str] = None) -> OracleResponse:
        """Ask Oracle to identify potential bugs"""
        question = (
            f"Identify potential bugs in {area}"
            if area
            else "Identify potential bugs in the codebase"
        )
        return self.ask(question)

    def get_architecture_overview(self) -> OracleResponse:
        """Ask Oracle for architecture overview"""
        return self.ask(
            "Provide a comprehensive overview of the codebase architecture. "
            "Explain the main components, how they interact, and the overall design pattern."
        )

    def how_to_add_feature(self, feature: str) -> OracleResponse:
        """Ask Oracle how to add a feature"""
        return self.ask(
            f"How would I add this feature: {feature}? "
            f"Which files would I need to modify? Show me the steps."
        )

    def trace_execution(self, entry_point: str) -> OracleResponse:
        """Ask Oracle to trace execution flow"""
        return self.ask(
            f"Trace the execution flow starting from {entry_point}. "
            f"Show me the call chain and what happens step by step."
        )

    def explain_imports(self, module: str) -> OracleResponse:
        """Ask Oracle about import relationships"""
        return self.ask(
            f"Explain the import relationships for {module}. Which files import it and why?"
        )
