from __future__ import annotations

from hockey_data.agent_bridge import (
    _mapping_numeric_value,
    _mapping_rule_command,
    _mapping_rule_matches,
    _mapping_value_function,
)


def _item(value: object) -> dict[str, object]:
    return {"value": value}


def test_mapping_numeric_value_supports_stats_formats() -> None:
    assert _mapping_numeric_value("25") == 25.0
    assert _mapping_numeric_value("51%") == 51.0
    assert _mapping_numeric_value("08:14") == 494.0
    assert _mapping_numeric_value("1:02:03") == 3723.0
    assert _mapping_numeric_value("12,5") == 12.5


def test_mapping_rule_matches_numeric_time_and_text() -> None:
    assert _mapping_rule_matches("25", "gt", "18") is True
    assert _mapping_rule_matches("08:14", ">", "07:59") is True
    assert _mapping_rule_matches("49%", "lt", "51%") is True
    assert _mapping_rule_matches("HOME", "eq", "home") is True
    assert _mapping_rule_matches("Power Play", "contains", "play") is True
    assert _mapping_rule_matches("", "empty") is True


def test_text_colour_rule_uses_true_and_false_colours() -> None:
    base = {
        "enabled": True,
        "action": "text_colour",
        "left_key": "stats.home",
        "operator": "gt",
        "right_mode": "field",
        "right_key": "stats.away",
        "true_value": "#E5CEA8",
        "false_value": "#FFFFFF",
    }
    command, error = _mapping_rule_command(
        base,
        field_type="text",
        input_ref="53",
        selected_name="HOME_SHOTS.Text",
        default_data_key="stats.home",
        by_key={"stats.home": _item(31), "stats.away": _item(25)},
    )
    assert error == ""
    assert command == {
        "Function": "SetTextColour",
        "Input": "53",
        "SelectedName": "HOME_SHOTS.Text",
        "Value": "#E5CEA8",
    }

    command, error = _mapping_rule_command(
        base,
        field_type="text",
        input_ref="53",
        selected_name="HOME_SHOTS.Text",
        default_data_key="stats.home",
        by_key={"stats.home": _item(20), "stats.away": _item(25)},
    )
    assert error == ""
    assert command is not None
    assert command["Value"] == "#FFFFFF"


def test_visibility_rule_is_deterministic_for_text_and_image() -> None:
    rule = {
        "enabled": True,
        "action": "visibility",
        "left_key": "stats.home",
        "operator": "gt",
        "right_mode": "field",
        "right_key": "stats.away",
        "true_value": "on",
        "false_value": "off",
    }
    text_command, text_error = _mapping_rule_command(
        rule,
        field_type="text",
        input_ref="53",
        selected_name="HOME_ARROW.Text",
        default_data_key="stats.home",
        by_key={"stats.home": _item(10), "stats.away": _item(7)},
    )
    assert text_error == ""
    assert text_command is not None
    assert text_command["Function"] == "SetTextVisibleOn"

    image_command, image_error = _mapping_rule_command(
        rule,
        field_type="image",
        input_ref="53",
        selected_name="HOME_ARROW.Source",
        default_data_key="image.path",
        by_key={"stats.home": _item(5), "stats.away": _item(7)},
    )
    assert image_error == ""
    assert image_command is not None
    assert image_command["Function"] == "SetImageVisibleOff"
    assert "Value" not in image_command


def test_rule_can_compare_constant_and_reports_missing_source() -> None:
    rule = {
        "enabled": True,
        "action": "visibility",
        "left_key": "penalties",
        "operator": "gte",
        "right_mode": "value",
        "right_value": "10",
        "true_value": "on",
        "false_value": "off",
    }
    command, error = _mapping_rule_command(
        rule,
        field_type="text",
        input_ref="1",
        selected_name="WARNING.Text",
        default_data_key="penalties",
        by_key={"penalties": _item(12)},
    )
    assert error == ""
    assert command is not None
    assert command["Function"] == "SetTextVisibleOn"

    missing, error = _mapping_rule_command(
        {**rule, "left_key": "missing"},
        field_type="text",
        input_ref="1",
        selected_name="WARNING.Text",
        default_data_key="penalties",
        by_key={"penalties": _item(12)},
    )
    assert missing is None
    assert error == "missing_left:missing"


def test_mapping_value_function_respects_mapping_type() -> None:
    assert _mapping_value_function("text") == "SetText"
    assert _mapping_value_function("image") == "SetImage"
    assert _mapping_value_function("source") == "SetImage"
    assert _mapping_value_function("color") == "SetColor"


def test_mapping_rule_controls_do_not_trigger_card_rerender() -> None:
    from pathlib import Path

    source = (Path(__file__).resolve().parents[1] / "hockey_data" / "static" / "admin-directories.js").read_text(encoding="utf-8")
    assert 'event.target.closest("button, input, select, textarea, label, a' in source
    assert '.hockey-map-rule-wrap' in source


def test_mapping_vmix_scroll_is_preserved_across_save_and_rerender() -> None:
    from pathlib import Path

    source = (Path(__file__).resolve().parents[1] / "hockey_data" / "static" / "admin-directories.js").read_text(encoding="utf-8")
    assert 'mappingVmixScrollTop: 0' in source
    assert 'vmixScroll.scrollTop = Math.max(0, Number(state.mappingVmixScrollTop || 0))' in source
    assert 'state.mappingVmixScrollTop = vmixScroll.scrollTop' in source
    assert 'if (currentScroll) state.mappingVmixScrollTop = currentScroll.scrollTop' in source
