from __future__ import annotations

from dataclasses import replace
from uuid import uuid4

import typer

from flow_xhs.cli.output.event_stream import emit_event
from flow_xhs.cli.spec.runtime_contracts import (
    command_option,
    emit_command_help_if_empty,
    group_summary,
    parameter_min,
)
from flow_xhs.contracts.command_inputs import AccountListInput, AuthLoginInput
from flow_xhs.services.auth_login import execute_auth_login
from flow_xhs.services.auth_status import execute_auth_status
from flow_xhs.services.account_list import execute_account_list
from flow_xhs.services.account_mutation import (
    execute_account_activate,
    execute_account_delete,
)
from flow_xhs.cli.context import CliContext
from flow_xhs.cli.runtime import run_async_command, run_sync_command
from flow_xhs.errors import InvalidArgsError

app = typer.Typer(
    help=group_summary(("account",)),
    no_args_is_help=True,
    options_metavar="[OPTIONS]",
    subcommand_metavar="<COMMAND>",
)


@app.command("login")
def account_login(
    ctx: typer.Context,
    mode: str = command_option(("account", "login"), "mode"),
    login_timeout_seconds: int = command_option(
        ("account", "login"),
        "login_timeout_seconds",
        min=parameter_min(("account", "login"), "login_timeout_seconds"),
    ),
    screenshot_path: str = command_option(("account", "login"), "screenshot_path", ""),
):
    """启动登录流程并写入持久登录态。"""
    cli_ctx: CliContext = ctx.obj
    effective_trace_id = cli_ctx.trace_id or uuid4().hex

    def _progress_callback(event_payload: dict) -> None:
        event_name = str(event_payload.get("event") or "").strip()
        if not event_name:
            return
        emit_event(
            command="account.login",
            event=event_name,
            trace_id=effective_trace_id,
            data={k: v for k, v in event_payload.items() if k != "event"},
        )

    async def _run():
        validated = AuthLoginInput(
            mode=mode,
            login_timeout_seconds=login_timeout_seconds,
            screenshot_path=screenshot_path,
        )
        return await execute_auth_login(
            account_uid=validated.account_uid or "",
            mode=validated.mode,
            login_timeout_seconds=validated.login_timeout_seconds,
            screenshot_path=validated.screenshot_path or "",
            progress_callback=_progress_callback,
        )

    effective_ctx = replace(
        cli_ctx,
        timeout=max(cli_ctx.timeout, login_timeout_seconds + 30),
        trace_id=effective_trace_id,
    )
    run_async_command(
        ctx=effective_ctx,
        command="account.login",
        func=_run,
    )


@app.command("status")
def account_status(
    ctx: typer.Context,
):
    """实时检查并刷新账号登录状态。"""
    cli_ctx: CliContext = ctx.obj

    async def _run() -> list[dict]:
        return await execute_auth_status()

    run_async_command(
        ctx=cli_ctx,
        command="account.status",
        func=_run,
    )


@app.command("list")
def account_list(
    ctx: typer.Context,
    only_active: str = command_option(("account", "list"), "only_active"),
):
    """列出账号池。"""
    cli_ctx: CliContext = ctx.obj

    def _run() -> list[dict]:
        validated = AccountListInput(only_active=only_active.strip())
        return execute_account_list(only_active=validated.only_active)

    run_sync_command(
        ctx=cli_ctx,
        command="account.list",
        func=_run,
    )


@app.command("activate")
def account_activate(
    ctx: typer.Context,
    account: str | None = command_option(("account", "activate"), "account", None),
):
    """设置当前账号环境。"""
    emit_command_help_if_empty(ctx, ("account", "activate"))

    cli_ctx: CliContext = ctx.obj
    account_uid = (account or "").strip()

    def _run() -> dict:
        if not account_uid:
            raise InvalidArgsError("`--account` 为必填参数")
        return execute_account_activate(account_uid=account_uid)

    run_sync_command(
        ctx=cli_ctx,
        command="account.activate",
        func=_run,
        account_uid=account_uid,
    )


@app.command("delete")
def account_delete(
    ctx: typer.Context,
    account: str | None = command_option(("account", "delete"), "account", None),
):
    """删除账号记录（不会清理业务输出文件）。"""
    emit_command_help_if_empty(ctx, ("account", "delete"))

    cli_ctx: CliContext = ctx.obj
    account_uid = (account or "").strip()

    def _run() -> dict:
        if not account_uid:
            raise InvalidArgsError("`--account` 为必填参数")
        return execute_account_delete(account_uid=account_uid)

    run_sync_command(
        ctx=cli_ctx,
        command="account.delete",
        func=_run,
        account_uid=account_uid,
    )
