"""Reusable completion providers for prompt commands."""

from __future__ import annotations

from typing import TYPE_CHECKING

from prompt_toolkit.completion import Completion

from fast_agent.agents.agent_types import AgentType
from fast_agent.llm.model_selection import ModelSelectionCatalog

if TYPE_CHECKING:
    from fast_agent.ui.prompt.completer import AgentCompleter


def _attached_mcp_servers_for_completion(completer: "AgentCompleter") -> list[str]:
    attached: list[str] = []
    if completer.agent_provider is not None and completer.current_agent:
        try:
            agent = completer.agent_provider._agent(completer.current_agent)
            aggregator = getattr(agent, "aggregator", None)
            list_attached = getattr(aggregator, "list_attached_servers", None)
            if callable(list_attached):
                attached = list_attached()
        except Exception:
            attached = []
    return attached


def _complete_attached_mcp_servers(completer: "AgentCompleter", partial: str) -> list[Completion]:
    attached = _attached_mcp_servers_for_completion(completer)
    return [
        Completion(
            server,
            start_position=-len(partial),
            display=server,
            display_meta="attached mcp server",
        )
        for server in attached
        if server.lower().startswith(partial.lower())
    ]


def _mcp_connect_completions(completer: "AgentCompleter", remainder: str) -> list[Completion]:
    connect_flags = {
        "--name": "set attached server name",
        "--auth": "set bearer token for URL servers",
        "--timeout": "set startup timeout in seconds",
        "--oauth": "enable oauth flow",
        "--no-oauth": "disable oauth flow",
        "--reconnect": "force reconnect and refresh tools",
        "--no-reconnect": "disable reconnect-on-disconnect",
    }

    context, target_count, partial = completer._mcp_connect_context(remainder)

    if context in {"target", "new_token"} and target_count == 0:
        results = [completer._mcp_connect_target_hint(partial)]
        results.extend(list(completer._complete_configured_mcp_servers(partial)))
        return results

    if context == "new_token" and target_count > 0:
        return [
            Completion(
                flag,
                start_position=0,
                display=flag,
                display_meta=description,
            )
            for flag, description in connect_flags.items()
        ]

    if context == "flag" and target_count > 0:
        return [
            Completion(
                flag,
                start_position=-len(partial),
                display=flag,
                display_meta=description,
            )
            for flag, description in connect_flags.items()
            if flag.startswith(partial.lower())
        ]

    return []


def _subcommand_completions(
    partial: str,
    subcommands: dict[str, str],
) -> list[Completion]:
    return [
        Completion(
            subcmd,
            start_position=-len(partial),
            display=subcmd,
            display_meta=description,
        )
        for subcmd, description in subcommands.items()
        if subcmd.startswith(partial.lower())
    ]


def _history_command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    if text_lower.startswith("/history load "):
        partial = text[len("/history load ") :]
        return list(completer._complete_history_files(partial))

    if text_lower.startswith("/history rewind "):
        partial = text[len("/history rewind ") :]
        return list(completer._complete_history_rewind(partial))

    if text_lower.startswith("/history detail "):
        partial = text[len("/history detail ") :]
        return list(completer._complete_history_rewind(partial))

    if text_lower.startswith("/history review "):
        partial = text[len("/history review ") :]
        return list(completer._complete_history_rewind(partial))

    if text_lower.startswith("/history clear "):
        partial = text[len("/history clear ") :]
        subcommands = {
            "all": "Clear the full history",
            "last": "Remove the most recent message",
        }
        return [
            Completion(
                subcmd,
                start_position=-len(partial),
                display=subcmd,
                display_meta=description,
            )
            for subcmd, description in subcommands.items()
            if subcmd.startswith(partial.lower())
        ]

    if text_lower.startswith("/history webclear "):
        if not completer._current_agent_has_web_tools_enabled():
            return []
        partial = text[len("/history webclear ") :].strip()
        partial_lower = partial.lower()
        return [
            Completion(
                name,
                start_position=-len(partial),
                display=name,
                display_meta="Strip web metadata channels for this agent",
            )
            for name in sorted(completer.agents)
            if (not partial or name.lower().startswith(partial_lower))
        ]
    if not text_lower.startswith("/history "):
        return None

    partial = text[len("/history ") :]
    subcommands = {
        "show": "Show per-turn timing summaries",
        "detail": "Show a previous user turn in full",
        "save": "Save history to a file",
        "load": "Load history from a file",
        "clear": "Clear history (all or last)",
        "rewind": "Rewind to a previous user turn",
        "fix": "Remove the last pending tool call",
    }
    if completer._current_agent_has_web_tools_enabled():
        subcommands["webclear"] = "Strip web tool/citation metadata channels"
    return _subcommand_completions(partial, subcommands)


