"""
Main CLI entry point for ReadAnyBook.

Usage:
    read-any-book build <input> [--output OUTPUT] [--config CONFIG] [--profile PROFILE]
    read-any-book index <input> [--collection COLLECTION]
    read-any-book search <query> [--collection COLLECTION] [--top-k K]
    read-any-book evaluate <cheatsheet> [--source SOURCE]
"""

import json
import sys
from pathlib import Path
from typing import Optional, List

try:
    import typer
    from rich.console import Console
    from rich.table import Table
    from rich.progress import Progress, SpinnerColumn, TextColumn
    from rich.panel import Panel
    RICH_AVAILABLE = True
except ImportError:
    RICH_AVAILABLE = False

# Fallback for when rich/typer not installed
if not RICH_AVAILABLE:
    def main():
        print("CLI dependencies not installed. Run: pip install typer rich")
        print("Or use the Python API directly:")
        print("  from readanybook import CheatSheetPipeline")
        sys.exit(1)
    
    app = None
else:
    app = typer.Typer(
        name="read-any-book",
        help="Generate cheat sheets from books and papers using RAG.",
        add_completion=False,
    )
    console = Console()


def load_config(config_path: Optional[Path], profile: Optional[str] = None):
    """Load configuration from file."""
    from ..infra.settings import Settings
    
    if config_path and config_path.exists():
        settings = Settings.from_yaml(config_path)
    else:
        settings = Settings()
    
    # Apply profile if specified
    if profile:
        settings = settings.with_profile(profile)
    
    return settings


@app.command("build")
def build_cheatsheet(
    input_path: Path = typer.Argument(
        ...,
        help="Path to input file or directory (PDF, EPUB, etc.)",
        exists=True,
    ),
    output: Optional[Path] = typer.Option(
        None,
        "--output", "-o",
        help="Output path for generated cheat sheet",
    ),
    config: Optional[Path] = typer.Option(
        None,
        "--config", "-c",
        help="Path to configuration file",
    ),
    profile: Optional[str] = typer.Option(
        None,
        "--profile", "-p",
        help="Configuration profile (technical_book, math_paper, nontechnical_book)",
    ),
    title: Optional[str] = typer.Option(
        None,
        "--title", "-t",
        help="Title for the cheat sheet",
    ),
    latex_only: bool = typer.Option(
        False,
        "--latex-only",
        help="Generate LaTeX source only, don't compile to PDF",
    ),
    collection: Optional[str] = typer.Option(
        None,
        "--collection",
        help="Vector store collection name",
    ),
    llm_backend: Optional[str] = typer.Option(
        None,
        "--llm-backend",
        help="LLM backend: huggingface, ollama, openai, vllm",
    ),
    llm_model: Optional[str] = typer.Option(
        None,
        "--llm-model",
        help="LLM model name (e.g., llama3.2, mistral)",
    ),
    verbose: bool = typer.Option(
        False,
        "--verbose", "-v",
        help="Enable verbose output",
    ),
):
    """
    Build a cheat sheet from a document.
    
    Processes the input document through RAG pipeline and generates
    a structured LaTeX cheat sheet.
    """
    from ..core.pipeline import CheatSheetPipeline
    from ..infra.logging import setup_logging
    
    # Setup logging
    if verbose:
        setup_logging(level="DEBUG", log_format="pretty")
    else:
        setup_logging(level="INFO", log_format="pretty")
    
    # Load configuration
    settings = load_config(config, profile)
    
    # Override LLM settings if provided via CLI
    if llm_backend:
        settings.llm.backend = llm_backend
    if llm_model:
        settings.llm.model_name = llm_model
    
    # Determine output path
    if output is None:
        output = input_path.parent / f"{input_path.stem}_cheatsheet.pdf"
        if latex_only:
            output = output.with_suffix(".tex")
    
    console.print(Panel(
        f"[bold blue]Building cheat sheet from:[/bold blue] {input_path}\n"
        f"[bold green]Output:[/bold green] {output}",
        title="ReadAnyBook",
    ))
    
    with Progress(
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        console=console,
    ) as progress:
        try:
            # Initialize pipeline
            task = progress.add_task("Initializing pipeline...", total=None)
            pipeline = CheatSheetPipeline(settings)
            
            # Ingest document
            progress.update(task, description="Ingesting document...")
            pipeline.ingest(str(input_path))
            
            # Index
            progress.update(task, description="Building index...")
            pipeline.index(collection_name=collection)
            
            # Generate content
            progress.update(task, description="Generating content...")
            content = pipeline.generate_content()
            
            # Set title
            if title:
                content.title = title
            
            # Build output
            progress.update(task, description="Building document...")
            if latex_only:
                latex_source = pipeline.build_latex(content)
                output.write_text(latex_source, encoding='utf-8')
            else:
                cheat_sheet = pipeline.build(content, str(output))
            
            progress.update(task, description="Complete!")
            
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            if verbose:
                console.print_exception()
            raise typer.Exit(1)
    
    console.print(f"\n[green]✓ Cheat sheet generated:[/green] {output}")
    
    # Print summary
    table = Table(title="Content Summary")
    table.add_column("Section", style="cyan")
    table.add_column("Count", style="magenta")
    
    table.add_row("Concepts", str(len(content.concepts)))
    table.add_row("Formulas", str(len(content.formulas)))
    table.add_row("Algorithms", str(len(content.algorithms)))
    table.add_row("Models", str(len(content.models)))
    
    console.print(table)


