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.contracts.command_inputs import AccountListInput
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_deactivate,
    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.cli.utils import all_option_params_are_default
from flow_xhs.errors import InvalidArgsError

app = typer.Typer(help="账号管理（登录/状态/激活/停用/删除）", no_args_is_help=True)


@app.command("login")
def account_login(
    ctx: typer.Context,
    account: str | None = typer.Option(
        None,
        "--account",
        help="账号唯一标识（user_no）",
    ),
    mode: str = typer.Option(
        "local",
        "--mode",
        help="登录模式：local（本机扫码）| remote（远程截图扫码）",
    ),
    login_timeout_seconds: int = typer.Option(
        240,
        "--login-timeout-seconds",
        min=30,
        help="扫码登录超时（秒）",
    ),
    screenshot_path: str = typer.Option(
        "",
        "--screenshot-path",
        help="remote 模式屏幕截图路径，可传目录或文件路径，默认为 $FLOW_XHS_HOME/outputs 或 $HOME/.flow_xhs/outputs 下的 login_viewport.png",
    ),
):
    """启动登录流程并写入持久登录态。"""
    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():
        return await execute_auth_login(
            account_uid=(account or "").strip(),
            mode=mode,
            login_timeout_seconds=login_timeout_seconds,
            screenshot_path=screenshot_path,
            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,
    account: str | None = typer.Option(None, "--account", help="账号唯一标识；为空时检查所有有效账号"),
):
    """实时检查并刷新账号登录状态。"""
    cli_ctx: CliContext = ctx.obj

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

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


@app.command("list")
def account_list(
    ctx: typer.Context,
    only_active: str = typer.Option(
        "true",
        "--only-active",
        help="仅显示当前可用账号，需显式传入 true|false（默认 true）",
    ),
):
    """列出账号池。"""
    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 = typer.Option(None, "--account", help="账号唯一标识（user_no）"),
):
    """将账号标记为可用。"""
    if all_option_params_are_default(ctx=ctx):
        typer.echo(ctx.get_help())
        raise typer.Exit(code=0)

    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("deactivate")
def account_deactivate(
    ctx: typer.Context,
    account: str | None = typer.Option(None, "--account", help="账号唯一标识（user_no）"),
):
    """将账号标记为不可用。"""
    if all_option_params_are_default(ctx=ctx):
        typer.echo(ctx.get_help())
        raise typer.Exit(code=0)

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

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

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


@app.command("delete")
def account_delete(
    ctx: typer.Context,
    account: str | None = typer.Option(None, "--account", help="账号唯一标识（user_no）"),
):
    """删除账号记录（不会清理业务输出文件）。"""
    if all_option_params_are_default(ctx=ctx):
        typer.echo(ctx.get_help())
        raise typer.Exit(code=0)

    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,
    )