def _prompt_command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    if not text_lower.startswith("/prompt load "):
        return None

    partial = text[len("/prompt load ") :]
    return list(completer._complete_history_files(partial))


def _session_delete_completions(
    completer: "AgentCompleter",
    partial: str,
) -> list[Completion]:
    results: list[Completion] = []
    if "all".startswith(partial.lower()):
        results.append(
            Completion(
                "all",
                start_position=-len(partial),
                display="all",
                display_meta="Delete all sessions",
            )
        )
    results.extend(list(completer._complete_session_ids(partial)))
    return results


def _session_pin_completions(
    completer: "AgentCompleter",
    text: str,
) -> list[Completion]:
    remainder = text[len("/session pin ") :]
    parts = remainder.split(maxsplit=1) if remainder else []
    if not parts:
        results = [
            Completion(
                option,
                start_position=0,
                display=option,
                display_meta="Toggle session pin",
            )
            for option in ("on", "off")
        ]
        results.extend(list(completer._complete_session_ids("")))
        return results

    first = parts[0].lower()
    if first in {"on", "off"}:
        if len(parts) == 1 and not remainder.endswith(" "):
            return [
                Completion(
                    option,
                    start_position=-len(first),
                    display=option,
                    display_meta="Toggle session pin",
                )
                for option in ("on", "off")
                if option.startswith(first)
            ]
        suffix = parts[1] if len(parts) > 1 else ""
        start_position = -len(suffix) if suffix else 0
        return list(completer._complete_session_ids(suffix, start_position=start_position))

    return list(completer._complete_session_ids(remainder))


def _session_command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    if text_lower.startswith("/resume "):
        partial = text[len("/resume ") :]
        return list(completer._complete_session_ids(partial))

    if text_lower.startswith("/session resume "):
        partial = text[len("/session resume ") :]
        return list(completer._complete_session_ids(partial))

    if text_lower.startswith("/session delete "):
        partial = text[len("/session delete ") :]
        return _session_delete_completions(completer, partial)

    if text_lower.startswith("/session clear "):
        partial = text[len("/session clear ") :]
        return _session_delete_completions(completer, partial)

    if text_lower.startswith("/session pin "):
        return _session_pin_completions(completer, text)

    if not text_lower.startswith("/session "):
        return None

    partial = text[len("/session ") :]
    subcommands = {
        "delete": "Delete a session (or all)",
        "pin": "Pin or unpin the current session",
        "clear": "Alias for delete",
        "list": "List recent sessions",
        "new": "Create a new session",
        "resume": "Resume a session",
        "title": "Set session title",
        "fork": "Fork current session",
    }
    return _subcommand_completions(partial, subcommands)

def _skills_command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    if not text_lower.startswith("/skills "):
        return None

    remainder = text[len("/skills ") :] or ""
    parts = remainder.split(maxsplit=1)
    subcommands = {
        "list": "List local skills",
        "available": "Browse marketplace skills",
        "search": "Search marketplace skills",
        "add": "Install a skill",
        "remove": "Remove a local skill",
        "update": "Check or apply skill updates",
        "registry": "Set skills registry",
        "help": "Show skills command usage",
    }
    results = list(completer._complete_subcommands(parts, remainder, subcommands))
    if not parts or (len(parts) == 1 and not remainder.endswith(" ")):
        return results

    subcmd = parts[0].lower()
    argument = parts[1] if len(parts) > 1 else ""
    if subcmd in {"remove", "rm", "delete", "uninstall"}:
        results.extend(list(completer._complete_local_skill_names(argument)))
        return results
    if subcmd in {"update", "refresh", "upgrade"}:
        if "all".startswith(argument.lower()):
            results.append(
                Completion(
                    "all",
                    start_position=-len(argument),
                    display="all",
                    display_meta="update all managed skills",
                )
            )
        if "--force".startswith(argument.lower()):
            results.append(
                Completion(
                    "--force",
                    start_position=-len(argument),
                    display="--force",
                    display_meta="overwrite local modifications",
                )
            )
        if "--yes".startswith(argument.lower()):
            results.append(
                Completion(
                    "--yes",
                    start_position=-len(argument),
                    display="--yes",
                    display_meta="confirm multi-skill apply",
                )
            )
        results.extend(
            list(
                completer._complete_local_skill_names(
                    argument,
                    managed_only=True,
                    include_indices=False,
                )
            )
        )
        return results
    if subcmd in {"registry", "marketplace", "source"}:
        results.extend(list(completer._complete_skill_registries(argument)))
        results.extend(list(completer._complete_registry_paths(argument)))
        return results
    return results

