from __future__ import annotations

from typing import Iterable, List, Optional


class SpecParseError(Exception):
    pass


def parse_hex_int(value) -> int:
    if isinstance(value, int):
        return value
    if isinstance(value, str):
        trimmed = value.strip()
        if not trimmed:
            raise SpecParseError("Empty hex value")
        lower = trimmed.lower()
        if lower.startswith("0x"):
            digits = lower[2:]
        else:
            digits = trimmed
        return int(digits, 16)
    raise SpecParseError(f"Unsupported hex value type: {type(value)}")


def parse_hex_byte(value) -> int:
    if isinstance(value, int):
        if not (0 <= value <= 0xFF):
            raise SpecParseError("Byte out of range")
        return value
    if isinstance(value, str):
        trimmed = value.strip()
        if trimmed.lower().startswith("0x"):
            trimmed = trimmed[2:]
        if len(trimmed) == 0:
            raise SpecParseError("Empty byte")
        return int(trimmed, 16)
    raise SpecParseError("Unsupported byte type")


def parse_hex_bytes(value, allow_odd_length: bool = False) -> List[int]:
    if value is None:
        return []
    if isinstance(value, list):
        return [parse_hex_byte(item) for item in value]
    if isinstance(value, str):
        trimmed = value.strip()
        if not trimmed:
            return []
        lower = trimmed.lower()
        if lower.startswith("0x"):
            lower = lower[2:]
        normalized = "".join(ch for ch in lower if ch not in " \t\n\r,_")
        if len(normalized) % 2 != 0:
            if allow_odd_length:
                normalized = "0" + normalized
            else:
                raise SpecParseError("Hex string must have even length")
        bytes_out = []
        for index in range(0, len(normalized), 2):
            pair = normalized[index:index + 2]
            bytes_out.append(int(pair, 16))
        return bytes_out
    raise SpecParseError("Unsupported bytes type")


def parse_hex_bytes_optional(value) -> Optional[List[int]]:
    if value is None:
        return None
    return parse_hex_bytes(value)


def parse_hex_string_list(value) -> List[List[int]]:
    if isinstance(value, list) and value and all(isinstance(item, list) for item in value):
        return [parse_hex_bytes(item) for item in value]
    if isinstance(value, list) and value and all(isinstance(item, str) for item in value):
        return [parse_hex_bytes(item) for item in value]
    if isinstance(value, list):
        return [parse_hex_bytes(value)]
    raise SpecParseError("Unsupported sequence value")


def parse_hex_array(value) -> List[int]:
    return parse_hex_bytes(value)


def parse_optional_string(value) -> Optional[str]:
    if value is None:
        return None
    return str(value)


def parse_float(value, default: float = 0.0) -> float:
    if value is None:
        return default
    return float(value)
