"""Robot Framework helper for UKO Layer 3 technology vocabulary tests.

Subcommands:
    vocab-py         -- verify uko-py: vocabulary, print ``vocab-py-ok``
    vocab-ts         -- verify uko-ts: vocabulary, print ``vocab-ts-ok``
    vocab-rs         -- verify uko-rs: vocabulary, print ``vocab-rs-ok``
    vocab-java       -- verify uko-java: vocabulary, print ``vocab-java-ok``
    detail-map-py    -- verify Python 15-level map, print ``detail-map-py-ok``
    detail-map-ts    -- verify TypeScript 12-level map, print ``detail-map-ts-ok``
    detail-map-rs    -- verify Rust 12-level map, print ``detail-map-rs-ok``
    detail-map-java  -- verify Java 12-level map, print ``detail-map-java-ok``
    provenance       -- verify ProvenanceInfo contract, print ``provenance-ok``
"""

from __future__ import annotations

import sys
import traceback
from collections.abc import Callable
from pathlib import Path

_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

from cleveragents.acms.uko.layer3_java import (  # noqa: E402
    JAVA_DETAIL_LEVELS,
    JAVA_VOCABULARY,
)
from cleveragents.acms.uko.layer3_py import (  # noqa: E402
    PYTHON_DETAIL_LEVELS,
    PYTHON_VOCABULARY,
)
from cleveragents.acms.uko.layer3_rs import (  # noqa: E402
    RUST_DETAIL_LEVELS,
    RUST_VOCABULARY,
)
from cleveragents.acms.uko.layer3_ts import (  # noqa: E402
    TYPESCRIPT_DETAIL_LEVELS,
    TYPESCRIPT_VOCABULARY,
)
from cleveragents.acms.uko.vocabulary import (  # noqa: E402
    ProvenanceInfo,
    resolve_detail_level,
)


def _cmd_vocab_py() -> int:
    """Verify uko-py: vocabulary has expected classes and properties."""
    try:
        v = PYTHON_VOCABULARY
        if v.prefix != "uko-py:":
            print(f"vocab-py-fail: prefix {v.prefix!r}")
            return 1
        if len(v.classes) != 5:
            print(f"vocab-py-fail: expected 5 classes, got {len(v.classes)}")
            return 1
        if len(v.properties) != 5:
            print(f"vocab-py-fail: expected 5 properties, got {len(v.properties)}")
            return 1
        expected = {
            "PythonModule",
            "PythonClass",
            "PythonFunction",
            "PythonDecorator",
            "PythonTypeStub",
        }
        actual = {c.label for c in v.classes}
        if actual != expected:
            print(f"vocab-py-fail: classes {actual}")
            return 1
        print(f"vocab-py-ok: {len(v.classes)} classes, {len(v.properties)} properties")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"vocab-py-fail: {exc}")
        return 1


def _cmd_vocab_ts() -> int:
    """Verify uko-ts: vocabulary has expected classes."""
    try:
        v = TYPESCRIPT_VOCABULARY
        if v.prefix != "uko-ts:":
            print(f"vocab-ts-fail: prefix {v.prefix!r}")
            return 1
        if len(v.classes) != 4:
            print(f"vocab-ts-fail: expected 4 classes, got {len(v.classes)}")
            return 1
        if len(v.properties) != 6:
            print(f"vocab-ts-fail: expected 6 properties, got {len(v.properties)}")
            return 1
        print(f"vocab-ts-ok: {len(v.classes)} classes, {len(v.properties)} properties")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"vocab-ts-fail: {exc}")
        return 1


def _cmd_vocab_rs() -> int:
    """Verify uko-rs: vocabulary has expected classes."""
    try:
        v = RUST_VOCABULARY
        if v.prefix != "uko-rs:":
            print(f"vocab-rs-fail: prefix {v.prefix!r}")
            return 1
        if len(v.classes) != 5:
            print(f"vocab-rs-fail: expected 5 classes, got {len(v.classes)}")
            return 1
        if len(v.properties) != 8:
            print(f"vocab-rs-fail: expected 8 properties, got {len(v.properties)}")
            return 1
        print(f"vocab-rs-ok: {len(v.classes)} classes, {len(v.properties)} properties")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"vocab-rs-fail: {exc}")
        return 1


def _cmd_vocab_java() -> int:
    """Verify uko-java: vocabulary has expected classes."""
    try:
        v = JAVA_VOCABULARY
        if v.prefix != "uko-java:":
            print(f"vocab-java-fail: prefix {v.prefix!r}")
            return 1
        if len(v.classes) != 5:
            print(f"vocab-java-fail: expected 5 classes, got {len(v.classes)}")
            return 1
        if len(v.properties) != 8:
            print(f"vocab-java-fail: expected 8 properties, got {len(v.properties)}")
            return 1
        print(
            f"vocab-java-ok: {len(v.classes)} classes, {len(v.properties)} properties"
        )
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"vocab-java-fail: {exc}")
        return 1