def _cards_publish_completions(
    completer: "AgentCompleter",
    argument: str,
    results: list[Completion],
) -> list[Completion]:
    current_token = ""
    if argument and not argument.endswith(" "):
        current_token = argument.split()[-1]
    elif argument.startswith("--"):
        current_token = argument

    if current_token.startswith("--") or not argument.strip():
        publish_flags = {
            "--no-push": "commit locally without push",
            "--message": "set publish commit message",
            "--temp-dir": "set parent directory for temp clone",
            "--keep-temp": "retain temp clone after publish",
        }
        results.extend(
            Completion(
                flag,
                start_position=-len(current_token),
                display=flag,
                display_meta=description,
            )
            for flag, description in publish_flags.items()
            if flag.startswith(current_token.lower())
        )

    results.extend(
        list(
            completer._complete_local_card_pack_names(
                argument,
                managed_only=True,
                include_indices=False,
            )
        )
    )
    return results


def _cards_command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    if not text_lower.startswith("/cards "):
        return None

    remainder = text[len("/cards ") :] or ""
    parts = remainder.split(maxsplit=1)
    subcommands = {
        "list": "List installed card packs",
        "add": "Install a card pack",
        "remove": "Remove an installed card pack",
        "readme": "Show an installed card pack README",
        "update": "Check or apply card pack updates",
        "publish": "Publish local card pack changes",
        "registry": "Set card pack registry",
    }
    results = list(completer._complete_subcommands(parts, remainder, subcommands))
    if not parts or (len(parts) == 1 and not remainder.endswith(" ")):
        return results

    subcmd = parts[0].lower()
    argument = parts[1] if len(parts) > 1 else ""
    if subcmd in {"remove", "rm", "delete", "uninstall"}:
        results.extend(list(completer._complete_local_card_pack_names(argument)))
        return results
    if subcmd in {"readme", "show", "cat"}:
        results.extend(list(completer._complete_local_card_pack_names(argument)))
        return results
    if subcmd in {"update", "refresh", "upgrade"}:
        if "all".startswith(argument.lower()):
            results.append(
                Completion(
                    "all",
                    start_position=-len(argument),
                    display="all",
                    display_meta="update all managed card packs",
                )
            )
        if "--force".startswith(argument.lower()):
            results.append(
                Completion(
                    "--force",
                    start_position=-len(argument),
                    display="--force",
                    display_meta="overwrite local modifications",
                )
            )
        if "--yes".startswith(argument.lower()):
            results.append(
                Completion(
                    "--yes",
                    start_position=-len(argument),
                    display="--yes",
                    display_meta="confirm multi-pack apply",
                )
            )
        results.extend(
            list(
                completer._complete_local_card_pack_names(
                    argument,
                    managed_only=True,
                    include_indices=False,
                )
            )
        )
        return results
    if subcmd in {"registry", "marketplace", "source"}:
        results.extend(list(completer._complete_card_registries(argument)))
        return results
    if subcmd == "publish":
        return _cards_publish_completions(completer, argument, results)
    return results

def _model_references_completions(
    completer: "AgentCompleter",
    argument: str,
    results: list[Completion],
) -> list[Completion]:
    alias_parts = argument.split(maxsplit=1)
    alias_subcommands = {
        "list": "List configured reference mappings",
        "set": "Set an alias: set [<token> [<model-spec>]]",
        "unset": "Unset an alias: unset [<token>]",
    }
    results.extend(completer._complete_subcommands(alias_parts, argument, alias_subcommands))

    if not alias_parts or (len(alias_parts) == 1 and not argument.endswith(" ")):
        return results

    alias_action = alias_parts[0].lower()
    if alias_action not in {"set", "unset"}:
        return results

    alias_argument = alias_parts[1] if len(alias_parts) > 1 else ""
    alias_tokens = alias_argument.split()
    current_token = ""
    if alias_argument and not alias_argument.endswith(" ") and alias_tokens:
        current_token = alias_tokens[-1]

    target_values = ("env", "project")
    if alias_tokens and alias_tokens[-1] == "--target" and alias_argument.endswith(" "):
        results.extend(
            Completion(
                target,
                start_position=0,
                display=target,
                display_meta="alias write target",
            )
            for target in target_values
        )
        return results

    if len(alias_tokens) >= 2 and alias_tokens[-2] == "--target" and current_token:
        results.extend(
            Completion(
                target,
                start_position=-len(current_token),
                display=target,
                display_meta="alias write target",
            )
            for target in target_values
            if target.startswith(current_token.lower())
        )
        return results

    if (not current_token and alias_argument.endswith(" ")) or current_token.startswith("--"):
        alias_flags = {
            "--target": "choose write target (env|project)",
            "--dry-run": "preview changes without writing",
        }
        results.extend(
            Completion(
                flag,
                start_position=-len(current_token),
                display=flag,
                display_meta=description,
            )
            for flag, description in alias_flags.items()
            if flag.startswith(current_token.lower())
        )
    return results


