import os
import pathlib
import typing as t

import pytest

from ecu_framework.config import load_config, EcuTestConfig
from ecu_framework.lin.base import LinInterface
from ecu_framework.lin.mock import MockBabyLinInterface

try:
    from ecu_framework.lin.babylin import BabyLinInterface  # type: ignore
except Exception:
    BabyLinInterface = None  # type: ignore


WORKSPACE_ROOT = pathlib.Path(__file__).resolve().parents[1]


@pytest.fixture(scope="session")
def config() -> EcuTestConfig:
    cfg = load_config(str(WORKSPACE_ROOT))
    return cfg


@pytest.fixture(scope="session")
def lin(config: EcuTestConfig) -> t.Iterator[LinInterface]:
    iface_type = config.interface.type
    if iface_type == "mock":
        lin = MockBabyLinInterface(bitrate=config.interface.bitrate, channel=config.interface.channel)
    elif iface_type == "babylin":
        if BabyLinInterface is None:
            pytest.skip("BabyLin interface not available in this environment")
        lin = BabyLinInterface(
            dll_path=config.interface.dll_path,
            bitrate=config.interface.bitrate,
            channel=config.interface.channel,
            node_name=config.interface.node_name,
            func_names=config.interface.func_names,
            sdf_path=config.interface.sdf_path,
            schedule_nr=config.interface.schedule_nr,
        )
    else:
        raise RuntimeError(f"Unknown interface type: {iface_type}")

    lin.connect()
    yield lin
    lin.disconnect()


@pytest.fixture(scope="session", autouse=False)
def flash_ecu(config: EcuTestConfig, lin: LinInterface) -> None:
    if not config.flash.enabled:
        pytest.skip("Flashing disabled in config")
    # Lazy import to avoid dependency during mock-only runs
    from ecu_framework.flashing import HexFlasher

    if not config.flash.hex_path:
        pytest.skip("No HEX path provided in config")

    flasher = HexFlasher(lin)
    ok = flasher.flash_hex(config.flash.hex_path)
    if not ok:
        pytest.fail("ECU flashing failed")


@pytest.fixture
def rp(record_property: "pytest.RecordProperty"):
    """Convenience reporter: attaches a key/value as a test property and echoes to captured output.

    Usage in tests:
        def test_something(rp):
            rp("key", value)
    """
    def _rp(key: str, value):
        # Attach property (pytest-html will show in Properties table)
        record_property(str(key), value)
        # Echo to captured output for quick scanning in report details
        try:
            print(f"[prop] {key}={value}")
        except Exception:
            pass
    return _rp
