"""bilge analyze - Analyze dataset and tokenizer."""

import json
from pathlib import Path

import typer
from rich.console import Console
from rich.panel import Panel
from rich.table import Table

from bilgeai.analyzer.dataset import analyze_dataset
from bilgeai.analyzer.privacy import scan_for_pii
from bilgeai.analyzer.quality import run_quality_checks
from bilgeai.core.constants import PROJECT_DIR
from bilgeai.core.exceptions import DataError

console = Console()


def analyze_command(
    data: Path = typer.Option(None, "--data", "-d", help="Path to dataset file or directory"),
    skip_pii: bool = typer.Option(False, "--skip-pii", help="Skip PII scanning"),
    tokenizer: str = typer.Option(
        None, "--tokenizer", "-t", help="Tokenizer/model name for accurate token counting"
    ),
) -> None:
    """Analyze dataset and tokenizer."""
    model_name = tokenizer

    if data is None:
        try:
            from bilgeai.core.config import BilgeConfig

            config = BilgeConfig.load()
            data = Path(config.data.path)
            if model_name is None:
                model_name = config.model.name
        except Exception:
            console.print("[red]No dataset specified. Use --data or configure bilge.yaml[/red]")
            raise typer.Exit(1) from None

    # If tokenizer not set via flag, try to get model name from config
    if model_name is None:
        try:
            from bilgeai.core.config import BilgeConfig

            config = BilgeConfig.load()
            model_name = config.model.name
        except Exception:
            pass

    if not data.exists():
        console.print(f"[red]Dataset not found: {data}[/red]")
        raise typer.Exit(1)

    console.print(f"[bold]Analyzing dataset: {data}[/bold]")
    if model_name:
        console.print(f"[dim]Tokenizer: {model_name}[/dim]")
    console.print()

    try:
        profile = analyze_dataset(data, tokenizer_name=model_name)
    except DataError as e:
        console.print(f"[red]Error: {e}[/red]")
        if e.suggestion:
            console.print(f"[yellow]Suggestion: {e.suggestion}[/yellow]")
        raise typer.Exit(1) from None

    # Dataset overview table
    table = Table(title="Dataset Profile", show_header=True)
    table.add_column("Metric", style="cyan")
    table.add_column("Value", style="green")

    table.add_row("Path", str(profile.path))
    table.add_row("Format", profile.format)
    table.add_row("Rows", f"{profile.num_rows:,}")
    table.add_row("Columns", ", ".join(profile.columns))
    if profile.text_column:
        table.add_row("Text Column", profile.text_column)
    table.add_row("Size", f"{profile.estimated_size_mb:.2f} MB")
    if profile.language:
        lang_str = profile.language
        if profile.language_distribution:
            dist = ", ".join(
                f"{lang} {pct:.0%}" for lang, pct in profile.language_distribution.items()
            )
            lang_str = f"{profile.language} ({dist})"
        table.add_row("Language", lang_str)
    if profile.duplicate_ratio > 0:
        table.add_row("Duplicates", f"{profile.duplicate_ratio:.1%}")
    if profile.empty_ratio > 0:
        table.add_row("Empty Rows", f"{profile.empty_ratio:.1%}")
    console.print(table)

    # Token statistics
    if profile.avg_tokens > 0:
        console.print()
        method_label = (
            f"Token Stats ({profile.tokenizer_name})"
            if profile.token_method == "tokenizer"
            else "Token Estimates (char/4)"
        )
        token_table = Table(title=method_label, show_header=True)
        token_table.add_column("Metric", style="cyan")
        token_table.add_column("Value", style="green")

        token_table.add_row("Average", f"{profile.avg_tokens:.0f}")
        token_table.add_row("Min", f"{profile.min_tokens:,}")
        token_table.add_row("Max", f"{profile.max_tokens:,}")
        token_table.add_row("P50", f"{profile.p50_tokens:,}")
        token_table.add_row("P90", f"{profile.p90_tokens:,}")
        token_table.add_row("P99", f"{profile.p99_tokens:,}")
        console.print(token_table)

        if profile.token_method == "char_estimate":
            console.print("[dim]Tip: Use --tokenizer <model> for accurate token counts[/dim]")

    # Quality checks
    rows = _load_rows(data)
    if rows:
        issues = run_quality_checks(rows)
        if issues:
            console.print()
            console.print("[bold yellow]Quality Issues Found:[/bold yellow]")
            for issue in issues:
                icon = "[red]![/red]" if issue.severity == "error" else "[yellow]![/yellow]"
                console.print(f"  {icon} {issue.message} ({issue.count} occurrence(s))")
            profile.quality_issues = issues
        else:
            console.print("\n[green]No quality issues found.[/green]")

        # PII scan
        if not skip_pii:
            pii_findings = scan_for_pii(rows)
            if pii_findings:
                console.print()
                console.print(
                    Panel(
                        "\n".join(
                            f"  [red]{f.pii_type}[/red]: {f.count} occurrence(s)"
                            for f in pii_findings
                        ),
                        title="[bold red]PII Detected[/bold red]",
                        expand=False,
                    )
                )
                profile.pii_findings = pii_findings
            else:
                console.print("\n[green]No PII detected.[/green]")

    # LLM insights (conditional on API key availability)
    _try_llm_insights(profile, rows)

    # Save profile
    project_dir = Path.cwd() / PROJECT_DIR
    project_dir.mkdir(parents=True, exist_ok=True)
    profile_path = project_dir / "dataset_profile.json"
    profile_path.write_text(
        json.dumps(profile.model_dump(), indent=2, ensure_ascii=False), encoding="utf-8"
    )
    console.print(f"\n[dim]Profile saved to {profile_path}[/dim]")

    from bilgeai.cli.hints import show_next_hint

    show_next_hint("analyze", console)


