"""Shared helpers for CLI command modules.

Spec source: plan task ``cli-refactor.extract-shared-helpers`` requires
centralizing repeated ``find_agent_by_prefix`` + not-found error handling.
"""

from __future__ import annotations

import sys

from rich.console import Console

from anima.core.schemas import AgentStateData
from anima.shell.state import find_agent_by_prefix


# @invar:allow shell_result: CLI helper exits on agent-not-found contract path
def resolve_agent(
    agent_id: str,
    *,
    json_output: bool,
    console: Console,
    exit_agent_not_found: int,
) -> AgentStateData:
    """Resolve agent ID/prefix or emit spec error envelope and exit.

    Args:
        agent_id: Full agent ID or supported prefix.
        json_output: Whether to emit Section G JSON error envelope.
        console: CLI console for human/JSON output.
        exit_agent_not_found: POSIX exit code used for not-found errors.

    Returns:
        Resolved agent state.
    """
    from returns.result import Failure

    result = find_agent_by_prefix(agent_id)
    if isinstance(result, Failure):
        if json_output:
            console.print_json(
                data={
                    "error": {
                        "code": "AGENT_NOT_FOUND",
                        "numeric_code": 300,
                        "message": f"Agent not found: {agent_id}",
                        "details": {"agent_id": agent_id},
                    }
                }
            )
        else:
            console.print(f"[red]Error: Agent not found: {agent_id}[/red]")
        sys.exit(exit_agent_not_found)

    return result.unwrap()


# @invar:allow shell_result: formatting helper used only for CLI presentation
# @shell_orchestration: Spec source deduplicate-shortest-unique-prefix keeps CLI-only display helper in shell shared module
# @shell_complexity: Spec source deduplicate-shortest-unique-prefix;
# bounded collision loop preserves existing CLI readability behavior
def shortest_unique_agent_id_prefixes(
    agent_ids: list[str],
    *,
    minimum_prefix: int = 12,
) -> dict[str, str]:
    """Return shortest unique display prefixes with a minimum length.

    Spec source: vectl step ``deduplicate-shortest-unique-prefix`` requires
    moving this helper to shared CLI helpers and reusing it from command modules.
    """
    if not agent_ids:
        return {}

    prefix_lengths: dict[str, int] = {
        agent_id: min(minimum_prefix, len(agent_id)) for agent_id in agent_ids
    }

    while True:
        collisions: dict[str, list[str]] = {}
        for agent_id in agent_ids:
            prefix = agent_id[: prefix_lengths[agent_id]]
            collisions.setdefault(prefix, []).append(agent_id)

        changed = False
        for colliding_ids in collisions.values():
            if len(colliding_ids) <= 1:
                continue
            for agent_id in colliding_ids:
                current_length = prefix_lengths[agent_id]
                if current_length < len(agent_id):
                    prefix_lengths[agent_id] = current_length + 1
                    changed = True

        if not changed:
            break

    return {agent_id: agent_id[: prefix_lengths[agent_id]] for agent_id in agent_ids}
