"""Typer CLI entrypoint for depwhy.

Provides the ``depwhy`` command that analyzes Python dependency files for
version conflicts and prints human-readable (or JSON) output.

Exit codes (part of the public API):
- 0 = no conflicts detected
- 1 = at least one conflict detected
- 2 = usage error or unexpected runtime error
"""

from __future__ import annotations

import importlib.metadata
import logging
from pathlib import Path
from typing import Optional

import typer

import depwhy
from depwhy._analyze import analyze
from depwhy.explain.formatter import format_json, format_report

logger = logging.getLogger(__name__)

app = typer.Typer(
    name="depwhy",
    help="Explain Python dependency conflicts in plain English and suggest fixes.",
    add_completion=False,
)


def _version_callback(value: bool) -> None:
    """Print the version string and exit when ``--version`` is passed."""
    if value:
        typer.echo(f"depwhy {depwhy.__version__}")
        raise typer.Exit()


@app.command()
def main(
    source: Optional[str] = typer.Argument(  # noqa: UP045
        default=None,
        help="Path to requirements.txt or pyproject.toml.",
    ),
    env: bool = typer.Option(
        False,
        "--env",
        help="Analyze installed packages in the current virtual environment.",
    ),
    json_output: bool = typer.Option(
        False,
        "--json",
        help="Output machine-readable JSON.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        help="No output; exit code only.",
    ),
    offline: bool = typer.Option(
        False,
        "--offline",
        help="Use cached metadata only; do not make network requests.",
    ),
    python_version: Optional[str] = typer.Option(  # noqa: UP045
        None,
        "--python-version",
        help="Override Python version for marker evaluation (e.g. '3.11').",
    ),
    no_color: bool = typer.Option(
        False,
        "--no-color",
        help="Disable Rich color output.",
    ),
    version: bool = typer.Option(  # noqa: ARG001
        False,
        "--version",
        callback=_version_callback,
        is_eager=True,
        help="Print version and exit.",
    ),
) -> None:
    """Analyze Python dependency files for version conflicts."""
    # Validate mutually exclusive inputs
    if source is not None and env:
        typer.echo("Error: Cannot specify both SOURCE and --env.", err=True)
        raise typer.Exit(code=2)

    if source is None and not env:
        typer.echo("Error: Provide a SOURCE file or use --env.", err=True)
        raise typer.Exit(code=2)

    # Resolve the analysis source
    if env:
        analysis_source: str | list[str] = [
            f"{d.metadata['Name']}=={d.version}" for d in importlib.metadata.distributions()
        ]
    else:
        assert source is not None  # guaranteed by validation above
        path = Path(source)
        if not path.exists():
            typer.echo(f"Error: File not found: {source}", err=True)
            raise typer.Exit(code=2)
        analysis_source = source

    # Run analysis
    try:
        report = analyze(
            analysis_source,
            python_version=python_version,
            offline=offline,
        )
    except Exception as exc:
        typer.echo(f"Error: {exc}", err=True)
        raise typer.Exit(code=2) from exc

    # Determine exit code
    exit_code = 1 if report.has_conflicts else 0

    # Produce output
    if quiet:
        raise typer.Exit(code=exit_code)

    if json_output:
        typer.echo(format_json(report))
        raise typer.Exit(code=exit_code)

    format_report(report, no_color=no_color)
    raise typer.Exit(code=exit_code)