def _cmd_detail_map_py() -> int:
    """Verify Python 15-level map and key depth resolutions."""
    try:
        levels = PYTHON_DETAIL_LEVELS
        if len(levels) != 15:
            print(f"detail-map-py-fail: expected 15 levels, got {len(levels)}")
            return 1
        checks = {
            "MODULE_LISTING": 0,
            "DECORATED_SIGNATURES": 7,
            "TYPE_STUBS": 11,
            "WITH_TESTS": 14,
            "FULL_SOURCE": 13,
        }
        for name, expected_depth in checks.items():
            actual = resolve_detail_level(name, levels)
            if actual != expected_depth:
                print(
                    f"detail-map-py-fail: {name} expected {expected_depth}, "
                    f"got {actual}"
                )
                return 1
        print(f"detail-map-py-ok: {len(levels)} levels, all depths correct")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"detail-map-py-fail: {exc}")
        return 1


def _cmd_detail_map_ts() -> int:
    """Verify TypeScript 12-level map and key depth resolutions."""
    try:
        levels = TYPESCRIPT_DETAIL_LEVELS
        if len(levels) != 12:
            print(f"detail-map-ts-fail: expected 12 levels, got {len(levels)}")
            return 1
        checks = {
            "MODULE_LISTING": 0,
            "SIGNATURES": 5,
            "FULL_SOURCE": 11,
        }
        for name, expected_depth in checks.items():
            actual = resolve_detail_level(name, levels)
            if actual != expected_depth:
                print(
                    f"detail-map-ts-fail: {name} expected {expected_depth}, "
                    f"got {actual}"
                )
                return 1
        print(f"detail-map-ts-ok: {len(levels)} levels, all depths correct")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"detail-map-ts-fail: {exc}")
        return 1


def _cmd_detail_map_rs() -> int:
    """Verify Rust 12-level map and key depth resolutions."""
    try:
        levels = RUST_DETAIL_LEVELS
        if len(levels) != 12:
            print(f"detail-map-rs-fail: expected 12 levels, got {len(levels)}")
            return 1
        checks = {
            "MODULE_LISTING": 0,
            "SIGNATURES": 5,
            "FULL_SOURCE": 11,
        }
        for name, expected_depth in checks.items():
            actual = resolve_detail_level(name, levels)
            if actual != expected_depth:
                print(
                    f"detail-map-rs-fail: {name} expected {expected_depth}, "
                    f"got {actual}"
                )
                return 1
        print(f"detail-map-rs-ok: {len(levels)} levels, all depths correct")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"detail-map-rs-fail: {exc}")
        return 1


def _cmd_detail_map_java() -> int:
    """Verify Java 12-level map and key depth resolutions."""
    try:
        levels = JAVA_DETAIL_LEVELS
        if len(levels) != 12:
            print(f"detail-map-java-fail: expected 12 levels, got {len(levels)}")
            return 1
        checks = {
            "MODULE_LISTING": 0,
            "SIGNATURES": 5,
            "FULL_SOURCE": 11,
        }
        for name, expected_depth in checks.items():
            actual = resolve_detail_level(name, levels)
            if actual != expected_depth:
                print(
                    f"detail-map-java-fail: {name} expected {expected_depth}, "
                    f"got {actual}"
                )
                return 1
        print(f"detail-map-java-ok: {len(levels)} levels, all depths correct")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"detail-map-java-fail: {exc}")
        return 1


def _cmd_provenance() -> int:
    """Verify ProvenanceInfo has all 5 required fields."""
    try:
        required = {
            "source_resource",
            "source_path",
            "source_range",
            "valid_from",
            "is_current",
        }
        actual = set(ProvenanceInfo.model_fields.keys())
        missing = required - actual
        if missing:
            print(f"provenance-fail: missing fields {missing}")
            return 1
        # Round-trip construction check
        p = ProvenanceInfo(source_resource="res-01", source_path="test.py")
        if not p.is_current:
            print("provenance-fail: is_current should default to True")
            return 1
        print(f"provenance-ok: {len(required)} required fields present")
        return 0
    except (ValueError, TypeError, AttributeError, ImportError) as exc:
        traceback.print_exc()
        print(f"provenance-fail: {exc}")
        return 1


_DISPATCH: dict[str, Callable[[], int]] = {
    "vocab-py": _cmd_vocab_py,
    "vocab-ts": _cmd_vocab_ts,
    "vocab-rs": _cmd_vocab_rs,
    "vocab-java": _cmd_vocab_java,
    "detail-map-py": _cmd_detail_map_py,
    "detail-map-ts": _cmd_detail_map_ts,
    "detail-map-rs": _cmd_detail_map_rs,
    "detail-map-java": _cmd_detail_map_java,
    "provenance": _cmd_provenance,
}


def main() -> None:
    """Entry point for Robot Framework process execution."""
    if len(sys.argv) < 2 or sys.argv[1] not in _DISPATCH:
        cmds = ", ".join(sorted(_DISPATCH))
        print(f"Usage: {sys.argv[0]} <{cmds}>")
        sys.exit(2)
    sys.exit(_DISPATCH[sys.argv[1]]())


if __name__ == "__main__":
    main()
