"""
GroknrollAgent - The Ultimate CLI Coding Agent

Main orchestrator combining RLM, project context, and autonomous workflows.
"""

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

from groknroll.core.context import ProjectContext
from groknroll.core.rlm_integration import RLMConfig, RLMIntegration
from groknroll.storage.database import Database


@dataclass
class AgentConfig:
    """Configuration for GroknrollAgent"""

    model: str = "gpt-4o-mini"
    max_cost: float = 5.0
    timeout: int = 300
    auto_index: bool = False  # Disabled by default for faster startup
    fsd_mode: bool = False  # FSD Mode: skip ALL permission checks


class GroknrollAgent:
    """
    The Ultimate CLI Coding Agent

    Features:
    - Unlimited context via RLM
    - Project-aware with persistent state
    - Autonomous multi-step workflows
    - Self-correcting and verifying
    - Local and private
    - FSD Mode for skipping permission checks
    """

    def __init__(
        self,
        project_path: Optional[Path] = None,
        config: Optional[AgentConfig] = None,
        fsd_mode: bool = False,
    ):
        """
        Initialize groknroll agent

        Args:
            project_path: Path to project (uses current dir if None)
            config: Agent configuration
            fsd_mode: FSD Mode - skip ALL permission checks (dangerous!)
        """
        self.config = config or AgentConfig()

        # FSD mode can be set via parameter or config
        self.fsd_mode = fsd_mode or self.config.fsd_mode

        # Set project path
        self.project_path = project_path or Path.cwd()
        if not self.project_path.exists():
            raise ValueError(f"Project path does not exist: {self.project_path}")

        # Initialize components
        self.db = Database()
        self.context = ProjectContext(self.project_path, self.db)

        # Initialize RLM
        rlm_config = RLMConfig(
            model=self.config.model,
            max_cost=self.config.max_cost,
            timeout_seconds=self.config.timeout,
        )
        self.rlm = RLMIntegration(rlm_config)

        # Auto-index if configured
        if self.config.auto_index:
            self._ensure_indexed()

    def _ensure_indexed(self) -> None:
        """Ensure project is indexed"""
        overview = self.context.get_project_overview()

        # Index if never indexed or very old
        if overview["total_files"] == 0:
            print("Indexing project for first time...")
            stats = self.context.index_project()
            print(f"✓ Indexed {stats['indexed']} files ({stats['total_lines']:,} lines)")

    # =========================================================================
    # Core Chat & Analysis
    # =========================================================================

    def chat(self, message: str, context: Optional[dict[str, Any]] = None) -> str:
        """
        Chat with agent about project

        Args:
            message: User message
            context: Additional context

        Returns:
            Agent response
        """
        # Add project context
        project_context = {
            "project_name": self.context.project.name,
            "project_path": str(self.project_path),
            "total_files": self.context.project.total_files,
            **(context or {}),
        }

        # Execute with RLM
        result = self.rlm.complete(task=message, context=project_context)

        # Log execution
        if result.success:
            self.context.log_execution(
                task=message,
                response=result.response,
                total_cost=result.total_cost,
                total_time=result.total_time,
                iterations=result.iterations,
                status="success",
            )

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

    def analyze_code(
        self,
        file_path: Optional[Path] = None,
        code: Optional[str] = None,
        analysis_type: str = "review",
    ) -> dict[str, Any]:
        """
        Analyze code

        Args:
            file_path: Path to file (or provide code directly)
            code: Code string (or provide file_path)
            analysis_type: Type of analysis (review, security, complexity, etc)

        Returns:
            Analysis results
        """
        if file_path and not code:
            with open(file_path) as f:
                code = f.read()

        if not code:
            raise ValueError("Must provide either file_path or code")

        # Determine language
        language = "python"  # Default
        if file_path:
            language = self.context._detect_language(file_path.suffix)

        # Analyze with RLM
        result = self.rlm.analyze_code(code=code, analysis_type=analysis_type, language=language)

        if result.success:
            # Parse response into structured format
            analysis_results = {
                "analysis": result.response,
                "file": str(file_path) if file_path else None,
                "language": language,
                "type": analysis_type,
            }

            # Save analysis
            self.context.save_analysis(
                analysis_type=analysis_type,
                results=analysis_results,
                target_path=str(file_path) if file_path else None,
                execution_time=result.total_time,
            )

            return analysis_results

        return {"error": result.error}

    def analyze_project(self, detailed: bool = False) -> dict[str, Any]:
        """
        Analyze entire project

        Args:
            detailed: Include detailed analysis

        Returns:
            Project analysis
        """
        overview = self.context.get_project_overview()

        analysis_prompt = f"""Analyze this project:

Name: {overview["name"]}
Files: {overview["total_files"]}
Lines of Code: {overview["total_lines"]:,}

Languages:
{self._format_language_stats(overview["languages"])}

Provide:
1. Project structure assessment
2. Code quality overview
3. Potential issues
4. Recommendations
"""

        if detailed:
            analysis_prompt += "\n5. Detailed analysis of key files\n6. Architecture suggestions"

        result = self.rlm.complete(task=analysis_prompt, context=overview)

        if result.success:
            analysis_results = {
                "overview": overview,
                "analysis": result.response,
                "metrics": {
                    "cost": result.total_cost,
                    "time": result.total_time,
                    "iterations": result.iterations,
                },
            }

            self.context.save_analysis(
                analysis_type="project_overview",
                results=analysis_results,
                execution_time=result.total_time,
            )

            return analysis_results

        return {"error": result.error}

    # =========================================================================
    # Code Search & Understanding
    # =========================================================================

    def search_code(self, query: str, language: Optional[str] = None) -> list[dict[str, Any]]:
        """
        Search codebase

        Args:
            query: Search query
            language: Filter by language

        Returns:
            List of matching files
        """
        return self.context.search_files(query, language)

    def explain_code(self, file_path: Path) -> str:
        """Explain what code does"""
        with open(file_path) as f:
            code = f.read()

        language = self.context._detect_language(file_path.suffix)

        result = self.rlm.analyze_code(code=code, analysis_type="explain", language=language)

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

    # =========================================================================
    # Statistics & History
    # =========================================================================

    def get_stats(self) -> dict[str, Any]:
        """Get usage statistics"""
        exec_stats = self.context.get_execution_stats()
        overview = self.context.get_project_overview()

        return {
            "project": {
                "name": overview["name"],
                "files": overview["total_files"],
                "lines": overview["total_lines"],
                "languages": overview["languages"],
            },
            "executions": exec_stats,
            "rlm": self.rlm.get_stats(),
        }

    def get_history(self, limit: int = 10) -> list[dict[str, Any]]:
        """Get recent execution history"""
        executions = self.db.get_recent_executions(project_id=self.context.project.id, limit=limit)

        return [
            {
                "task": e.task[:100] + "..." if len(e.task) > 100 else e.task,
                "status": e.status,
                "cost": e.total_cost,
                "time": e.total_time,
                "timestamp": e.started_at,
            }
            for e in executions
        ]

    # =========================================================================
    # Project Management
    # =========================================================================

    def reindex_project(self, force: bool = True) -> dict[str, Any]:
        """Re-index project"""
        print("Re-indexing project...")
        stats = self.context.index_project(force=force)
        print(f"✓ Indexed {stats['indexed']} files")
        return stats

    def get_project_info(self) -> dict[str, Any]:
        """Get project information"""
        return self.context.get_project_overview()

    # =========================================================================
    # Utilities
    # =========================================================================

    def _format_language_stats(self, language_stats: dict[str, dict[str, int]]) -> str:
        """Format language statistics"""
        lines = []
        for lang, stats in sorted(
            language_stats.items(), key=lambda x: x[1]["lines"], reverse=True
        ):
            lines.append(f"  {lang}: {stats['files']} files, {stats['lines']:,} lines")
        return "\n".join(lines)

    def reset_rlm(self) -> None:
        """Reset RLM environment"""
        self.rlm.reset()

    def __repr__(self) -> str:
        return f"GroknrollAgent(project={self.project_path.name})"
