"""Command-line interface for the AccuWeather client.

Requires the ``cli`` extra::

    pip install 'accuweather-client[cli]'

The API key is read from the ``--token`` option or the
``ACCUWEATHER_API_KEY`` environment variable (a ``.env`` file in the
working directory is honored when python-dotenv is installed).

Examples::

    accuweather now --city sydney
    accuweather forecast --city sydney --days 5
    accuweather hourly --lat 51.9 --lon -4.8 --hours 12
    accuweather alerts --poi "Eiffel tower"
"""

import os

try:
    import typer
    from rich.console import Console
    from rich.table import Table
except ImportError as exc:  # pragma: no cover
    raise ImportError(
        "typer and rich are required for the CLI. Install them with: "
        "pip install 'accuweather-client[cli]'"
    ) from exc

from accuweather_client import WeatherClient, __version__
from accuweather_client.exceptions import AccuWeatherError

app = typer.Typer(
    name="accuweather",
    help="Human-friendly AccuWeather CLI: weather by city, POI or lat/lon.",
    no_args_is_help=True,
)
console = Console()

_TOKEN_ENV = "ACCUWEATHER_API_KEY"


def _load_dotenv() -> None:
    """Load a .env file when python-dotenv is available; ignore otherwise."""
    try:
        from dotenv import load_dotenv

        load_dotenv()
    except ImportError:
        pass


def _build_client(
    token: str | None,
    city: str | None,
    country: str | None,
    poi: str | None,
    lat: float | None,
    lon: float | None,
) -> WeatherClient:
    """Create a WeatherClient from CLI options, with friendly errors."""
    _load_dotenv()
    token = token or os.getenv(_TOKEN_ENV) or os.getenv("API_TOKEN")
    if not token:
        console.print(
            f"[red]No API key. Pass --token or set {_TOKEN_ENV} "
            "(get a key at https://developer.accuweather.com).[/red]"
        )
        raise typer.Exit(code=2)
    try:
        return WeatherClient(
            token=token, city=city, country=country, poi=poi, lat=lat, lon=lon
        )
    except (AccuWeatherError, ValueError) as exc:
        console.print(f"[red]{exc}[/red]")
        raise typer.Exit(code=2) from exc


def _location_options():
    """Shared location option definitions (kept in one place)."""
    return {
        "city": typer.Option(None, help="City name, e.g. 'sydney'."),
        "country": typer.Option(
            None, help="Country to disambiguate the city."
        ),
        "poi": typer.Option(
            None, help="Point of interest, e.g. 'Eiffel tower'."
        ),
        "lat": typer.Option(None, help="Latitude (use with --lon)."),
        "lon": typer.Option(None, help="Longitude (use with --lat)."),
        "token": typer.Option(None, help=f"API key (default: ${_TOKEN_ENV})."),
    }


_OPTS = _location_options()


@app.command()
def now(
    city: str | None = _OPTS["city"],
    country: str | None = _OPTS["country"],
    poi: str | None = _OPTS["poi"],
    lat: float | None = _OPTS["lat"],
    lon: float | None = _OPTS["lon"],
    token: str | None = _OPTS["token"],
) -> None:
    """Show the current weather conditions."""
    client = _build_client(token, city, country, poi, lat, lon)
    try:
        conditions = client.get_current_conditions()
        console.print(f"[bold]{client.location}[/bold]")
        console.print(conditions.current_conditions)
    except AccuWeatherError as exc:
        console.print(f"[red]{exc}[/red]")
        raise typer.Exit(code=1) from exc


@app.command()
def forecast(
    days: int = typer.Option(5, help="Forecast length: 1, 5, 10 or 15."),
    city: str | None = _OPTS["city"],
    country: str | None = _OPTS["country"],
    poi: str | None = _OPTS["poi"],
    lat: float | None = _OPTS["lat"],
    lon: float | None = _OPTS["lon"],
    token: str | None = _OPTS["token"],
) -> None:
    """Show the daily forecast as a table."""
    client = _build_client(token, city, country, poi, lat, lon)
    try:
        result = client.get_daily_forecast(days=days)
        console.print(f"[bold]{client.location}[/bold] - {result.text}")
        table = Table("Date", "", "Day", "Min", "Max", "Rain %")
        for day in result.daily_forecasts:
            temp = day.temperature
            table.add_row(
                day.date[:10],
                day.day.emoji,
                day.day.icon_phrase,
                f"{temp['Minimum']['Value']}{temp['Minimum']['Unit']}",
                f"{temp['Maximum']['Value']}{temp['Maximum']['Unit']}",
                str(day.day.precipitation_probability),
            )
        console.print(table)
    except (AccuWeatherError, ValueError) as exc:
        console.print(f"[red]{exc}[/red]")
        raise typer.Exit(code=1) from exc


@app.command()
def hourly(
    hours: int = typer.Option(
        12, help="Forecast length: 1, 12, 24, 72 or 120."
    ),
    city: str | None = _OPTS["city"],
    country: str | None = _OPTS["country"],
    poi: str | None = _OPTS["poi"],
    lat: float | None = _OPTS["lat"],
    lon: float | None = _OPTS["lon"],
    token: str | None = _OPTS["token"],
) -> None:
    """Show the hourly forecast as a table."""
    client = _build_client(token, city, country, poi, lat, lon)
    try:
        result = client.get_hourly_forecast(hours=hours)
        console.print(f"[bold]{client.location}[/bold]")
        table = Table("Time", "", "Forecast", "Temp", "Rain %")
        for hour in result.output:
            table.add_row(
                hour.date_time,
                hour.emoji,
                hour.icon_phrase,
                str(hour.temperature),
                str(hour.precipitation_probability),
            )
        console.print(table)
    except (AccuWeatherError, ValueError) as exc:
        console.print(f"[red]{exc}[/red]")
        raise typer.Exit(code=1) from exc


@app.command()
def alerts(
    city: str | None = _OPTS["city"],
    country: str | None = _OPTS["country"],
    poi: str | None = _OPTS["poi"],
    lat: float | None = _OPTS["lat"],
    lon: float | None = _OPTS["lon"],
    token: str | None = _OPTS["token"],
) -> None:
    """Show active severe-weather alerts."""
    client = _build_client(token, city, country, poi, lat, lon)
    try:
        result = client.get_alerts()
        console.print(f"[bold]{client.location}[/bold]")
        console.print(str(result))
    except AccuWeatherError as exc:
        console.print(f"[red]{exc}[/red]")
        raise typer.Exit(code=1) from exc


@app.command()
def version() -> None:
    """Show the accuweather-client version."""
    console.print(f"accuweather-client {__version__}")


if __name__ == "__main__":  # pragma: no cover
    app()
