from __future__ import annotations

import json
from pathlib import Path

from pymulator.setup import Setup


def _load_kwp_fixture() -> dict:
    fixture = Path(__file__).resolve().parent / "fixtures" / "kwp.json"
    return json.loads(fixture.read_text(encoding="utf-8"))


def test_setup_accepts_inline_vehicle_with_legacy_kind(tmp_path: Path) -> None:
    kwp_spec = _load_kwp_fixture()
    vehicle = {
        "formatVersion": 2,
        "name": "Inline Legacy Vehicle",
        "vin": "YS2R6X40005412735",
        "ecus": [{"name": "ENGINE", "kind": "kwp", "kwp": kwp_spec["kwp"]}],
    }
    vehicle_path = tmp_path / "inline-legacy.vehicle"
    vehicle_path.write_text(json.dumps(vehicle), encoding="utf-8")

    setup = Setup()
    setup.add(str(vehicle_path))

    assert "ENGINE" in setup._ecu_map
    assert len(setup._ecu_map["ENGINE"]._handlers) == 1
    assert setup._path_map["ENGINE"].endswith("#ENGINE")


def test_setup_accepts_inline_vehicle_with_ui_protocol_shape(tmp_path: Path) -> None:
    kwp_spec = _load_kwp_fixture()["kwp"]
    kwp_inline = {key: value for key, value in kwp_spec.items() if key != "arbitration"}
    kwp_inline["timingParameters"] = [25.0, 5000.0, 0.5]

    vehicle = {
        "formatVersion": 2,
        "name": "Inline UI Vehicle",
        "vin": "YS2R6X40005412735",
        "ecus": [
            {
                "role": "POWERTRAIN",
                "name": "Scania S8",
                "protocol": "kwp",
                "arbitration": {
                    "requestId": 0x18DA00F9,
                    "replyId": 0x18DAF900,
                    "auxiliaryIds": [],
                    "auxiliaryRequestExtensions": [],
                },
                "kwp": kwp_inline,
            }
        ],
    }
    vehicle_path = tmp_path / "inline-ui.vehicle"
    vehicle_path.write_text(json.dumps(vehicle), encoding="utf-8")

    setup = Setup()
    setup.add(str(vehicle_path))

    assert "Scania S8" in setup._ecu_map
    handler = setup._ecu_map["Scania S8"]._handlers[0]
    assert handler.arbitration_id == 0x18DA00F9
    assert handler.reply_id == 0x18DAF900


def test_setup_accepts_mixed_path_and_inline_vehicle(tmp_path: Path) -> None:
    kwp_spec = _load_kwp_fixture()
    ecu_path = tmp_path / "engine.json"
    ecu_path.write_text(json.dumps(kwp_spec), encoding="utf-8")

    kwp_inline = {key: value for key, value in kwp_spec["kwp"].items() if key != "arbitration"}
    vehicle = {
        "formatVersion": 2,
        "name": "Mixed Vehicle",
        "vin": "YS2R6X40005412735",
        "ecus": [
            {"name": "FILE_ECU", "path": "engine.json"},
            {
                "role": "INLINE_ECU",
                "protocol": "kwp",
                "arbitration": {
                    "requestId": 0x18DA00F9,
                    "replyId": 0x18DAF900,
                    "auxiliaryIds": [],
                    "auxiliaryRequestExtensions": [],
                },
                "kwp": kwp_inline,
            },
        ],
    }
    vehicle_path = tmp_path / "mixed.vehicle"
    vehicle_path.write_text(json.dumps(vehicle), encoding="utf-8")

    setup = Setup()
    setup.add(str(vehicle_path))

    assert "FILE_ECU" in setup._ecu_map
    assert "INLINE_ECU" in setup._ecu_map
    assert setup._path_map["FILE_ECU"] == str(ecu_path.resolve())
    assert setup._path_map["INLINE_ECU"].endswith("#INLINE_ECU")
