#!/usr/bin/python3
"""Cross-check shell_completion.COMMAND_FLAGS against the real argparse parser.

For every canonical command in COMMAND_FLAGS, every flag declared in main.py
must appear in the corresponding COMMAND_FLAGS entry, and vice-versa.

This test catches two classes of drift:
  - A flag added to main.py but forgotten in shell_completion.py
  - A flag present in shell_completion.py that no longer exists in main.py
"""

import sys
from pathlib import Path

import pytest

# shell_completion.py lives at the project root (not inside the slpkg package).
# The sys.path modification must precede the import, so the noqa and pylint
# disable comments are intentional and necessary.
_ROOT = Path(__file__).parent.parent
if str(_ROOT) not in sys.path:
    sys.path.insert(0, str(_ROOT))

import shell_completion  # noqa: E402  # pylint: disable=wrong-import-position
from slpkg.main import build_parser  # noqa: E402  # pylint: disable=wrong-import-position

# ---------------------------------------------------------------------------
# Build the reference data once for the whole module
# ---------------------------------------------------------------------------

_PARSER, _SUBPARSERS_MAP = build_parser()

# Flags to ignore during comparison:
#   -h / --help  — argparse adds these automatically; not in COMMAND_FLAGS by design
_IGNORED_FLAGS: frozenset[str] = frozenset({"-h", "--help"})

# Canonical command names that COMMAND_FLAGS knows about (skip aliases)
_CANONICAL_COMMANDS: list[str] = list(shell_completion.COMMAND_FLAGS.keys())


def _argparse_flags(command: str) -> frozenset[str]:
    """Return all option strings for *command* from the real argparse parser."""
    sp = _SUBPARSERS_MAP.get(command)
    assert sp is not None, f"Command '{command}' not found in _SUBPARSERS_MAP"
    flags: set[str] = set()
    for action in sp._actions:  # pylint: disable=protected-access
        flags.update(action.option_strings)
    return frozenset(flags - _IGNORED_FLAGS)


def _completion_flags(command: str) -> frozenset[str]:
    """Return all flags listed in shell_completion.COMMAND_FLAGS for *command*."""
    return frozenset(shell_completion.COMMAND_FLAGS.get(command, []))


# ---------------------------------------------------------------------------
# Parametrised tests
# ---------------------------------------------------------------------------


@pytest.mark.parametrize("command", _CANONICAL_COMMANDS)
def test_no_missing_flags_in_completion(command: str) -> None:
    """Every flag declared in main.py must appear in shell_completion.COMMAND_FLAGS."""
    real = _argparse_flags(command)
    defined = _completion_flags(command)
    missing = real - defined
    assert not missing, (
        f"Command '{command}': flags present in main.py but missing from "
        f"shell_completion.COMMAND_FLAGS: {sorted(missing)}"
    )


@pytest.mark.parametrize("command", _CANONICAL_COMMANDS)
def test_no_extra_flags_in_completion(command: str) -> None:
    """Every flag in shell_completion.COMMAND_FLAGS must exist in main.py."""
    real = _argparse_flags(command)
    defined = _completion_flags(command)
    extra = defined - real
    assert not extra, (
        f"Command '{command}': flags in shell_completion.COMMAND_FLAGS that no "
        f"longer exist in main.py: {sorted(extra)}"
    )


def test_no_unknown_commands_in_completion() -> None:
    """Every canonical command in COMMAND_FLAGS must be a real slpkg command."""
    unknown = set(_CANONICAL_COMMANDS) - set(_SUBPARSERS_MAP.keys())
    assert not unknown, (
        f"Commands in shell_completion.COMMAND_FLAGS not found in main.py: {sorted(unknown)}"
    )


def test_all_main_commands_covered_in_completion() -> None:
    """Every canonical command in main.py must have an entry in COMMAND_FLAGS."""
    not_covered = set(_SUBPARSERS_MAP.keys()) - set(_CANONICAL_COMMANDS)
    assert not not_covered, (
        f"Commands in main.py missing from shell_completion.COMMAND_FLAGS: {sorted(not_covered)}"
    )
