"""
RLM-Powered Codebase Analysis

Use RLM's unlimited context to work with massive codebases.
No chunking needed - RLM recursively processes everything!
"""

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

from groknroll.core.rlm_integration import RLMConfig, RLMIntegration


@dataclass
class CodebaseContext:
    """Context for RLM to explore codebase"""

    project_path: Path
    file_tree: str  # Directory tree structure
    file_list: list[str]  # All indexed files
    total_files: int
    total_lines: int
    languages: dict[str, int]


class RLMCodebaseAnalyzer:
    """
    Use RLM to analyze massive codebases without context limits

    Strategy:
    1. Give RLM the full file tree and list
    2. Let RLM recursively explore files as needed
    3. RLM decides what to read based on the task
    4. No pre-chunking - RLM handles context intelligently
    """

    def __init__(self, project_path: Path, model: str = "gpt-4o-mini", max_cost: float = 10.0):
        """
        Initialize RLM codebase analyzer

        Args:
            project_path: Project root
            model: LLM model to use
            max_cost: Maximum cost per task
        """
        self.project_path = project_path.resolve()

        # Initialize RLM
        rlm_config = RLMConfig(
            model=model,
            max_cost=max_cost,
            timeout_seconds=600,  # 10 minutes for large tasks
        )
        self.rlm = RLMIntegration(rlm_config)

        # Build codebase context
        self.context = self._build_context()

    def analyze_entire_codebase(self, focus: Optional[str] = None) -> str:
        """
        Analyze entire codebase with RLM

        RLM will recursively explore files as needed.

        Args:
            focus: Optional focus area (e.g., "security", "architecture")

        Returns:
            Analysis results
        """
        task = f"""Analyze this entire codebase.

Project: {self.project_path.name}
Total Files: {self.context.total_files:,}
Total Lines: {self.context.total_lines:,}

Available to you in the Python environment:
- project_path = Path("{self.project_path}")
- You can read ANY file: Path("file.py").read_text()
- You can list directories: list(Path("dir").glob("*"))
- Explore recursively as needed

File Tree:
{self.context.file_tree}

{f"Focus on: {focus}" if focus else ""}

Instructions:
1. Start by understanding the project structure
2. Read key files to understand architecture
3. Explore dependencies and relationships
4. Provide comprehensive analysis

You have unlimited context - explore everything you need!
"""

        result = self.rlm.complete(
            task,
            context={
                "project_path": str(self.project_path),
                "file_list": self.context.file_list,
                "languages": self.context.languages,
            },
        )

        return result.response if result.success else f"Error: {result.error}"

    def find_and_fix(self, issue_description: str) -> str:
        """
        Find and fix an issue across the entire codebase

        RLM will:
        1. Search for relevant code
        2. Understand the issue
        3. Make fixes
        4. Verify the fix

        Args:
            issue_description: Description of the issue to fix

        Returns:
            Fix results
        """
        task = f"""Find and fix this issue in the codebase:

Issue: {issue_description}

Project: {self.project_path.name}
Files: {self.context.total_files:,}
Lines: {self.context.total_lines:,}

You have access to:
- file_ops: FileOperations instance (read, write, edit files)
- bash_ops: BashOperations instance (run tests, commands)
- git_ops: GitOperations instance (git operations)

File Tree:
{self.context.file_tree}

Instructions:
1. Search through files to find the issue
2. Understand the root cause
3. Make necessary fixes using file_ops.edit_file()
4. Run tests to verify the fix
5. Report what you fixed

You can read and modify ANY file. Explore as needed!
"""

        result = self.rlm.complete(
            task, context={"project_path": str(self.project_path), "issue": issue_description}
        )

        return result.response if result.success else f"Error: {result.error}"

    def implement_feature(self, feature_description: str) -> str:
        """
        Implement a feature across the entire codebase

        RLM will:
        1. Understand existing architecture
        2. Plan the implementation
        3. Create/modify files as needed
        4. Integrate with existing code

        Args:
            feature_description: Description of feature to implement

        Returns:
            Implementation results
        """
        task = f"""Implement this feature in the codebase:

Feature: {feature_description}

Project: {self.project_path.name}
Files: {self.context.total_files:,}

You have full access to:
- file_ops: Read/write/edit files
- bash_ops: Run commands and tests
- git_ops: Git operations

File Tree:
{self.context.file_tree}

Instructions:
1. Understand the existing codebase architecture
2. Plan where the feature should be implemented
3. Create new files or modify existing ones
4. Integrate with existing code
5. Run tests to verify
6. Report what you implemented

Explore the codebase as needed. You have unlimited context!
"""

        result = self.rlm.complete(
            task, context={"project_path": str(self.project_path), "feature": feature_description}
        )

        return result.response if result.success else f"Error: {result.error}"

    def refactor(self, refactor_description: str) -> str:
        """
        Refactor code across the entire codebase

        Args:
            refactor_description: What to refactor

        Returns:
            Refactoring results
        """
        task = f"""Refactor the codebase:

Refactoring: {refactor_description}

Project: {self.project_path.name}
Files: {self.context.total_files:,}

Available operations:
- Read any file
- Edit files (with automatic backups)
- Run tests to verify changes
- Git operations

File Tree:
{self.context.file_tree}

Instructions:
1. Find all code that needs refactoring
2. Make changes carefully
3. Ensure tests still pass
4. Report all changes made

You can explore and modify ANY file!
"""

        result = self.rlm.complete(
            task, context={"project_path": str(self.project_path), "refactor": refactor_description}
        )

        return result.response if result.success else f"Error: {result.error}"

    def answer_question(self, question: str) -> str:
        """
        Answer a question about the codebase

        RLM will explore files to find the answer.

        Args:
            question: Question about the codebase

        Returns:
            Answer
        """
        task = f"""Answer this question about the codebase:

Question: {question}

Project: {self.project_path.name}
Files: {self.context.total_files:,}

File Tree:
{self.context.file_tree}

Instructions:
1. Read relevant files to understand the answer
2. Explore related code if needed
3. Provide a clear, detailed answer

You can read ANY file to find the answer!
"""

        result = self.rlm.complete(
            task, context={"project_path": str(self.project_path), "question": question}
        )

        return result.response if result.success else f"Error: {result.error}"

    def generate_documentation(self, doc_type: str = "overview") -> str:
        """
        Generate documentation for the codebase

        Args:
            doc_type: Type of documentation (overview, API, architecture)

        Returns:
            Generated documentation
        """
        task = f"""Generate {doc_type} documentation for this codebase.

Project: {self.project_path.name}
Files: {self.context.total_files:,}
Lines: {self.context.total_lines:,}

File Tree:
{self.context.file_tree}

Instructions:
1. Explore the codebase structure
2. Read key files to understand functionality
3. Generate comprehensive {doc_type} documentation
4. Include code examples where relevant

Explore as needed - you have unlimited context!
"""

        result = self.rlm.complete(
            task, context={"project_path": str(self.project_path), "doc_type": doc_type}
        )

        return result.response if result.success else f"Error: {result.error}"

    # =========================================================================
    # Helper Methods
    # =========================================================================

    def _build_context(self) -> CodebaseContext:
        """Build context about the codebase for RLM"""
        import os

        file_list = []
        total_files = 0
        total_lines = 0
        languages = {}

        # Walk directory tree
        for root, dirs, files in os.walk(self.project_path):
            # Skip common ignore directories
            dirs[:] = [
                d
                for d in dirs
                if d
                not in {
                    ".git",
                    "node_modules",
                    ".venv",
                    "venv",
                    "__pycache__",
                    "build",
                    "dist",
                    ".next",
                    "target",
                    ".groknroll",
                    ".pytest_cache",
                    "coverage",
                    ".mypy_cache",
                }
            ]

            for file in files:
                if self._should_include(file):
                    file_path = Path(root) / file
                    relative_path = file_path.relative_to(self.project_path)
                    file_list.append(str(relative_path))

                    try:
                        lines = len(file_path.read_text(errors="ignore").splitlines())
                        total_lines += lines
                        total_files += 1

                        # Track language
                        lang = self._detect_language(file_path.suffix)
                        languages[lang] = languages.get(lang, 0) + 1
                    except Exception:
                        continue

        # Generate file tree
        file_tree = self._generate_tree()

        return CodebaseContext(
            project_path=self.project_path,
            file_tree=file_tree,
            file_list=file_list,
            total_files=total_files,
            total_lines=total_lines,
            languages=languages,
        )

    def _generate_tree(self, max_depth: int = 3) -> str:
        """Generate directory tree structure"""

        tree_lines = [f"{self.project_path.name}/"]

        def walk_dir(path: Path, prefix: str = "", depth: int = 0):
            if depth >= max_depth:
                return

            try:
                entries = sorted(path.iterdir(), key=lambda p: (not p.is_dir(), p.name))

                # Filter out ignored directories
                entries = [
                    e
                    for e in entries
                    if e.name
                    not in {
                        ".git",
                        "node_modules",
                        ".venv",
                        "venv",
                        "__pycache__",
                        "build",
                        "dist",
                        ".next",
                        "target",
                        ".groknroll",
                    }
                ]

                for i, entry in enumerate(entries[:50]):  # Limit to 50 entries per dir
                    is_last = i == len(entries) - 1
                    current_prefix = "└── " if is_last else "├── "
                    next_prefix = "    " if is_last else "│   "

                    tree_lines.append(f"{prefix}{current_prefix}{entry.name}")

                    if entry.is_dir():
                        walk_dir(entry, prefix + next_prefix, depth + 1)

            except PermissionError:
                pass

        walk_dir(self.project_path)

        return "\n".join(tree_lines[:500])  # Limit tree size

    def _should_include(self, filename: str) -> bool:
        """Check if file should be included"""
        skip_extensions = {
            ".pyc",
            ".pyo",
            ".so",
            ".dylib",
            ".dll",
            ".jpg",
            ".jpeg",
            ".png",
            ".gif",
            ".svg",
            ".ico",
            ".pdf",
            ".zip",
            ".tar",
            ".gz",
            ".bz2",
            ".lock",
            ".log",
            ".tmp",
            ".cache",
            ".min.js",
            ".min.css",
        }

        ext = Path(filename).suffix.lower()
        return ext not in skip_extensions and not filename.startswith(".")

    def _detect_language(self, extension: str) -> str:
        """Detect language from extension"""
        lang_map = {
            ".py": "Python",
            ".js": "JavaScript",
            ".ts": "TypeScript",
            ".jsx": "React",
            ".tsx": "React",
            ".go": "Go",
            ".rs": "Rust",
            ".java": "Java",
            ".cpp": "C++",
            ".c": "C",
            ".rb": "Ruby",
            ".php": "PHP",
            ".md": "Markdown",
            ".json": "JSON",
            ".yaml": "YAML",
            ".yml": "YAML",
            ".html": "HTML",
            ".css": "CSS",
            ".sql": "SQL",
        }
        return lang_map.get(extension.lower(), "Other")
