from __future__ import annotations

import asyncio
from importlib.metadata import version
from typing import TypedDict

from bleak import BleakClient, BleakScanner
from bleak.exc import BleakDeviceNotFoundError

from k1link.artifacts import utc_now_iso


class CharacteristicReadResult(TypedDict):
    schema_version: int
    started_at_utc: str
    completed_at_utc: str
    adapter: str
    bleak_version: str
    device_macos_uuid: str
    device_name: str
    characteristic_uuid: str
    operation: str
    value_length: int
    value_hex: str


async def read_characteristic_once(
    device_macos_uuid: str,
    characteristic_uuid: str,
    timeout_seconds: float,
) -> CharacteristicReadResult:
    """Read one explicitly selected characteristic once without pairing or writes."""
    if timeout_seconds <= 0:
        raise ValueError("timeout_seconds must be positive")

    started_at = utc_now_iso()
    async with asyncio.timeout(timeout_seconds):
        device = await BleakScanner.find_device_by_address(
            device_macos_uuid,
            timeout=min(20.0, timeout_seconds),
        )
        if device is None:
            raise BleakDeviceNotFoundError(
                device_macos_uuid,
                "Device was not rediscovered; keep the K1 powered and nearby.",
            )

        async with BleakClient(device, timeout=timeout_seconds, pair=False) as client:
            characteristic = client.services.get_characteristic(characteristic_uuid)
            if characteristic is None:
                raise ValueError(f"Characteristic not found: {characteristic_uuid}")
            if "read" not in characteristic.properties:
                raise ValueError(f"Characteristic is not readable: {characteristic_uuid}")
            value = bytes(await client.read_gatt_char(characteristic))

            return {
                "schema_version": 1,
                "started_at_utc": started_at,
                "completed_at_utc": utc_now_iso(),
                "adapter": "CoreBluetooth",
                "bleak_version": version("bleak"),
                "device_macos_uuid": device_macos_uuid,
                "device_name": client.name,
                "characteristic_uuid": characteristic.uuid,
                "operation": "single_gatt_read_no_pair_no_write",
                "value_length": len(value),
                "value_hex": value.hex(),
            }