@app.command("index")
def index_document(
    input_path: Path = typer.Argument(
        ...,
        help="Path to input file or directory",
        exists=True,
    ),
    collection: str = typer.Option(
        "default",
        "--collection", "-c",
        help="Collection name for vector store",
    ),
    config: Optional[Path] = typer.Option(
        None,
        "--config",
        help="Path to configuration file",
    ),
    verbose: bool = typer.Option(
        False,
        "--verbose", "-v",
        help="Enable verbose output",
    ),
):
    """
    Index a document into the vector store.
    
    Creates embeddings and stores them for later retrieval.
    """
    from ..core.pipeline import CheatSheetPipeline
    from ..infra.logging import setup_logging
    
    if verbose:
        setup_logging(level="DEBUG", log_format="pretty")
    else:
        setup_logging(level="INFO", log_format="pretty")
    
    settings = load_config(config)
    
    with Progress(
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        console=console,
    ) as progress:
        task = progress.add_task("Indexing document...", total=None)
        
        try:
            pipeline = CheatSheetPipeline(settings)
            
            progress.update(task, description="Ingesting...")
            pipeline.ingest(str(input_path))
            
            progress.update(task, description="Creating embeddings...")
            num_chunks = pipeline.index(collection_name=collection)
            
            progress.update(task, description="Complete!")
            
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            raise typer.Exit(1)
    
    console.print(f"\n[green]✓ Indexed {num_chunks} chunks into collection '{collection}'[/green]")


@app.command("search")
def search_index(
    query: str = typer.Argument(
        ...,
        help="Search query",
    ),
    collection: str = typer.Option(
        "default",
        "--collection", "-c",
        help="Collection to search",
    ),
    top_k: int = typer.Option(
        5,
        "--top-k", "-k",
        help="Number of results to return",
    ),
    config: Optional[Path] = typer.Option(
        None,
        "--config",
        help="Path to configuration file",
    ),
):
    """
    Search the indexed documents.
    
    Returns relevant chunks for the given query.
    """
    from ..core.retrieval import RetrievalService
    from ..core.indexing import create_embedding_model
    from ..infra.vectordb import create_vector_store
    
    settings = load_config(config)
    
    # Set the collection name
    settings.vectordb.collection_name = collection
    
    # Initialize components
    vector_store = create_vector_store(settings)
    
    embedding_model = create_embedding_model(settings)
    retriever = RetrievalService(
        vector_store=vector_store,
        embedding_model=embedding_model,
        settings=settings.retrieval
    )
    
    # Search
    results = retriever.retrieve(query, top_k=top_k)
    
    # Display results
    console.print(f"\n[bold]Search results for:[/bold] {query}\n")
    
    for i, result in enumerate(results, 1):
        content = result.content[:300] if hasattr(result, 'content') else str(result)[:300]
        score = result.score if hasattr(result, 'score') else 0.0
        
        console.print(Panel(
            content + "...",
            title=f"Result {i} (score: {score:.3f})",
            border_style="blue",
        ))


