"""
Elephate CLI - Hoofdmodule met Typer commands

Commands:
- elephate            - Start interactieve sessie
- elephate calc [PATHS...] - Start calculatie
- elephate version - Toon versie
- elephate info - Toon systeem info
"""

# Suppress library deprecation warnings FIRST, before any imports
import warnings
import os

# Set environment variable to silence cryptography warnings
os.environ.setdefault("PYTHONWARNINGS", "ignore::DeprecationWarning")

# Multiple approaches to suppress the ARC4 deprecation warning
warnings.filterwarnings("ignore", category=DeprecationWarning)
warnings.filterwarnings("ignore", message=".*ARC4.*")
warnings.filterwarnings("ignore", module=".*pypdf.*")
warnings.filterwarnings("ignore", module=".*cryptography.*")

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

import typer
from rich.console import Console

from . import __version__
from .parser import scan_directory, DocumentType
from .mock_data import get_mock_results, get_mock_token_usage, CATEGORIES
from .output import (
    print_header,
    print_files_found,
    simulate_processing,
    print_results_table,
    print_mock_warning,
    print_token_usage,
    print_export_info,
    print_error,
    print_success,
    print_info,
    console
)
from .export import export_json, export_csv, get_export_summary
from .auth import (
    get_credentials,
    save_credentials,
    clear_credentials,
    redeem_access_code,
    start_device_flow,
    poll_device_flow,
    open_browser_for_auth,
    is_authenticated,
    get_config_dir,
)

app = typer.Typer(
    name="elephate",
    help="Elephate CLI - Calculatie Copilot voor installatiebedrijven",
    add_completion=False,
    invoke_without_command=True,
)


@app.callback()
def callback(ctx: typer.Context):
    """
    Elephate CLI - Calculatie Copilot voor installatiebedrijven.

    Start zonder arguments voor interactieve sessie, of gebruik een subcommand.
    """
    # Als geen subcommand is gegeven, start de interactieve sessie
    if ctx.invoked_subcommand is None:
        from .session import start_session
        start_session()
        raise typer.Exit()


@app.command()
def calc(
    paths: List[Path] = typer.Argument(
        None,
        help="Paden naar bestanden of directories met PDFs. Standaard: huidige directory",
        exists=False  # We doen eigen validatie
    ),
    output: Path = typer.Option(
        "./elephate-output",
        "--output", "-o",
        help="Output directory voor resultaten"
    ),
    no_export: bool = typer.Option(
        False,
        "--no-export",
        help="Sla export over, toon alleen resultaten"
    ),
    fast: bool = typer.Option(
        False,
        "--fast", "-f",
        help="Snel modus: skip animaties"
    ),
    recursive: bool = typer.Option(
        True,
        "--recursive/--no-recursive", "-r/-R",
        help="Zoek recursief in subdirectories"
    ),
):
    """
    Start een calculatie op basis van PDF bestanden.

    Scant de opgegeven paden voor PDF bestanden, classificeert ze als
    tekst-documenten (bestekken) of technische tekeningen, en genereert
    mock calculatie resultaten.

    \b
    Voorbeelden:
        elephate calc                    # Huidige directory
        elephate calc ./bestek           # Specifieke directory
        elephate calc ./bestek ./tek     # Meerdere directories
        elephate calc bestand.pdf        # Specifiek bestand
    """
    # Check authentication first
    if not is_authenticated():
        print_error("Je moet eerst inloggen om calculaties uit te voeren")
        console.print("[dim]Gebruik 'elephate login' om in te loggen[/]")
        raise typer.Exit(1)

    # Print header
    print_header(__version__)

    # Default naar huidige directory als geen paden opgegeven
    if not paths:
        paths = [Path(".")]

    # Valideer paden
    valid_paths = []
    for path in paths:
        if not path.exists():
            print_error(f"Pad niet gevonden: {path}")
            continue
        valid_paths.append(str(path))

    if not valid_paths:
        print_error("Geen geldige paden opgegeven")
        raise typer.Exit(1)

    # Scan voor PDFs
    pdf_files = scan_directory(valid_paths, recursive=recursive)

    if not pdf_files:
        print_error("Geen PDF bestanden gevonden")
        print_info("Tip: Gebruik --recursive om in subdirectories te zoeken")
        raise typer.Exit(1)

    # Toon gevonden bestanden
    print_files_found(pdf_files)

    # Simuleer verwerking
    delay = 0.01 if fast else 0.05
    stats = simulate_processing(pdf_files, delay=delay)

    # Genereer mock resultaten
    results = get_mock_results(
        num_docs=len(pdf_files),
        add_variation=True
    )

    # Toon resultaten
    print_results_table(results)

    # Toon token gebruik
    total_pages = sum(f.num_pages for f in pdf_files)
    token_usage = get_mock_token_usage(num_docs=len(pdf_files), num_pages=total_pages)
    print_token_usage(token_usage)

    print_mock_warning()

    # Export resultaten
    if not no_export:
        output_dir = str(output)
        json_path = export_json(results, output_dir)
        csv_paths = export_csv(results, f"{output_dir}/csv")
        all_files = get_export_summary(json_path, csv_paths)
        print_export_info(output_dir, all_files[:4])  # Toon eerste 4
        if len(all_files) > 4:
            print_info(f"...en {len(all_files) - 4} meer bestanden")

    print_success("Calculatie voltooid")