def _model_catalog_completions(argument: str, results: list[Completion]) -> list[Completion]:
    provider_names = sorted(
        {provider.config_name for provider in ModelSelectionCatalog.CATALOG_ENTRIES_BY_PROVIDER}
    )
    catalog_tokens = argument.split()
    current_token = ""
    if argument and not argument.endswith(" "):
        current_token = catalog_tokens[-1]

    if (not catalog_tokens and not argument) or (current_token and not current_token.startswith("--")):
        partial = current_token.lower()
        results.extend(
            Completion(
                provider_name,
                start_position=-len(current_token),
                display=provider_name,
                display_meta="provider",
            )
            for provider_name in provider_names
            if provider_name.startswith(partial)
        )

    if ((not current_token and argument.endswith(" ")) or current_token.startswith("--")) and (
        "--all".startswith(current_token.lower())
    ):
        results.append(
            Completion(
                "--all",
                start_position=-len(current_token),
                display="--all",
                display_meta="include all known models",
            )
        )
    return results


def _model_command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    if not text_lower.startswith("/model "):
        return None

    remainder = text[len("/model ") :] or ""
    parts = remainder.split(maxsplit=1)
    subcommands: dict[str, str] = {
        "reasoning": (
            "Set reasoning effort (off/low/medium/high/max/xhigh or budgets like "
            "0/1024/16000/32000)"
        )
    }
    if completer._resolve_verbosity_values():
        subcommands["verbosity"] = "Set text verbosity (low/medium/high)"
    if completer._supports_service_tier_setting():
        subcommands["fast"] = "Set service tier (on/off/status; flex when supported)"
    if completer._supports_web_search_setting():
        subcommands["web_search"] = "Set web search tool state (on/off/default)"
    if completer._supports_web_fetch_setting():
        subcommands["web_fetch"] = "Set web fetch tool state (on/off/default)"
    subcommands["switch"] = "Switch model (starts new session)"
    subcommands["doctor"] = "Inspect model onboarding readiness"
    subcommands["references"] = "List or update configured model reference mappings"
    subcommands["catalog"] = "Show curated models for a provider"
    results = list(completer._complete_subcommands(parts, remainder, subcommands))
    if not parts or (len(parts) == 1 and not remainder.endswith(" ")):
        return results

    subcmd = parts[0].lower()
    argument = parts[1] if len(parts) > 1 else ""
    if subcmd == "reasoning":
        results.extend(
            Completion(
                value,
                start_position=-len(argument),
                display=value,
                display_meta="reasoning",
            )
            for value in completer._resolve_reasoning_values()
            if value.startswith(argument.lower())
        )
        return results
    if subcmd == "verbosity":
        results.extend(
            Completion(
                value,
                start_position=-len(argument),
                display=value,
                display_meta="verbosity",
            )
            for value in completer._resolve_verbosity_values()
            if value.startswith(argument.lower())
        )
        return results
    if subcmd == "fast" and completer._supports_service_tier_setting():
        results.extend(
            Completion(
                value,
                start_position=-len(argument),
                display=value,
                display_meta=subcmd,
            )
            for value in completer._resolve_service_tier_values()
            if value.startswith(argument.lower())
        )
        return results
    if subcmd == "web_search" and completer._supports_web_search_setting():
        results.extend(
            Completion(
                value,
                start_position=-len(argument),
                display=value,
                display_meta=subcmd,
            )
            for value in ("on", "off", "default")
            if value.startswith(argument.lower())
        )
        return results
    if subcmd == "web_fetch" and completer._supports_web_fetch_setting():
        results.extend(
            Completion(
                value,
                start_position=-len(argument),
                display=value,
                display_meta=subcmd,
            )
            for value in ("on", "off", "default")
            if value.startswith(argument.lower())
        )
        return results
    if subcmd == "references":
        return _model_references_completions(completer, argument, results)
    if subcmd == "catalog":
        return _model_catalog_completions(argument, results)
    return results