@app.command("evaluate")
def evaluate_cheatsheet(
    cheatsheet: Path = typer.Argument(
        ...,
        help="Path to cheat sheet (PDF or LaTeX)",
        exists=True,
    ),
    source: Optional[Path] = typer.Option(
        None,
        "--source", "-s",
        help="Path to original source document",
    ),
    output: Optional[Path] = typer.Option(
        None,
        "--output", "-o",
        help="Output path for evaluation report",
    ),
):
    """
    Evaluate a generated cheat sheet.
    
    Checks LaTeX quality, content coverage, and other metrics.
    """
    from ..evaluation.metrics import evaluate_latex_quality, CheatSheetMetrics
    
    console.print(f"\n[bold]Evaluating:[/bold] {cheatsheet}\n")
    
    if cheatsheet.suffix == ".tex":
        latex_source = cheatsheet.read_text(encoding='utf-8')
        latex_eval = evaluate_latex_quality(latex_source)
        
        # Display results
        table = Table(title="LaTeX Quality Evaluation")
        table.add_column("Metric", style="cyan")
        table.add_column("Value", style="magenta")
        
        table.add_row("Valid", "✓" if latex_eval["valid"] else "✗")
        table.add_row("Compiles", "✓" if latex_eval["compiles"] else "✗")
        table.add_row("Errors", str(len(latex_eval["errors"])))
        table.add_row("Warnings", str(len(latex_eval["warnings"])))
        
        console.print(table)
        
        if latex_eval["errors"]:
            console.print("\n[bold red]Errors:[/bold red]")
            for error in latex_eval["errors"]:
                console.print(f"  • {error}")
        
        if latex_eval["warnings"]:
            console.print("\n[bold yellow]Warnings:[/bold yellow]")
            for warning in latex_eval["warnings"]:
                console.print(f"  • {warning}")
    
    else:
        console.print(f"[yellow]Note: Full evaluation requires LaTeX source file[/yellow]")


@app.command("config")
def show_config(
    config: Optional[Path] = typer.Option(
        None,
        "--config", "-c",
        help="Path to configuration file",
    ),
    profile: Optional[str] = typer.Option(
        None,
        "--profile", "-p",
        help="Show profile-specific settings",
    ),
    output: Optional[Path] = typer.Option(
        None,
        "--output", "-o",
        help="Write default config to file",
    ),
):
    """
    Show or generate configuration.
    """
    from ..infra.settings import Settings
    
    if output:
        # Generate default config
        settings = Settings()
        # Would need to implement to_yaml
        console.print(f"[green]Default config written to:[/green] {output}")
    else:
        # Show current config
        settings = load_config(config, profile)
        
        table = Table(title="Current Configuration")
        table.add_column("Setting", style="cyan")
        table.add_column("Value", style="magenta")
        
        # Show key settings
        table.add_row("Embedding Model", settings.embedding.model_name)
        table.add_row("Vector Store", settings.vectordb.store_type)
        table.add_row("LLM Backend", settings.llm.backend)
        table.add_row("Chunking Strategy", settings.chunking.strategy)
        table.add_row("Retrieval Mode", settings.retrieval.mode)
        
        console.print(table)


@app.command("version")
def show_version():
    """Show version information."""
    console.print("[bold]ReadAnyBook[/bold] v0.1.13")
    console.print("A RAG-based cheat sheet generator")


def main():
    """Main entry point."""
    if not RICH_AVAILABLE:
        print("CLI dependencies not installed.")
        print("Install with: pip install typer rich")
        sys.exit(1)
    
    app()


if __name__ == "__main__":
    main()