@app.command()
def version():
    """Toon versie informatie"""
    console.print(f"[bold]Elephate CLI[/] v{__version__}")
    console.print("[dim]Calculatie Copilot voor installatiebedrijven[/]")
    console.print()
    console.print("[yellow]Dit is een mockup versie - geen echte LLM integratie[/]")


@app.command()
def info():
    """Toon systeem informatie"""
    import platform

    console.print("[bold]Systeem Informatie[/]")
    console.print()
    console.print(f"  Elephate CLI:  v{__version__}")
    console.print(f"  Python:        {platform.python_version()}")
    console.print(f"  Platform:      {platform.system()} {platform.release()}")
    console.print()

    # Check dependencies
    console.print("[bold]Dependencies:[/]")

    deps = [
        ("typer", "typer"),
        ("rich", "rich"),
        ("pypdf", "pypdf"),
        ("pymupdf", "fitz"),
    ]

    for name, module in deps:
        try:
            mod = __import__(module)
            version = getattr(mod, "__version__", "?")
            console.print(f"  [green][OK][/] {name}: {version}")
        except ImportError:
            console.print(f"  [red][X][/] {name}: niet geinstalleerd")

    console.print()

    # Categorieën
    console.print("[bold]Ondersteunde STABU categorieën:[/]")
    for cat in CATEGORIES:
        console.print(f"  {cat.code} - {cat.full_name}")


@app.command()
def categories():
    """Toon ondersteunde STABU categorieën"""
    console.print("[bold]STABU Categorieën[/]")
    console.print()

    for cat in CATEGORIES:
        console.print(f"  [cyan]{cat.code}[/] {cat.name}")
        console.print(f"      [dim]{cat.full_name}[/]")
        console.print()


