"""tyta auth subcommands: login, logout, status."""

from __future__ import annotations

import asyncio
import getpass
import json
import os
import sys

import typer
from loguru import logger

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.config import get_config_path

app = typer.Typer(
    name="auth",
    help="Manage Toyota account authentication.",
    no_args_is_help=True,
)


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

    return _gs()


def _get_debug() -> bool:
    return _get_state().get("debug", False)


def _get_auth_path_override() -> str | None:
    return _get_state().get("auth_file")


def _get_config_path_override() -> str | None:
    return _get_state().get("config_file")


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:
    """Render envelope (human or JSON) and exit."""
    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("login")
def login() -> None:
    """Authenticate with Toyota and save credentials."""
    debug = _get_debug()
    auth_path = core_auth.get_auth_path(_get_auth_path_override())

    # Collect credentials — use env vars if available
    username = os.environ.get("TOYOTA_USERNAME")
    password = os.environ.get("TOYOTA_PASSWORD")

    if not username:
        username = typer.prompt("Toyota username (email)")
    if not password:
        password = getpass.getpass("Toyota password: ")

    config_path = get_config_path(_get_config_path_override())

    try:
        token_data = asyncio.run(core_auth.login(username, password, auth_path, config_path))
    except core_auth.InvalidUsernameError as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _emit_and_exit(env.error(exc.code, exc.message), exit_code=1)
        return
    except core_auth.AuthError as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        _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", "Received malformed JSON from Toyota API."), exit_code=1
        )
        return
    except Exception as exc:
        if debug:
            import traceback

            traceback.print_exc(file=sys.stderr)
        logger.debug(f"Unexpected error during login: {exc}")
        _emit_and_exit(env.error("unknown_error", str(exc)), exit_code=1)
        return

    login_data: dict = {
        "message": "Logged in successfully.",
        "username": token_data["username"],
        "expires_at": token_data["expires_at"],
    }
    auto_vin_message = token_data.get("auto_vin_message")
    if auto_vin_message:
        login_data["auto_vin_message"] = auto_vin_message

    _emit_and_exit(
        env.ok(login_data),
        command="auth login",
    )


@app.command("logout")
def logout() -> None:
    """Delete saved credentials."""
    debug = _get_debug()
    auth_path = core_auth.get_auth_path(_get_auth_path_override())

    try:
        deleted = core_auth.logout(auth_path)
    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

    if deleted:
        _emit_and_exit(env.ok({"message": "Logged out successfully."}), command="auth logout")
    else:
        _emit_and_exit(
            env.ok({"message": "Already logged out (no token file found)."}),
            command="auth logout",
        )


@app.command("status")
def auth_status() -> None:
    """Show current authentication status."""
    debug = _get_debug()
    auth_path = core_auth.get_auth_path(_get_auth_path_override())

    try:
        result = core_auth.status(auth_path)
    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(result), command="auth status")
