"""
Oracle Commands - CLI for Stateful Oracle with MADACE state machine
"""

import sys
from pathlib import Path
from typing import Optional

import click
from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from rich.table import Table

from groknroll.oracle.oracle_state_machine import QueryPriority, QueryState
from groknroll.oracle.stateful_oracle import StatefulOracle

console = Console()


@click.group()
def oracle():
    """Oracle - RLM-powered codebase knowledge with state machine"""
    pass


@oracle.command()
@click.option("--path", type=click.Path(exists=True), help="Project path")
@click.option("--auto-accept", is_flag=True, help="Auto-accept all queries")
def init(path: Optional[str], auto_accept: bool):
    """
    Initialize Stateful Oracle for project

    Creates Oracle state machine and indexes codebase.
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        console.print()
        console.print(
            Panel.fit(
                "[bold cyan]Initializing Stateful Oracle[/bold cyan]\n\n"
                "[yellow]Building codebase index...[/yellow]",
                title="[bold]Oracle Setup[/bold]",
                border_style="cyan",
            )
        )

        with console.status("[bold cyan]Indexing codebase..."):
            oracle_agent = StatefulOracle(
                project_path=project_path,
                auto_accept=auto_accept,
            )

        console.print()
        console.print(
            Panel.fit(
                f"[bold green]✓ Oracle initialized![/bold green]\n\n"
                f"[cyan]Files indexed:[/cyan] {oracle_agent.index.total_files}\n"
                f"[cyan]Auto-accept:[/cyan] {'enabled' if auto_accept else 'disabled'}\n"
                f"[cyan]State file:[/cyan] .madace/oracle/oracle_state.json\n\n"
                "[dim]Use 'groknroll oracle query' to ask questions[/dim]",
                title="[bold]Oracle Ready[/bold]",
                border_style="green",
            )
        )

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        import traceback

        traceback.print_exc()
        sys.exit(1)


@oracle.command()
@click.argument("question")
@click.option("--path", type=click.Path(exists=True), help="Project path")
@click.option(
    "--priority", type=click.Choice(["low", "medium", "high", "critical"]), default="medium"
)
@click.option("--process", is_flag=True, help="Process immediately instead of queueing")
def query(question: str, path: Optional[str], priority: str, process: bool):
    """
    Queue or process a query for Oracle

    By default, queries are queued. Use --process to execute immediately.
    """
    project_path = Path(path) if path else Path.cwd()

    # Map priority string to enum
    priority_map = {
        "low": QueryPriority.LOW,
        "medium": QueryPriority.MEDIUM,
        "high": QueryPriority.HIGH,
        "critical": QueryPriority.CRITICAL,
    }

    try:
        with console.status("[bold cyan]Loading Oracle..."):
            oracle_agent = StatefulOracle(project_path=project_path)

        # Queue the query
        queued_query = oracle_agent.queue_query(question, priority=priority_map[priority])

        if not process:
            # Just queue it
            console.print()
            console.print(
                Panel.fit(
                    f"[bold green]✓ Query queued![/bold green]\n\n"
                    f"[cyan]ID:[/cyan] {queued_query.id}\n"
                    f"[cyan]Question:[/cyan] {question}\n"
                    f"[cyan]Priority:[/cyan] {priority.upper()}\n"
                    f"[cyan]State:[/cyan] {queued_query.state.value}\n\n"
                    f"[dim]Process with: groknroll oracle process {queued_query.id}[/dim]",
                    title="[bold]Query Queued[/bold]",
                    border_style="green",
                )
            )
        else:
            # Process immediately
            console.print()
            console.print(f"[bold cyan]Processing query {queued_query.id}...[/bold cyan]")

            with console.status("[bold cyan]Oracle analyzing..."):
                response = oracle_agent.process_query(queued_query.id)

            if response:
                console.print()
                console.print(
                    Panel(
                        Markdown(response.answer),
                        title=f"[bold cyan]Oracle: {queued_query.id}[/bold cyan]",
                        border_style="cyan",
                    )
                )

                console.print()
                console.print(f"[dim]Confidence: {response.confidence}[/dim]")
                console.print(f"[dim]Sources: {len(response.sources)} files[/dim]")
                console.print(f"[dim]Time: {response.execution_time:.2f}s[/dim]")
            else:
                console.print("[bold red]Error:[/bold red] Query processing failed")

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        import traceback

        traceback.print_exc()
        sys.exit(1)


@oracle.command()
@click.argument("query_id", required=False)
@click.option("--path", type=click.Path(exists=True), help="Project path")
@click.option("--all", "process_all", is_flag=True, help="Process all pending queries")
@click.option("--max", type=int, help="Max queries to process")
def process(query_id: Optional[str], path: Optional[str], process_all: bool, max: Optional[int]):
    """
    Process queued queries

    Process a specific query by ID, or use --all to process all pending.
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        with console.status("[bold cyan]Loading Oracle..."):
            oracle_agent = StatefulOracle(project_path=project_path)

        if process_all:
            # Process all pending
            console.print()
            console.print("[bold cyan]Processing all pending queries...[/bold cyan]")

            responses = oracle_agent.process_all(max_queries=max)

            console.print()
            console.print(
                Panel.fit(
                    f"[bold green]✓ Processed {len(responses)} queries![/bold green]\n\n"
                    "[dim]Use 'groknroll oracle status' to see results[/dim]",
                    title="[bold]Batch Complete[/bold]",
                    border_style="green",
                )
            )

        elif query_id:
            # Process specific query
            console.print()
            console.print(f"[bold cyan]Processing query {query_id}...[/bold cyan]")

            with console.status("[bold cyan]Oracle analyzing..."):
                response = oracle_agent.process_query(query_id)

            if response:
                console.print()
                console.print(
                    Panel(
                        Markdown(response.answer),
                        title=f"[bold cyan]Oracle: {query_id}[/bold cyan]",
                        border_style="cyan",
                    )
                )

                console.print()
                console.print(f"[dim]Confidence: {response.confidence}[/dim]")
                console.print(f"[dim]Sources: {len(response.sources)} files[/dim]")
                console.print(f"[dim]Time: {response.execution_time:.2f}s[/dim]")
            else:
                console.print("[bold red]Error:[/bold red] Query processing failed or blocked")

        else:
            # Process next by priority
            console.print()
            console.print("[bold cyan]Processing next query by priority...[/bold cyan]")

            with console.status("[bold cyan]Oracle analyzing..."):
                response = oracle_agent.process_next()

            if response:
                query = oracle_agent.state_machine.current_analyzing or "unknown"
                console.print()
                console.print(
                    Panel(
                        Markdown(response.answer),
                        title=f"[bold cyan]Oracle: {query}[/bold cyan]",
                        border_style="cyan",
                    )
                )

                console.print()
                console.print(f"[dim]Confidence: {response.confidence}[/dim]")
                console.print(f"[dim]Sources: {len(response.sources)} files[/dim]")
                console.print(f"[dim]Time: {response.execution_time:.2f}s[/dim]")
            else:
                console.print("[yellow]No pending queries to process[/yellow]")

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        import traceback

        traceback.print_exc()
        sys.exit(1)


