"""tyta trips subcommands: list, show."""

from __future__ import annotations

import asyncio
import json
import sys
from datetime import date
from typing import Annotated

import typer

from tyta.cli import render
from tyta.core import auth as core_auth
from tyta.core import config as core_config
from tyta.core import envelope as env
from tyta.core import trips as core_trips
from tyta.core import vehicles as core_vehicles
from tyta.core.client import ToyotaApiError, ToyotaClient

app = typer.Typer(
    name="trips",
    help="View trip history.",
    no_args_is_help=True,
)


def _get_state() -> dict:
    from tyta.cli.main import _get_state as _gs

    return _gs()


def _is_json_mode() -> bool:
    return _get_state().get("json", False)


def _load_config() -> dict:
    config_path = core_config.get_config_path(_get_state().get("config_file"))
    try:
        return core_config.load_config(config_path)
    except Exception:  # noqa: BLE001
        return {}


def _emit_and_exit(data: dict, exit_code: int = 0, command: str = "") -> None:
    json_mode = _is_json_mode()
    if exit_code != 0:
        render.render_error(data, json_mode)
    else:
        render.render_output(data, json_mode, command, config=_load_config())
    sys.exit(exit_code)


@app.command("list")
def trips_list(
    vin: Annotated[
        str | None,
        typer.Option("--vin", help="VIN of the vehicle.", show_default=False),
    ] = None,
    from_date: Annotated[
        str | None,
        typer.Option(
            "--from",
            help="Start date in YYYY-MM-DD format. Defaults to today minus 30 days.",
            show_default=False,
        ),
    ] = None,
    to_date: Annotated[
        str | None,
        typer.Option(
            "--to",
            help="End date in YYYY-MM-DD format. Defaults to today.",
            show_default=False,
        ),
    ] = None,
    routes: Annotated[
        bool,
        typer.Option("--route/--no-route", help="Include per-trip route geometry in response."),
    ] = False,
    limit: Annotated[
        int,
        typer.Option("--limit", help="Maximum trips to return (default: 10, max: 50)."),
    ] = 10,
    page: Annotated[
        int,
        typer.Option("--page", help="1-based page number (default: 1)."),
    ] = 1,
) -> None:
    """List trips for a vehicle (default: last 30 days)."""
    asyncio.run(_trips_list(vin, from_date, to_date, routes, limit, page))


async def _trips_list(
    vin_flag: str | None,
    from_str: str | None,
    to_str: str | None,
    routes: bool,
    limit: int,
    page: int,
) -> None:
    state = _get_state()
    debug = state.get("debug", False)
    auth_path = core_auth.get_auth_path(state.get("auth_file"))
    config_path = state.get("config_file")

    # Parse dates
    from_date: date | None = None
    to_date: date | None = None
    if from_str:
        try:
            from_date = date.fromisoformat(from_str)
        except ValueError:
            _emit_and_exit(
                env.error("invalid_input", f"Invalid --from date '{from_str}'. Use YYYY-MM-DD."),
                exit_code=1,
            )
            return
    if to_str:
        try:
            to_date = date.fromisoformat(to_str)
        except ValueError:
            _emit_and_exit(
                env.error("invalid_input", f"Invalid --to date '{to_str}'. Use YYYY-MM-DD."),
                exit_code=1,
            )
            return

    try:
        token_data = await core_auth.get_valid_token(auth_path)
    except core_auth.NotAuthenticatedError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except core_auth.TokenExpiredError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except json.JSONDecodeError:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("invalid_config", "Token file is malformed JSON."), exit_code=1)
        return

    client = ToyotaClient(
        access_token=token_data["access_token"],
        uuid=token_data["uuid"],
    )

    try:
        vin, warnings = await core_vehicles.resolve_vin(
            client, vin_flag=vin_flag, config_path=config_path
        )
    except core_vehicles.NoVehiclesError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except core_vehicles.VehicleNotFoundError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except ToyotaApiError as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("api_error", f"Toyota API error: {exc.message}"), exit_code=1)
        return

    try:
        data = await core_trips.list_trips(
            client,
            vin=vin,
            from_date=from_date,
            to_date=to_date,
            route=routes,
            limit=limit,
            page=page,
        )
    except ToyotaApiError as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("api_error", f"Toyota API error: {exc.message}"), exit_code=1)
        return
    except Exception as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("unknown_error", str(exc)), exit_code=1)
        return

    # Extract pagination metadata from response
    payload = (data or {}).get("payload") or {}
    metadata = payload.get("_metadata") or {}
    pagination = metadata.get("pagination") or {}
    total = pagination.get("totalCount")

    _emit_and_exit(
        env.ok(
            {
                "vin": vin,
                "trips": data,
                "limit": limit,
                "page": page,
                "total": total,
            },
            warnings=warnings,
        ),
        command="trips list",
    )


@app.command("show")
def trips_show(
    trip_id: Annotated[
        str,
        typer.Argument(help="Trip UUID to retrieve."),
    ],
    vin: Annotated[
        str | None,
        typer.Option("--vin", help="VIN of the vehicle.", show_default=False),
    ] = None,
) -> None:
    """Show full detail for a single trip (route always included)."""
    asyncio.run(_trips_show(trip_id, vin))


async def _trips_show(trip_id: str, vin_flag: str | None) -> None:
    state = _get_state()
    debug = state.get("debug", False)
    auth_path = core_auth.get_auth_path(state.get("auth_file"))
    config_path = state.get("config_file")

    try:
        token_data = await core_auth.get_valid_token(auth_path)
    except core_auth.NotAuthenticatedError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except core_auth.TokenExpiredError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except json.JSONDecodeError:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("invalid_config", "Token file is malformed JSON."), exit_code=1)
        return

    client = ToyotaClient(
        access_token=token_data["access_token"],
        uuid=token_data["uuid"],
    )

    try:
        vin, warnings = await core_vehicles.resolve_vin(
            client, vin_flag=vin_flag, config_path=config_path
        )
    except core_vehicles.NoVehiclesError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except core_vehicles.VehicleNotFoundError as exc:
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except ToyotaApiError as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("api_error", f"Toyota API error: {exc.message}"), exit_code=1)
        return

    try:
        data = await core_trips.get_trip(client, vin=vin, trip_id=trip_id)
    except ToyotaApiError as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("api_error", f"Toyota API error: {exc.message}"), exit_code=1)
        return
    except Exception as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error("unknown_error", str(exc)), exit_code=1)
        return

    _emit_and_exit(
        env.ok({"vin": vin, "trip_id": trip_id, "trip": data}, warnings=warnings),
        command="trips show",
    )