def _mcp_session_use_completions(
    completer: "AgentCompleter",
    attached: list[str],
    tail: str,
    tail_tokens: list[str],
    partial: str,
) -> list[Completion]:
    if not tail_tokens:
        completions: list[Completion] = []
        session_choices = completer._run_async_completion(
            completer._list_attached_session_cookie_choices()
        )
        if isinstance(session_choices, list) and session_choices:
            for index, choice in enumerate(session_choices, start=1):
                server_name, identity, cookie_id, title, is_active = choice
                completion_text = f"{server_name} {cookie_id}"
                display = f"{index}-{cookie_id}"
                meta_parts = [identity or server_name]
                if title:
                    meta_parts.append(title)
                meta_text = ", ".join(meta_parts)
                state = "active" if is_active else "stored"
                completions.append(
                    Completion(
                        completion_text,
                        start_position=0,
                        display=display,
                        display_meta=f"{state} session | {meta_text}",
                    )
                )
        return completions

    if len(tail_tokens) <= 1 and not tail.endswith(" "):
        server_completions = [
            Completion(
                server,
                start_position=-len(partial),
                display=server,
                display_meta="attached mcp server",
            )
            for server in attached
            if server.lower().startswith(partial.lower())
        ]

        session_choices = completer._run_async_completion(
            completer._list_attached_session_cookie_choices()
        )
        if not isinstance(session_choices, list) or not session_choices:
            return server_completions

        partial_lower = partial.lower()
        session_completions: list[Completion] = []
        for index, choice in enumerate(session_choices, start=1):
            server_name, identity, cookie_id, title, is_active = choice
            display = f"{index}-{cookie_id}"
            if partial and not (
                display.lower().startswith(partial_lower)
                or cookie_id.lower().startswith(partial_lower)
                or server_name.lower().startswith(partial_lower)
            ):
                continue

            completion_text = f"{server_name} {cookie_id}"
            meta_parts = [identity or server_name]
            if title:
                meta_parts.append(title)
            meta_text = ", ".join(meta_parts)
            state = "active" if is_active else "stored"
            session_completions.append(
                Completion(
                    completion_text,
                    start_position=-len(partial),
                    display=display,
                    display_meta=f"{state} session | {meta_text}",
                )
            )

        return session_completions + server_completions

    if not tail_tokens:
        return []

    server_identifier = tail_tokens[0]
    if not tail.endswith(" ") and len(tail_tokens) < 2:
        return []

    cookie_partial = "" if tail.endswith(" ") else tail_tokens[-1]
    cookie_choices = completer._run_async_completion(
        completer._list_server_session_cookie_choices(server_identifier)
    )
    if not isinstance(cookie_choices, list):
        return []

    return [
        Completion(
            cookie_id,
            start_position=-len(cookie_partial),
            display=cookie_id,
            display_meta=(
                f"{'active' if is_active else 'stored'} session"
                + (f" · {title}" if isinstance(title, str) and title else "")
            ),
        )
        for cookie_id, title, is_active in cookie_choices
        if cookie_id.lower().startswith(cookie_partial.lower())
    ]