@oracle.command()
@click.option("--path", type=click.Path(exists=True), help="Project path")
def status(path: Optional[str]):
    """
    Show Oracle state machine status
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        with console.status("[bold cyan]Loading Oracle..."):
            oracle_agent = StatefulOracle(project_path=project_path)

        status_data = oracle_agent.get_status()

        # Status panel
        console.print()
        console.print(
            Panel.fit(
                f"[bold cyan]Total Queries:[/bold cyan] {status_data['total_queries']}\n"
                f"[cyan]Pending:[/cyan] {status_data['pending']}\n"
                f"[cyan]Analyzing:[/cyan] {status_data['analyzing']}\n"
                f"[cyan]Reviewed:[/cyan] {status_data['reviewed']}\n"
                f"[cyan]Completed:[/cyan] {status_data['completed']}\n"
                f"[cyan]Failed:[/cyan] {status_data['failed']}\n\n"
                f"[cyan]Current:[/cyan] {status_data['current_analyzing'] or 'None'}",
                title="[bold]Oracle Status[/bold]",
                border_style="cyan",
            )
        )

        # State machine rules
        console.print()
        console.print("[bold]State Machine:[/bold] PENDING → ANALYZING → REVIEWED → COMPLETED")
        console.print("[dim]Rules: Max 1 in ANALYZING, Sequential transitions[/dim]")

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@oracle.command()
@click.option("--path", type=click.Path(exists=True), help="Project path")
@click.option(
    "--state", type=click.Choice(["pending", "analyzing", "reviewed", "completed", "failed"])
)
@click.option("--limit", type=int, default=10, help="Max queries to show")
def list(path: Optional[str], state: Optional[str], limit: int):
    """
    List queries by state
    """
    project_path = Path(path) if path else Path.cwd()

    # Map state string to enum
    state_map = {
        "pending": QueryState.PENDING,
        "analyzing": QueryState.ANALYZING,
        "reviewed": QueryState.REVIEWED,
        "completed": QueryState.COMPLETED,
        "failed": QueryState.FAILED,
    }

    try:
        with console.status("[bold cyan]Loading Oracle..."):
            oracle_agent = StatefulOracle(project_path=project_path)

        state_filter = state_map.get(state) if state else None
        queries = oracle_agent.list_queries(state=state_filter, limit=limit)

        if not queries:
            console.print("[yellow]No queries found[/yellow]")
            return

        # Display queries in table
        table = Table(
            title=f"Oracle Queries{' - ' + state.upper() if state else ''}",
            show_header=True,
        )
        table.add_column("ID", style="cyan", width=8)
        table.add_column("State", style="green", width=12)
        table.add_column("Priority", style="yellow", width=10)
        table.add_column("Question", style="white")
        table.add_column("Created", style="dim", width=16)

        for query in queries:
            # Truncate question if too long
            question = query.question if len(query.question) <= 60 else query.question[:57] + "..."

            table.add_row(
                query.id,
                query.state.value,
                f"P{query.priority.value}",
                question,
                query.created_at[:16],
            )

        console.print()
        console.print(table)

        console.print()
        console.print(f"[dim]Showing {len(queries)} queries[/dim]")

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@oracle.command()
@click.argument("query_id")
@click.option("--path", type=click.Path(exists=True), help="Project path")
def show(query_id: str, path: Optional[str]):
    """
    Show detailed query information
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        with console.status("[bold cyan]Loading Oracle..."):
            oracle_agent = StatefulOracle(project_path=project_path)

        query = oracle_agent.get_query_result(query_id)

        if not query:
            console.print(f"[bold red]Error:[/bold red] Query {query_id} not found")
            sys.exit(1)

        # Query details
        console.print()
        console.print(
            Panel.fit(
                f"[bold cyan]ID:[/bold cyan] {query.id}\n"
                f"[cyan]State:[/cyan] {query.state.value}\n"
                f"[cyan]Priority:[/cyan] P{query.priority.value}\n"
                f"[cyan]Created:[/cyan] {query.created_at}\n"
                f"[cyan]Started:[/cyan] {query.started_at or 'N/A'}\n"
                f"[cyan]Completed:[/cyan] {query.completed_at or 'N/A'}",
                title="[bold]Query Info[/bold]",
                border_style="cyan",
            )
        )

        # Question
        console.print()
        console.print("[bold]Question:[/bold]")
        console.print(query.question)

        # Answer (if available)
        if query.answer:
            console.print()
            console.print(
                Panel(
                    Markdown(query.answer),
                    title="[bold cyan]Answer[/bold cyan]",
                    border_style="cyan",
                )
            )

            console.print()
            console.print(f"[dim]Confidence: {query.confidence}[/dim]")
            console.print(f"[dim]Sources: {len(query.sources)} files[/dim]")
            console.print(f"[dim]Time: {query.execution_time:.2f}s[/dim]")

        # Error (if failed)
        if query.error:
            console.print()
            console.print(f"[bold red]Error:[/bold red] {query.error}")

        # Transitions
        if query.transitions:
            console.print()
            console.print("[bold]State Transitions:[/bold]")
            for transition in query.transitions:
                console.print(
                    f"  {transition['from']} → {transition['to']} "
                    f"[dim]({transition['timestamp'][:16]})[/dim]"
                )

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@oracle.command()
@click.argument("query_id")
@click.option("--path", type=click.Path(exists=True), help="Project path")
def accept(query_id: str, path: Optional[str]):
    """
    Accept a reviewed query
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        with console.status("[bold cyan]Loading Oracle..."):
            oracle_agent = StatefulOracle(project_path=project_path)

        oracle_agent.accept_query(query_id)

        console.print()
        console.print(
            Panel.fit(
                f"[bold green]✓ Query accepted![/bold green]\n\n"
                f"[cyan]ID:[/cyan] {query_id}\n"
                f"[cyan]State:[/cyan] COMPLETED",
                title="[bold]Accepted[/bold]",
                border_style="green",
            )
        )

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@oracle.command()
@click.argument("query_id")
@click.option("--path", type=click.Path(exists=True), help="Project path")
def retry(query_id: str, path: Optional[str]):
    """
    Retry a failed query
    """
    project_path = Path(path) if path else Path.cwd()

    try:
        with console.status("[bold cyan]Loading Oracle..."):
            oracle_agent = StatefulOracle(project_path=project_path)

        console.print()
        console.print(f"[bold cyan]Retrying query {query_id}...[/bold cyan]")

        response = oracle_agent.retry_query(query_id)

        if response:
            console.print()
            console.print(
                Panel(
                    Markdown(response.answer),
                    title=f"[bold cyan]Oracle: {query_id}[/bold cyan]",
                    border_style="cyan",
                )
            )

            console.print()
            console.print(f"[dim]Confidence: {response.confidence}[/dim]")
            console.print(f"[dim]Sources: {len(response.sources)} files[/dim]")
            console.print(f"[dim]Time: {response.execution_time:.2f}s[/dim]")
        else:
            console.print("[bold red]Error:[/bold red] Retry failed or blocked")

    except Exception as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


if __name__ == "__main__":
    oracle()
