"""Tests for the OpenDisplay integration."""

from time import time

from bleak.backends.scanner import AdvertisementData
from opendisplay import (
    BinaryInputs,
    BoardManufacturer,
    ColorScheme,
    DisplayConfig,
    GlobalConfig,
    ManufacturerData,
    PowerOption,
    SystemConfig,
)

from homeassistant.components.bluetooth import BluetoothServiceInfoBleak

from tests.components.bluetooth import generate_ble_device

OPENDISPLAY_MANUFACTURER_ID = 9286  # 0x2446

# V1 advertisement payload (14 bytes):
# battery_mv=3700, temperature_c=25.0, loop_counter=1
V1_ADVERTISEMENT_DATA = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x72\x11"

TEST_ADDRESS = "AA:BB:CC:DD:EE:FF"
TEST_TITLE = "OpenDisplay 1234"
ENCRYPTION_KEY = "aabbccddee112233aabbccddee112233"  # 32 hex chars = 16 bytes

# Firmware version response: major=1, minor=2, sha="abc123"
FIRMWARE_VERSION = {"major": 1, "minor": 2, "sha": "abc123"}

DEVICE_CONFIG = GlobalConfig(
    system=SystemConfig(
        ic_type=0,
        communication_modes=0,
        device_flags=0,
        pwr_pin=0xFF,
        reserved=b"\x00" * 17,
    ),
    manufacturer=ManufacturerData(
        manufacturer_id=BoardManufacturer.SEEED,
        board_type=1,
        board_revision=0,
        reserved=b"\x00" * 18,
    ),
    power=PowerOption(
        power_mode=0,
        battery_capacity_mah=b"\x00" * 3,
        sleep_timeout_ms=0,
        tx_power=0,
        sleep_flags=0,
        battery_sense_pin=0xFF,
        battery_sense_enable_pin=0xFF,
        battery_sense_flags=0,
        capacity_estimator=0,
        voltage_scaling_factor=0,
        deep_sleep_current_ua=0,
        deep_sleep_time_seconds=0,
        reserved=b"\x00" * 12,
    ),
    displays=[
        DisplayConfig(
            instance_number=0,
            display_technology=0,
            panel_ic_type=0,
            pixel_width=296,
            pixel_height=128,
            active_width_mm=67,
            active_height_mm=29,
            tag_type=0,
            rotation=0,
            reset_pin=0xFF,
            busy_pin=0xFF,
            dc_pin=0xFF,
            cs_pin=0xFF,
            data_pin=0,
            partial_update_support=0,
            color_scheme=ColorScheme.BWR.value,
            transmission_modes=0x01,
            clk_pin=0,
            reserved_pins=b"\x00" * 7,
            full_update_mC=0,
            reserved=b"\x00" * 33,
        )
    ],
)


def make_service_info(
    name: str | None = "OpenDisplay 1234",
    address: str = "AA:BB:CC:DD:EE:FF",
    manufacturer_data: dict[int, bytes] | None = None,
) -> BluetoothServiceInfoBleak:
    """Create a BluetoothServiceInfoBleak for testing."""
    if manufacturer_data is None:
        manufacturer_data = {OPENDISPLAY_MANUFACTURER_ID: V1_ADVERTISEMENT_DATA}
    return BluetoothServiceInfoBleak(
        name=name or "",
        address=address,
        rssi=-60,
        manufacturer_data=manufacturer_data,
        service_data={},
        service_uuids=[],
        source="local",
        connectable=True,
        time=time(),
        device=generate_ble_device(address, name=name),
        advertisement=AdvertisementData(
            local_name=name,
            manufacturer_data=manufacturer_data,
            service_data={},
            service_uuids=[],
            rssi=-60,
            tx_power=-127,
            platform_data=(),
        ),
        tx_power=-127,
    )


BINARY_INPUT = BinaryInputs(
    instance_number=0,
    input_type=0,
    display_as=0,
    reserved_pins=b"\x00" * 8,
    input_flags=0x01,  # bit 0 set → button_id 0 active
    invert=0,
    pullups=0,
    pulldowns=0,
    button_data_byte_index=0,
)

BUTTON_DEVICE_CONFIG = GlobalConfig(
    system=DEVICE_CONFIG.system,
    manufacturer=DEVICE_CONFIG.manufacturer,
    power=DEVICE_CONFIG.power,
    displays=DEVICE_CONFIG.displays,
    binary_inputs=[BINARY_INPUT],
)


def make_v1_service_info(
    dynamic_data: bytes = b"\x00" * 11,
    name: str | None = "OpenDisplay 1234",
    address: str = TEST_ADDRESS,
) -> BluetoothServiceInfoBleak:
    """Create a v1 advertisement service info with a custom 11-byte dynamic block."""
    # temperature=25.0°C, battery≈3700 mV, loop_counter=1
    return make_service_info(
        name=name,
        address=address,
        manufacturer_data={OPENDISPLAY_MANUFACTURER_ID: dynamic_data + b"\x82\x72\x11"},
    )


def make_binary_inputs(
    instance_number: int = 0,
    byte_index: int = 0,
    input_flags: int = 0x01,
) -> BinaryInputs:
    """Create a minimal BinaryInputs config entry.

    input_flags is a bitmask of active inputs: bit N set means button_id N is active.
    """
    return BinaryInputs(
        instance_number=instance_number,
        input_type=0,
        display_as=0,
        reserved_pins=b"\x00" * 8,
        input_flags=input_flags,
        invert=0,
        pullups=0,
        pulldowns=0,
        button_data_byte_index=byte_index,
    )


def make_button_device_config(binary_inputs: list[BinaryInputs]) -> GlobalConfig:
    """Return a GlobalConfig with the given binary_inputs list."""
    return GlobalConfig(
        system=DEVICE_CONFIG.system,
        manufacturer=DEVICE_CONFIG.manufacturer,
        power=DEVICE_CONFIG.power,
        displays=DEVICE_CONFIG.displays,
        binary_inputs=binary_inputs,
    )


VALID_SERVICE_INFO = make_service_info()

NOT_OPENDISPLAY_SERVICE_INFO = make_service_info(
    name="Other Device",
    manufacturer_data={0x1234: b"\x00\x01"},
)
