from __future__ import annotations

import json
from pathlib import Path

import pytest

import cli.commands.items as item_commands
from cli.exceptions import CLIError

_CONTRACT_VECTORS_PATH = (
    Path(__file__).resolve().parents[2] / "tests" / "vectors" / "item-key-contract-vectors.json"
)


def _load_contract_vectors() -> dict:
    return json.loads(_CONTRACT_VECTORS_PATH.read_text(encoding="utf-8"))


_CONTRACT_VECTORS = _load_contract_vectors()


def _is_valid_cli_manual_key(raw: str) -> bool:
    try:
        item_commands._validate_item_key(raw)
        return True
    except CLIError:
        return False


@pytest.mark.parametrize(
    "case",
    _CONTRACT_VECTORS["manual_key_cases"],
    ids=lambda item: item["id"],
)
def test_cli_manual_key_vectors(case: dict) -> None:
    raw = case["input"]
    expected = case["components"]["cli_manual"]

    actual_normalized = item_commands._normalize_item_key(raw)
    actual_is_valid = _is_valid_cli_manual_key(raw)

    assert actual_normalized == expected["normalized"]
    assert actual_is_valid == expected["is_valid"]


@pytest.mark.parametrize(
    "case",
    _CONTRACT_VECTORS["auto_title_cases"],
    ids=lambda item: item["id"],
)
def test_cli_auto_title_vectors(case: dict) -> None:
    expected = case["components"]["cli_auto_title"]

    actual_value = item_commands._derive_key_from_title(case["input"])
    # Known phase-2 gap: the CLI helper returns only the key value and does not report truncation
    # metadata or enforce max-length truncation during derivation.
    actual_was_truncated = False

    assert actual_value == expected["value"]
    assert actual_was_truncated == expected["was_truncated"]


def test_cli_known_divergences_match_contract_vectors() -> None:
    title_cases = {case["id"]: case for case in _CONTRACT_VECTORS["auto_title_cases"]}

    for divergence in _CONTRACT_VECTORS["known_divergences"]:
        if divergence["component"] != "cli_auto_title":
            continue

        case = title_cases[divergence["case_id"]]
        canonical = case["canonical"]["value"]
        actual = item_commands._derive_key_from_title(case["input"])
        component_meta = case["components"]["cli_auto_title"]

        assert (actual == canonical) is component_meta["conforms_to_canonical"]
