from __future__ import annotations

import asyncio
from pathlib import Path
from typing import Optional

import typer

from aicd.cli_encoding import configure_cli_utf8
from aicd.env_probe import refresh_runtime_env_file
from aicd.agent.loop import merge_env_api_key
from aicd.home import init_home
from aicd.runtime import build_runtime, persist_config
from aicd.setup_wizard import (
    run_first_time_setup,
    runtime_llm_ready,
    should_prompt_setup,
    skip_first_time_setup_interactive,
)
from aicd.ui.cli_headless import run_noui_ai_turn
from aicd.ui.tui import AicdTui
from aicd.version import VERSION

app = typer.Typer(help="Aicd — 命令行 AI Agent（开发/文档）")


@app.command()
def version() -> None:
    """打印当前版本号。"""
    typer.echo(VERSION)


@app.command()
def init(
    home: Optional[Path] = typer.Option(
        None,
        "--home",
        "-h",
        help="HOME 根目录；不设则用环境变量 AICD_HOME，否则在当前用户主目录下创建并使用 .aicd",
    ),
    wizard: bool = typer.Option(
        True,
        "--wizard/--no-wizard",
        help="是否在终端交互配置 LLM（首次/无完成标记时）；非交互环境自动跳过",
    ),
) -> None:
    """初始化 HOME 目录、config.yaml 与 SQLite。"""
    root, layout, cfg = init_home(home)
    merge_env_api_key(cfg)
    cfg_path = layout["config"]
    if (
        wizard
        and should_prompt_setup()
        and not skip_first_time_setup_interactive(layout, cfg_path, cfg)
    ):
        cfg = run_first_time_setup(layout, cfg, home_label=str(root.resolve()))
        merge_env_api_key(cfg)
    else:
        persist_config(layout, cfg)
    refresh_runtime_env_file(layout)
    typer.echo(f"初始化完成: {root}")


@app.command()
def tui(
    home: Optional[Path] = typer.Option(
        None,
        "--home",
        help="HOME 根目录；不设则用 AICD_HOME，否则在用户主目录下自动创建 .aicd",
    ),
    work: Optional[Path] = typer.Option(
        None,
        "--work",
        "-w",
        help="启动后将 AI 工作区设为该目录（等同 TUI /work）；须为已存在的目录",
    ),
    out: Optional[Path] = typer.Option(
        None,
        "--out",
        "-o",
        help="AI 输出根目录（等同 /doc，内含 tmp/）；相对路径相对当前 AI 工作区",
    ),
    ai: Optional[str] = typer.Option(
        None,
        "--ai",
        help="非交互：启动后自动向主 AI 发送该任务（纯 CLI 批处理时常用）；不设则为交互模式",
    ),
    noui: bool = typer.Option(
        False,
        "--noui",
        help="不启动 TUI：仅 stdout 打印工具行与最终助手回复，任务结束后退出（须配合 --ai）",
    ),
    skip_setup: bool = typer.Option(
        False,
        "--skip-setup",
        help="跳过首次 HOME 的 LLM 交互配置（也可用环境变量 AICD_SKIP_SETUP=1）",
    ),
) -> None:
    """启动 Textual 界面（左聊天、右任务），或使用 --ai / --noui 走纯命令行。

    首次使用且无 API 密钥时，启动前会在**当前终端**走交互式 LLM 配置（与 ``aicd init`` 相同逻辑）；
    若环境无法交互，请运行 ``aicd init`` 或配置密钥后再启动。"""

    if noui and not (ai and str(ai).strip()):
        typer.echo("错误: --noui 必须与 --ai 同时使用（无界面模式下必须指定任务内容）", err=True)
        raise typer.Exit(code=2)

    async def _run() -> None:
        ctx = await build_runtime(
            home=home,
            skip_first_setup=skip_setup,
            setup_tty_relaxed=not skip_setup,
        )
        if (
            not skip_setup
            and not noui
            and not runtime_llm_ready(ctx.config)
            and not should_prompt_setup(relaxed=True)
        ):
            typer.secho(
                "未检测到可交互终端（stdin 非 TTY），已跳过首次 LLM 向导。"
                "请在本机终端执行:  aicd init\n"
                "或设置环境变量 OPENAI_API_KEY / DASHSCOPE_API_KEY，或在 config.yaml 填写 llm.apiKey。",
                fg=typer.colors.YELLOW,
                err=True,
            )
        if work is not None:
            ok, msg = ctx.set_ai_workspace(str(work))
            if not ok:
                typer.echo(f"无法设置 AI 工作目录: {msg}", err=True)
                raise typer.Exit(code=1)
        if out is not None:
            ok, msg = ctx.set_ai_output_dir(str(out))
            if not ok:
                typer.echo(f"无法设置 AI 输出目录: {msg}", err=True)
                raise typer.Exit(code=1)
        if noui:
            code = await run_noui_ai_turn(ctx, str(ai).strip())
            if code != 0:
                raise typer.Exit(code=code)
            return
        bootstrap = str(ai).strip() if ai else None
        tui_app = AicdTui(ctx, bootstrap_user_message=bootstrap or None)
        await tui_app.run_async()

    asyncio.run(_run())


@app.command()
def serve(
    home: Optional[Path] = typer.Option(
        None,
        "--home",
        help="HOME 根目录（与 TUI 一致）；不设则用 AICD_HOME",
    ),
    host: str = typer.Option(
        "127.0.0.1",
        "--host",
        help="监听地址（生产环境请配 X-API-Key 或环境变量 AICD_API_KEY）",
    ),
    port: int = typer.Option(8765, "--port", help="监听端口"),
    api_key: Optional[str] = typer.Option(
        None,
        "--api-key",
        help="可选；要求请求头 X-API-Key 或 Authorization: Bearer …；也可设环境变量 AICD_API_KEY",
        envvar="AICD_API_KEY",
    ),
) -> None:
    """启动只读聊天历史 HTTP API（需 pip install 'aicd[api]'）。"""

    try:
        from aicd.api_serve import run_serve
    except ImportError:
        typer.echo(
            "缺少依赖，请执行: pip install 'aicd[api]'",
            err=True,
        )
        raise typer.Exit(code=1) from None

    async def _go() -> None:
        await run_serve(home=home, host=host, port=port, api_key=api_key)

    asyncio.run(_go())


def main() -> None:
    configure_cli_utf8()
    app()


if __name__ == "__main__":
    main()
