"""
Project Context Management

Maintains comprehensive project state including:
- File index with AST metadata
- Dependency graphs
- Test coverage
- Conversation history
- Active tasks
"""

from datetime import datetime
from pathlib import Path
from typing import Any, Optional

from groknroll.storage.database import Database


class ProjectContext:
    """
    Project context manager

    Maintains all project state in SQLite database for instant access.
    """

    def __init__(self, project_path: Path, database: Optional[Database] = None):
        """
        Initialize project context

        Args:
            project_path: Path to project root
            database: Database instance (creates new if None)
        """
        self.project_path = project_path.resolve()
        self.db = database or Database()

        # Get or create project in database
        self.project = self.db.get_or_create_project(self.project_path)

    def index_project(self, force: bool = False) -> dict[str, Any]:
        """
        Index entire project

        Args:
            force: Force re-indexing even if up-to-date

        Returns:
            Indexing statistics
        """
        indexed_count = 0
        total_lines = 0
        skipped_count = 0

        # File extensions to index
        code_extensions = {
            ".py",
            ".js",
            ".ts",
            ".jsx",
            ".tsx",
            ".go",
            ".rs",
            ".java",
            ".c",
            ".cpp",
            ".h",
            ".hpp",
            ".rb",
            ".php",
            ".swift",
            ".kt",
            ".scala",
        }

        for file_path in self.project_path.rglob("*"):
            if not file_path.is_file():
                continue

            if file_path.suffix not in code_extensions:
                continue

            # Skip common directories
            if any(
                part.startswith(".") or part in ["node_modules", "venv", ".venv", "dist", "build"]
                for part in file_path.parts
            ):
                skipped_count += 1
                continue

            try:
                # Get file stats
                stat = file_path.stat()
                relative_path = str(file_path.relative_to(self.project_path))

                # Count lines
                with open(file_path, encoding="utf-8", errors="ignore") as f:
                    lines = len(f.readlines())
                    total_lines += lines

                # Determine language
                language = self._detect_language(file_path.suffix)

                # Index file
                self.db.index_file(
                    project_id=self.project.id,
                    file_path=file_path,
                    relative_path=relative_path,
                    language=language,
                    size_bytes=stat.st_size,
                    lines_of_code=lines,
                    last_modified=datetime.fromtimestamp(stat.st_mtime),
                )

                indexed_count += 1

            except Exception as e:
                print(f"Error indexing {file_path}: {e}")
                continue

        # Update project stats
        self.db.update_project_stats(
            project_id=self.project.id, total_files=indexed_count, total_lines=total_lines
        )

        return {"indexed": indexed_count, "skipped": skipped_count, "total_lines": total_lines}

    def get_file_context(self, file_path: Path) -> Optional[dict[str, Any]]:
        """Get context for specific file"""
        files = self.db.get_project_files(self.project.id)

        for f in files:
            if Path(f.path) == file_path:
                return {
                    "path": f.path,
                    "relative_path": f.relative_path,
                    "language": f.language,
                    "lines_of_code": f.lines_of_code,
                    "complexity": f.complexity,
                    "imports": f.imports,
                    "exports": f.exports,
                }

        return None

    def search_files(self, query: str, language: Optional[str] = None) -> list[dict[str, Any]]:
        """Search indexed files"""
        results = self.db.search_files(project_id=self.project.id, query=query, language=language)

        return [
            {
                "path": f.path,
                "relative_path": f.relative_path,
                "language": f.language,
                "lines_of_code": f.lines_of_code,
            }
            for f in results
        ]

    def get_project_overview(self) -> dict[str, Any]:
        """Get project overview"""
        files = self.db.get_project_files(self.project.id)

        # Group by language
        language_stats = {}
        for f in files:
            lang = f.language or "unknown"
            if lang not in language_stats:
                language_stats[lang] = {"files": 0, "lines": 0}

            language_stats[lang]["files"] += 1
            language_stats[lang]["lines"] += f.lines_of_code or 0

        return {
            "name": self.project.name,
            "path": self.project.path,
            "total_files": self.project.total_files or 0,
            "total_lines": self.project.total_lines or 0,
            "last_indexed": self.project.last_indexed,
            "languages": language_stats,
        }

    def get_execution_stats(self) -> dict[str, Any]:
        """Get RLM execution statistics"""
        return self.db.get_execution_stats(self.project.id)

    def log_execution(self, task: str, response: str, **metrics) -> None:
        """Log RLM execution"""
        self.db.log_execution(project_id=self.project.id, task=task, response=response, **metrics)

    def save_analysis(self, analysis_type: str, results: dict[str, Any], **metadata) -> None:
        """Save analysis results"""
        self.db.save_analysis(
            project_id=self.project.id, analysis_type=analysis_type, results=results, **metadata
        )

    def get_latest_analysis(self, analysis_type: str) -> Optional[dict[str, Any]]:
        """Get latest analysis of given type"""
        analysis = self.db.get_latest_analysis(
            project_id=self.project.id, analysis_type=analysis_type
        )

        if analysis:
            return {
                "type": analysis.analysis_type,
                "results": analysis.results,
                "recommendations": analysis.recommendations,
                "issues": analysis.issues,
                "metrics": analysis.metrics,
                "created_at": analysis.created_at,
            }

        return None

    def _detect_language(self, extension: str) -> str:
        """Detect language from file extension"""
        mapping = {
            ".py": "python",
            ".js": "javascript",
            ".ts": "typescript",
            ".jsx": "javascript",
            ".tsx": "typescript",
            ".go": "go",
            ".rs": "rust",
            ".java": "java",
            ".c": "c",
            ".cpp": "cpp",
            ".h": "c",
            ".hpp": "cpp",
            ".rb": "ruby",
            ".php": "php",
            ".swift": "swift",
            ".kt": "kotlin",
            ".scala": "scala",
        }

        return mapping.get(extension, "unknown")