def _mcp_session_completions(
    completer: "AgentCompleter",
    text: str,
) -> list[Completion]:
    remainder = text[len("/mcp session ") :]
    parts = remainder.split(maxsplit=1) if remainder else []
    subcommands = {
        "list": "List sessions (all connected servers by default) and highlight active",
        "jar": "Show all stored sessions grouped by target/mcp name",
        "new": "Create a new MCP session",
        "use": "Switch active session to an existing session id",
        "clear": "Clear one session entry or the full local store",
    }
    results = list(completer._complete_subcommands(parts, remainder, subcommands))
    if not parts or (len(parts) == 1 and not remainder.endswith(" ")):
        return results

    attached = _attached_mcp_servers_for_completion(completer)
    subcmd = parts[0].lower()
    tail = parts[1] if len(parts) > 1 else ""
    tail_tokens = tail.split()
    partial = tail_tokens[-1] if tail and not tail.endswith(" ") else ""

    if subcmd in {"list", "jar", "new"}:
        if subcmd == "new" and "--title" in tail_tokens:
            return []
        if "--title" in partial.lower():
            return []
        if subcmd == "jar" and not tail_tokens and not partial and len(attached) <= 1:
            return []

        completions: list[Completion] = []
        if subcmd == "new" and (not tail_tokens or tail.endswith(" ")):
            completions.append(
                Completion(
                    "--title",
                    start_position=0,
                    display="--title",
                    display_meta="session title hint",
                )
            )

        completions.extend(
            Completion(
                server,
                start_position=-len(partial),
                display=server,
                display_meta="attached mcp server",
            )
            for server in attached
            if server.lower().startswith(partial.lower())
        )
        return completions

    if subcmd in {"use", "resume"}:
        return _mcp_session_use_completions(completer, attached, tail, tail_tokens, partial)

    if subcmd == "clear":
        options = ["--all", *attached]
        return [
            Completion(
                option,
                start_position=-len(partial),
                display=option,
                display_meta=(
                    "clear full session store" if option == "--all" else "attached mcp server"
                ),
            )
            for option in options
            if option.lower().startswith(partial.lower())
        ]

    return results


def _mcp_command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    if text_lower.startswith("/mcp disconnect "):
        partial = text[len("/mcp disconnect ") :]
        return _complete_attached_mcp_servers(completer, partial)

    if text_lower.startswith("/mcp reconnect "):
        partial = text[len("/mcp reconnect ") :]
        return _complete_attached_mcp_servers(completer, partial)

    if text_lower.startswith("/mcp connect "):
        remainder = text[len("/mcp connect ") :]
        return _mcp_connect_completions(completer, remainder)

    if text_lower.startswith("/connect "):
        remainder = text[len("/connect ") :]
        return _mcp_connect_completions(completer, remainder)

    if text_lower.startswith("/mcp session "):
        return _mcp_session_completions(completer, text)

    if not text_lower.startswith("/mcp "):
        return None

    remainder = text[len("/mcp ") :]
    parts = remainder.split(maxsplit=1) if remainder else []
    subcommands = {
        "list": "List currently attached MCP servers",
        "connect": "Connect a new MCP server",
        "disconnect": "Disconnect an attached MCP server",
        "reconnect": "Reconnect an attached MCP server",
        "session": "Inspect and control MCP data-layer sessions",
    }
    return list(completer._complete_subcommands(parts, remainder, subcommands))


def _card_command_completions(
    completer: "AgentCompleter",
    text_lower: str,
    text: str,
) -> list[Completion] | None:
    if not text_lower.startswith("/card "):
        return None

    partial = text[len("/card ") :]
    return list(completer._complete_agent_card_files(partial))


def _agent_command_completions(
    completer: "AgentCompleter",
    text_lower: str,
    text: str,
) -> list[Completion] | None:
    if not text_lower.startswith("/agent "):
        return None

    partial = text[len("/agent ") :].lstrip()
    if partial.startswith("@"):
        partial = partial[1:]
    return [
        Completion(
            agent,
            start_position=-len(partial),
            display=agent,
            display_meta=completer.agent_types.get(agent, AgentType.BASIC).value,
        )
        for agent in completer.agents
        if agent != completer.current_agent and agent.lower().startswith(partial.lower())
    ]


def command_completions(
    completer: "AgentCompleter",
    text: str,
    text_lower: str,
) -> list[Completion] | None:
    """Return command-specific completions or ``None`` when unhandled."""
    history_result = _history_command_completions(completer, text, text_lower)
    if history_result is not None:
        return history_result

    prompt_result = _prompt_command_completions(completer, text, text_lower)
    if prompt_result is not None:
        return prompt_result

    session_result = _session_command_completions(completer, text, text_lower)
    if session_result is not None:
        return session_result

    skills_result = _skills_command_completions(completer, text, text_lower)
    if skills_result is not None:
        return skills_result

    cards_result = _cards_command_completions(completer, text, text_lower)
    if cards_result is not None:
        return cards_result

    model_result = _model_command_completions(completer, text, text_lower)
    if model_result is not None:
        return model_result

    mcp_result = _mcp_command_completions(completer, text, text_lower)
    if mcp_result is not None:
        return mcp_result

    card_result = _card_command_completions(completer, text_lower, text)
    if card_result is not None:
        return card_result

    agent_result = _agent_command_completions(completer, text_lower, text)
    if agent_result is not None:
        return agent_result

    return None
