from __future__ import annotations

import argparse

from ..context import CliContext
from ..interaction import cancelled_result, resolve_interactive_selection
from ..terminal_ui import SelectionOption
from .common import raise_config_error


def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
    parser = subparsers.add_parser("app", help="应用发现")
    app_subparsers = parser.add_subparsers(dest="app_command", required=True)

    list_parser = app_subparsers.add_parser("list", help="列出可见应用")
    list_parser.add_argument("--query", default="", help="按关键词在可见应用列表中本地过滤")
    list_parser.add_argument("--keyword", default="", help="兼容别名；建议使用 --query")
    list_parser.set_defaults(handler=_handle_list, format_hint="app_list")

    get = app_subparsers.add_parser("get", help="读取应用可访问视图与导入能力")
    get.add_argument("--app-key", help="不传时在交互终端中选择应用")
    get.set_defaults(handler=_handle_get, format_hint="app_get")


def _handle_list(args: argparse.Namespace, context: CliContext) -> dict:
    return context.app.app_list(profile=args.profile, query=args.query, keyword=args.keyword)


def _handle_get(args: argparse.Namespace, context: CliContext) -> dict:
    if not (args.app_key or "").strip():
        selection = _choose_app_interactively(args, context)
        if selection.status == "unavailable":
            raise_config_error(
                "app get requires --app-key, or an interactive terminal to choose an app",
                fix_hint="Run `app list` to inspect visible apps, or retry with `--app-key APP_KEY`.",
            )
        if selection.status == "empty":
            raise_config_error(
                selection.message or "app get could not open a selector because no visible apps were returned.",
                fix_hint="Run `app list` to confirm visible apps, or retry with `--app-key APP_KEY`.",
            )
        if selection.status == "cancelled":
            return cancelled_result(selection.message or "已取消")
        args.app_key = str(selection.value or "")
    return context.app.app_get(profile=args.profile, app_key=args.app_key)


def _choose_app_interactively(args: argparse.Namespace, context: CliContext):
    def load_options() -> list[SelectionOption[str]]:
        result = context.app.app_list(profile=args.profile)
        items = result.get("items") if isinstance(result, dict) and isinstance(result.get("items"), list) else []
        options: list[SelectionOption[str]] = []
        for item in items:
            if not isinstance(item, dict):
                continue
            app_key = str(item.get("app_key") or "").strip()
            if not app_key:
                continue
            app_name = str(item.get("app_name") or app_key).strip() or app_key
            package_name = str(item.get("package_name") or "").strip()
            hint = f"app_key={app_key}"
            if package_name:
                hint += f" · package={package_name}"
            options.append(SelectionOption(value=app_key, label=app_name, hint=hint))
        return options

    return resolve_interactive_selection(
        args,
        title="选择应用",
        unavailable_message="app get requires --app-key, or an interactive terminal to choose an app",
        empty_message="app get could not open a selector because no visible apps were returned.",
        load_options=load_options,
    )
