from __future__ import annotations

import argparse
import json
from pathlib import Path

from rich.console import Console, Group
from rich.json import JSON
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

from . import __version__
from .detector import scan


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="litellm-detector",
        description="Detect installed LiteLLM packages without importing them.",
    )
    parser.add_argument(
        "--root",
        action="append",
        default=[],
        help="Extra filesystem root to inspect. Can be passed multiple times.",
    )
    parser.add_argument(
        "--crawl",
        "--crawal",
        action="store_true",
        help=(
            "Recursively crawl filesystem roots looking for Python package directories. "
            "With no --root values, this scans the whole disk."
        ),
    )
    parser.add_argument(
        "--json",
        action="store_true",
        help="Emit machine-readable JSON instead of the rich terminal report.",
    )
    parser.add_argument(
        "--show-files",
        action="store_true",
        help="Show suspicious files found near the LiteLLM package.",
    )
    parser.add_argument(
        "--no-animation",
        action="store_true",
        help="Disable spinner animation for CI or plain logs.",
    )
    parser.add_argument(
        "--version",
        action="version",
        version=f"%(prog)s {__version__}",
    )
    return parser


def main() -> int:
    args = build_parser().parse_args()
    console = Console()

    if args.json:
        findings = scan(args.root, crawl=args.crawl)
        console.print(
            JSON.from_data(
                {
                    "tool": "litellm-detector",
                    "version": __version__,
                    "roots": [str(Path(root).expanduser()) for root in args.root],
                    "crawl": args.crawl,
                    "findings": [finding.to_dict() for finding in findings],
                }
            )
        )
        return 1 if any(item.status == "warning" for item in findings) else 0

    console.print(_hero_panel())
    if args.no_animation:
        findings = scan(args.root, crawl=args.crawl)
    else:
        with console.status(
            "[bold cyan]Scanning Python environments for LiteLLM metadata...[/]",
            spinner="dots12",
        ):
            findings = scan(args.root, crawl=args.crawl)

    console.print(_credits_panel())
    console.print(_summary_panel(findings))

    for finding in findings:
        console.print(_finding_table(finding, show_files=args.show_files))

    if not findings:
        console.print(
            Panel(
                (
                    "No `litellm` package metadata was found in the current interpreter paths, "
                    "supplied roots, or crawl targets."
                ),
                title="Result",
                border_style="green",
            )
        )
        return 0

    return 1 if any(item.status == "warning" for item in findings) else 0


def _hero_panel() -> Panel:
    text = Text()
    text.append("LiteLLM Detector\n", style="bold white")
    text.append("Filesystem-only LiteLLM package discovery with advisory checks", style="cyan")
    return Panel(text, border_style="bright_blue")


def _credits_panel() -> Panel:
    body = Text()
    body.append("Built by ", style="white")
    body.append("Abhiyan Timilsina", style="bold magenta")
    body.append("\nLinkedIn: ", style="white")
    body.append(
        "https://www.linkedin.com/in/abhiyan-timilsina-6b679b142/",
        style="underline bright_blue",
    )
    body.append("\nOpen to new opportunities.", style="yellow")
    return Panel(body, title="Credits", border_style="magenta")


def _summary_panel(findings) -> Panel:
    total = len(findings)
    warnings = sum(1 for finding in findings if finding.status == "warning")
    ok = sum(1 for finding in findings if finding.status == "ok")
    summary = Text()
    summary.append(f"Detected distributions: {total}\n", style="bold white")
    summary.append(f"Warnings: {warnings}\n", style="yellow")
    summary.append(f"OK: {ok}", style="green")
    style = "yellow" if warnings else "green"
    return Panel(summary, title="Environment Scan Complete", border_style=style)


def _finding_table(finding, show_files: bool) -> Panel:
    table = Table.grid(padding=(0, 1))
    table.add_column(style="bold white", width=18)
    table.add_column(style="cyan")
    table.add_row("Status", finding.status)
    table.add_row("Package", finding.name)
    table.add_row("Version", finding.version)
    table.add_row("Metadata", finding.metadata_path)
    table.add_row("Package Path", finding.package_path or "not found")
    table.add_row("Entry Points", ", ".join(finding.entry_points) if finding.entry_points else "none")
    table.add_row("Notes", "\n".join(f"- {note}" for note in finding.notes))

    if finding.advisories:
        advisory_lines = [
            f"{item['id']} ({item['published_on']}): {item['title']} | fixed >= {item['fixed_version']}"
            for item in finding.advisories
        ]
        table.add_row("Advisories", "\n".join(advisory_lines))

    if show_files and finding.suspicious_files:
        table.add_row("Suspicious Files", "\n".join(finding.suspicious_files))

    title_style = "yellow" if finding.status == "warning" else "green"
    return Panel(Group(table), title="Finding", border_style=title_style)


if __name__ == "__main__":
    raise SystemExit(main())
