from __future__ import annotations

from pymulator.specimport.core import ConversationCandidate
from pymulator.specimport.core import build_ecu_spec


def test_build_uds_spec_exports_identifiers_routines_security_and_custom_services() -> None:
    candidate = ConversationCandidate(
        key="7E0-7E8",
        request_id=0x7E0,
        response_id=0x7E8,
        extended_addr=None,
        message_count=6,
        request_count=6,
        response_count=6,
        matched_pairs=6,
        unmatched_requests=0,
        unique_requests=6,
        score=60,
        confidence="high",
        protocol_hint="uds",
        vin=None,
        auxiliary_request_ids=[0x7DF],
        request_response_map={
            "10 03": [[0x50, 0x03, 0x00, 0x64, 0x01, 0x2C]],
            "22 F1 90": [[0x62, 0xF1, 0x90, 0x57, 0x56, 0x57, 0x5A, 0x5A, 0x5A, 0x31, 0x4A, 0x5A, 0x58, 0x57, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]],
            "31 01 12 34 AA": [[0x71, 0x01, 0x12, 0x34, 0x99]],
            "31 03 12 34 AA": [[0x71, 0x03, 0x12, 0x34, 0x98]],
            "27 05": [[0x67, 0x05, 0x01, 0x02]],
            "27 06 0A 0B": [[0x67, 0x06]],
            "2E F1 90 00": [[0x6E, 0xF1, 0x90]],
            "34 00 44 80 14 00 00 00 0C 00 00": [[0x74, 0x20, 0x0F, 0xFF]],
        },
    )

    spec = build_ecu_spec(candidate, ecu_name="ECU_7E0", default_vin="UNKNOWN00000000000")
    uds = spec["uds"]

    assert uds["vin"] == "WVWZZZ1JZXW000000"
    assert uds["p2ServerMax"] == 0.1
    assert uds["p2extServerMax"] == 3.0
    identifiers = {identifier["id"]: identifier for identifier in uds["identifiers"]}
    assert "0xF190" in identifiers
    assert identifiers["0xF190"]["writeLevels"] == [5]

    assert len(uds["routines"]) == 1
    routine = uds["routines"][0]
    assert routine["id"] == "0x1234"
    assert routine["ignoreOptionRecord"] is False
    assert len(routine["responses"]) == 1
    assert routine["responses"][0]["optionRecord"] == "AA"
    assert routine["responses"][0]["startResponse"] == "99"
    assert routine["responses"][0]["resultsResponse"] == "98"

    assert len(uds["securityLevels"]) == 1
    security = uds["securityLevels"][0]
    assert security["level"] == "0x05"
    assert security["seedKeyPairs"] == [{"seed": "01 02", "key": "0A 0B"}]

    assert len(uds["memoryLayout"]) == 1
    memory = uds["memoryLayout"][0]
    assert memory["address"] == "0x80140000"
    assert memory["size"] == "0x000C0000"
    assert memory["mtu"] == "0xFFF"

    custom_requests = {service["request"] for service in uds["customServices"]}
    assert "2E F1 90 00" not in custom_requests
    assert "34 00 44 80 14 00 00 00 0C 00 00" not in custom_requests
    assert "22 F1 90" not in custom_requests
    assert "31 01 12 34 AA" not in custom_requests
    assert "27 05" not in custom_requests


def test_build_uds_spec_creates_write_only_identifier_with_empty_content() -> None:
    candidate = ConversationCandidate(
        key="7E0-7E8",
        request_id=0x7E0,
        response_id=0x7E8,
        extended_addr=None,
        message_count=3,
        request_count=3,
        response_count=3,
        matched_pairs=3,
        unmatched_requests=0,
        unique_requests=3,
        score=30,
        confidence="high",
        protocol_hint="uds",
        vin=None,
        auxiliary_request_ids=[],
        request_response_map={
            "27 05": [[0x67, 0x05, 0xCA, 0xFE]],
            "27 06 BE EF": [[0x67, 0x06]],
            "2E F1 A0 12 34": [[0x6E, 0xF1, 0xA0]],
        },
    )

    spec = build_ecu_spec(candidate, ecu_name="ECU_7E0", default_vin="UNKNOWN00000000000")
    identifiers = {identifier["id"]: identifier for identifier in spec["uds"]["identifiers"]}
    assert "0xF1A0" in identifiers
    assert identifiers["0xF1A0"]["bytes"] == ""
    assert identifiers["0xF1A0"]["writeLevels"] == [5]