def _load_rows(path: Path) -> list[dict]:
    """Load rows from a dataset file or directory for quality/PII checks."""
    # Directory: load rows from first file only (sample)
    if path.is_dir():
        supported = (".jsonl", ".json", ".csv")
        files = sorted(f for f in path.iterdir() if f.is_file() and f.suffix.lower() in supported)
        if files:
            return _load_rows(files[0])
        return []

    suffix = path.suffix.lower()
    try:
        if suffix in (".jsonl", ".json"):
            content = path.read_text(encoding="utf-8").strip()
            if content.startswith("["):
                return json.loads(content)
            return [json.loads(line) for line in content.split("\n") if line.strip()]
        elif suffix == ".csv":
            import csv

            with open(path, encoding="utf-8") as f:
                return list(csv.DictReader(f))
    except Exception:
        pass
    return []


def _try_llm_insights(profile, rows: list[dict]) -> None:
    """Try to get LLM-powered dataset insights. Skips silently if API unavailable."""
    import os

    try:
        from bilgeai.core.config import BilgeConfig

        config = BilgeConfig.load()
        llm_cfg = config.llm

        # Check API key availability (skip for local, check env for cloud)
        if llm_cfg.provider != "local":
            api_key = os.environ.get(llm_cfg.api_key_env, "")
            if not api_key:
                console.print(
                    "\n[dim]LLM insights icin API key ayarlayin: "
                    "'bilge init' ile provider secin.[/dim]"
                )
                return

        from bilgeai.analyzer.llm_evaluator import LLMDatasetEvaluator
        from bilgeai.llm.router import get_llm_client

        client = get_llm_client(
            provider=llm_cfg.provider,
            model=llm_cfg.model,
            api_key_env=llm_cfg.api_key_env,
            base_url=llm_cfg.base_url,
        )
        evaluator = LLMDatasetEvaluator(client)

        console.print("\n[dim]Getting LLM insights...[/dim]")
        sample = rows[:10] if rows else []
        insights = evaluator.evaluate(profile, sample, model_name=config.model.name)

        # Display insights
        insights_table = Table(title="LLM Dataset Insights", show_header=True)
        insights_table.add_column("Metric", style="cyan")
        insights_table.add_column("Value", style="green")

        suitability_colors = {
            "excellent": "green",
            "good": "green",
            "fair": "yellow",
            "poor": "red",
        }
        color = suitability_colors.get(insights.training_suitability, "white")
        insights_table.add_row(
            "Training Suitability",
            f"[{color}]{insights.training_suitability.upper()}[/{color}]",
        )
        insights_table.add_row("Quality Summary", insights.quality_summary)

        if insights.recommended_tokenizer:
            insights_table.add_row("Recommended Tokenizer", insights.recommended_tokenizer)

        console.print()
        console.print(insights_table)

        if insights.recommended_preprocessing:
            console.print("\n[bold]Recommended Preprocessing:[/bold]")
            for step in insights.recommended_preprocessing:
                console.print(f"  - {step}")

        if insights.warnings:
            console.print("\n[bold yellow]Warnings:[/bold yellow]")
            for w in insights.warnings:
                console.print(f"  [yellow]![/yellow] {w}")

        if insights.suggestions:
            console.print("\n[bold]Suggestions:[/bold]")
            for s in insights.suggestions:
                console.print(f"  - {s}")

    except Exception:
        # LLM insights are optional - don't break the command
        pass
