"""
Stateful Oracle Agent - Oracle with MADACE state machine

Combines Oracle Agent's unlimited context with MADACE state machine discipline.
"""

from pathlib import Path
from typing import Any, Optional

from groknroll.oracle.oracle_agent import OracleAgent, OracleResponse
from groknroll.oracle.oracle_state_machine import (
    OracleQuery,
    OracleStateMachine,
    QueryPriority,
    QueryState,
)


class StatefulOracle(OracleAgent):
    """
    Oracle Agent with MADACE state machine

    Extends Oracle Agent with:
    - Query queueing and prioritization
    - State machine enforcement (PENDING → ANALYZING → REVIEWED → COMPLETED)
    - One analysis at a time
    - Full query history and tracking
    - Persistent state across sessions

    Example:
        oracle = StatefulOracle("/path/to/project")

        # Create queries
        q1 = oracle.queue_query("Where is RLM defined?", priority=QueryPriority.HIGH)
        q2 = oracle.queue_query("How does authentication work?")

        # Process next query
        response = oracle.process_next()

        # Review and accept
        oracle.accept_query(q1.id)

        # Check status
        status = oracle.get_status()
    """

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

        Args:
            project_path: Path to project root
            backend: LLM backend to use
            model: Model name
            verbose: Whether to show detailed output
            auto_accept: Automatically accept queries after analysis
        """
        # Initialize base Oracle Agent
        super().__init__(project_path, backend, model, verbose)

        # Initialize state machine
        self.state_machine = OracleStateMachine(self.project_path)
        self.auto_accept = auto_accept

        print(f"🔮 Stateful Oracle ready - State machine initialized")
        print(f"   Auto-accept: {'enabled' if auto_accept else 'disabled'}")

    def queue_query(
        self,
        question: str,
        priority: QueryPriority = QueryPriority.MEDIUM,
        metadata: Optional[dict] = None,
    ) -> OracleQuery:
        """
        Queue a query for Oracle to answer

        Args:
            question: Question to ask
            priority: Query priority (LOW, MEDIUM, HIGH, CRITICAL)
            metadata: Additional metadata

        Returns:
            Created OracleQuery in PENDING state
        """
        query = self.state_machine.create_query(question, priority, metadata)
        print(f"📝 Query queued: {query.id} - {question[:60]}...")
        return query

    def process_query(self, query_id: str) -> Optional[OracleResponse]:
        """
        Process a specific query

        Args:
            query_id: Query ID to process

        Returns:
            OracleResponse if successful, None if blocked
        """
        # Try to start analysis
        if not self.state_machine.start_analysis(query_id):
            analyzing = self.state_machine.current_analyzing
            print(f"❌ Blocked: Query {analyzing} is already being analyzed")
            return None

        query = self.state_machine.get_query(query_id)
        if not query:
            return None

        print(f"🔮 Analyzing: {query.id} - {query.question[:60]}...")

        try:
            # Use base Oracle Agent to answer
            response = self.ask(query.question, context=query.metadata)

            # Complete analysis
            self.state_machine.complete_analysis(
                query_id,
                answer=response.answer,
                sources=response.sources,
                confidence=response.confidence,
                execution_time=response.execution_time,
            )

            print(f"✅ Analysis complete: {query.id}")
            print(f"   Confidence: {response.confidence}")
            print(f"   Sources: {len(response.sources)} files")
            print(f"   Time: {response.execution_time:.2f}s")

            # Auto-accept if enabled
            if self.auto_accept:
                self.accept_query(query_id)
                print(f"✓ Auto-accepted: {query.id}")

            return response

        except Exception as e:
            # Fail analysis
            self.state_machine.fail_analysis(query_id, str(e))
            print(f"❌ Analysis failed: {query.id}")
            print(f"   Error: {e}")
            return None

    def process_next(self) -> Optional[OracleResponse]:
        """
        Process next pending query by priority

        Returns:
            OracleResponse if successful, None if no pending queries
        """
        next_query = self.state_machine.get_next_pending()

        if not next_query:
            print("📭 No pending queries")
            return None

        return self.process_query(next_query.id)

    def process_all(self, max_queries: Optional[int] = None) -> list[OracleResponse]:
        """
        Process all pending queries

        Args:
            max_queries: Maximum number of queries to process (None = all)

        Returns:
            List of OracleResponse objects
        """
        responses = []
        processed = 0

        while True:
            if max_queries and processed >= max_queries:
                break

            response = self.process_next()
            if not response:
                break

            responses.append(response)
            processed += 1

        print(f"✅ Processed {processed} queries")
        return responses

    def accept_query(self, query_id: str) -> None:
        """
        Accept a reviewed query

        Args:
            query_id: Query ID to accept
        """
        self.state_machine.accept_query(query_id)
        print(f"✓ Accepted: {query_id}")

    def retry_query(self, query_id: str) -> Optional[OracleResponse]:
        """
        Retry a failed query

        Args:
            query_id: Query ID to retry

        Returns:
            OracleResponse if successful, None if blocked
        """
        if self.state_machine.retry_query(query_id):
            return self.process_query(query_id)
        else:
            print(f"❌ Retry blocked: Another query is being analyzed")
            return None

    def get_query_result(self, query_id: str) -> Optional[OracleQuery]:
        """
        Get query and its result

        Args:
            query_id: Query ID

        Returns:
            OracleQuery with results
        """
        return self.state_machine.get_query(query_id)

    def get_status(self) -> dict[str, Any]:
        """
        Get state machine status

        Returns:
            Status dictionary
        """
        return self.state_machine.get_status()

    def list_queries(
        self,
        state: Optional[QueryState] = None,
        limit: Optional[int] = None,
    ) -> list[OracleQuery]:
        """
        List queries by state

        Args:
            state: Filter by state (optional)
            limit: Maximum number to return

        Returns:
            List of OracleQuery objects
        """
        return self.state_machine.list_queries(state, limit)

    # Convenience methods with state machine integration

    def queue_find_function(self, function_name: str, priority: QueryPriority = QueryPriority.MEDIUM) -> OracleQuery:
        """Queue query to find a function"""
        return self.queue_query(
            f"Where is the function '{function_name}' defined? Show me the code.",
            priority=priority,
            metadata={"type": "find_function", "target": function_name},
        )

    def queue_find_class(self, class_name: str, priority: QueryPriority = QueryPriority.MEDIUM) -> OracleQuery:
        """Queue query to find a class"""
        return self.queue_query(
            f"Where is the class '{class_name}' defined? Show me the code and explain what it does.",
            priority=priority,
            metadata={"type": "find_class", "target": class_name},
        )

    def queue_explain_file(self, file_path: str, priority: QueryPriority = QueryPriority.MEDIUM) -> OracleQuery:
        """Queue query to explain a file"""
        return self.queue_query(
            f"Explain what {file_path} does and how it fits into the overall architecture.",
            priority=priority,
            metadata={"type": "explain_file", "target": file_path},
        )

    def queue_architecture_overview(self, priority: QueryPriority = QueryPriority.HIGH) -> OracleQuery:
        """Queue query for architecture overview"""
        return self.queue_query(
            "Provide a comprehensive overview of the codebase architecture. "
            "Explain the main components, how they interact, and the overall design pattern.",
            priority=priority,
            metadata={"type": "architecture_overview"},
        )

    def queue_find_bugs(self, area: Optional[str] = None, priority: QueryPriority = QueryPriority.HIGH) -> OracleQuery:
        """Queue query to find bugs"""
        question = (
            f"Identify potential bugs in {area}"
            if area
            else "Identify potential bugs in the codebase"
        )
        return self.queue_query(
            question,
            priority=priority,
            metadata={"type": "find_bugs", "area": area},
        )

    def queue_how_to_add_feature(self, feature: str, priority: QueryPriority = QueryPriority.MEDIUM) -> OracleQuery:
        """Queue query about adding a feature"""
        return self.queue_query(
            f"How would I add this feature: {feature}? Which files would I need to modify? Show me the steps.",
            priority=priority,
            metadata={"type": "add_feature", "feature": feature},
        )