@app.command()
def login(
    code: Optional[str] = typer.Option(
        None,
        "--code", "-c",
        help="Toegangscode voor directe login"
    ),
    sso: bool = typer.Option(
        False,
        "--sso",
        help="Login via Auth0 (browser)"
    ),
):
    """
    Log in bij Elephate.

    Zonder opties: kies interactief tussen toegangscode of Auth0.
    Met --code: login direct met toegangscode.
    Met --sso: start Auth0 device flow in browser.
    """
    if is_authenticated():
        creds = get_credentials()
        console.print(f"[yellow]Je bent al ingelogd als {creds.email or 'onbekend'}[/]")
        console.print("[dim]Gebruik 'elephate logout' om uit te loggen[/]")
        raise typer.Exit(0)

    if code:
        # Direct login met code
        console.print("[dim]Verifiëren...[/]")
        success, message, credentials = redeem_access_code(code)

        if success and credentials:
            save_credentials(credentials)
            print_success(f"Ingelogd! {message}")
            if credentials.email:
                console.print(f"[dim]Welkom, {credentials.email}[/]")
        else:
            print_error(message)
            raise typer.Exit(1)

    elif sso:
        # Auth0 device flow
        _do_auth0_login()

    else:
        # Interactive selection
        console.print("[bold]Login bij Elephate[/]")
        console.print()
        console.print("  [cyan]1[/] Toegangscode")
        console.print("  [cyan]2[/] Auth0 (browser)")
        console.print()

        choice = typer.prompt("Kies methode (1/2)")

        if choice == "1":
            access_code = typer.prompt("Toegangscode")
            console.print("[dim]Verifiëren...[/]")
            success, message, credentials = redeem_access_code(access_code)

            if success and credentials:
                save_credentials(credentials)
                print_success(f"Ingelogd! {message}")
                if credentials.email:
                    console.print(f"[dim]Welkom, {credentials.email}[/]")
            else:
                print_error(message)
                raise typer.Exit(1)

        elif choice == "2":
            _do_auth0_login()

        else:
            print_error("Ongeldige keuze. Kies 1 of 2.")
            raise typer.Exit(1)


def _do_auth0_login():
    """Helper voor Auth0 device flow login."""
    console.print("[dim]Starting Auth0 device flow...[/]")

    success, message, device_data = start_device_flow()

    if not success:
        print_error(message)
        raise typer.Exit(1)

    # Show verification URL and code
    verification_uri = device_data.get("verification_uri_complete") or device_data.get("verification_uri")
    user_code = device_data.get("user_code", "")
    device_code = device_data.get("device_code", "")
    interval = device_data.get("interval", 5)

    console.print()
    console.print(f"[bold]Ga naar:[/] [cyan]{verification_uri}[/]")
    if user_code and not device_data.get("verification_uri_complete"):
        console.print(f"[bold]Code:[/] [yellow]{user_code}[/]")
    console.print()

    # Try to open browser
    if open_browser_for_auth(verification_uri):
        console.print("[dim]Browser geopend. Wachtend op autorisatie...[/]")
    else:
        console.print("[dim]Open de URL handmatig in je browser.[/]")

    console.print("[dim]Druk Ctrl+C om te annuleren[/]")
    console.print()

    # Poll for completion
    try:
        success, message, credentials = poll_device_flow(device_code, interval=interval)

        if success and credentials:
            save_credentials(credentials)
            print_success(f"Ingelogd via Auth0!")
            if credentials.email:
                console.print(f"[dim]Welkom, {credentials.email}[/]")
        else:
            print_error(message)
            raise typer.Exit(1)

    except KeyboardInterrupt:
        console.print()
        print_info("Login geannuleerd")
        raise typer.Exit(0)


@app.command()
def logout():
    """Log uit en verwijder opgeslagen credentials."""
    if not is_authenticated():
        console.print("[yellow]Je bent niet ingelogd[/]")
        raise typer.Exit(0)

    creds = get_credentials()
    if clear_credentials():
        print_success("Uitgelogd")
        if creds and creds.email:
            console.print(f"[dim]Tot ziens, {creds.email}[/]")
    else:
        print_error("Kon niet uitloggen")
        raise typer.Exit(1)


@app.command()
def status():
    """Toon huidige login status."""
    console.print("[bold]Status[/]")
    console.print()

    if is_authenticated():
        creds = get_credentials()
        console.print(f"  [green][OK][/] Ingelogd")
        if creds.email:
            console.print(f"  [dim]Email:[/] {creds.email}")
        console.print(f"  [dim]Methode:[/] {creds.auth_method}")
        console.print(f"  [dim]Config:[/] {get_config_dir()}")
    else:
        console.print(f"  [yellow][!][/] Niet ingelogd")
        console.print("[dim]Gebruik 'elephate login' om in te loggen[/]")


def main():
    """Entry point voor de CLI"""
    app()


if __name__ == "__main__":
    main()
