"""
RGD-PHYSICS :: CODEC (Universal Decoder)
Auto-detects Aion type based on byte length and handles Hex serialization.
Critical for interfacing with Network Layers and LLMs.
"""
import binascii
from typing import Union
from .interfaces import ChrononProtocol
from .aions.light import Aion128
from .aions.standard import Aion512
from .aions.heavy import Aion4096

# Mapping Size (Bytes) -> Class
_REGISTRY = {
    16: Aion128,  # Light
    64: Aion512,  # Standard
    512: Aion4096 # Heavy
}

def decode_bytes(buffer: bytes) -> ChrononProtocol:
    """
    Universal Factory: Converts raw bytes into the correct Aion object.
    Auto-detects isotope based on buffer length.
    
    Args:
        buffer: Raw binary data (16, 64, or 512 bytes).
    
    Returns:
        A valid Aion instance (Aion128, Aion512, or Aion4096).
    
    Raises:
        ValueError: If the buffer size doesn't match any known standard.
    """
    size = len(buffer)
    
    if size not in _REGISTRY:
        raise ValueError(f"RGD CODEC ERROR: Unknown Aion size: {size} bytes. Must be 16, 64, or 512.")
    
    # Dispatch to the specific class .from_bytes() method
    target_class = _REGISTRY[size]
    return target_class.from_bytes(buffer)

def from_hex(hex_string: str) -> ChrononProtocol:
    """
    Converts a Hexadecimal string (common LLM output) into an Aion.
    Strips '0x' prefix/whitespace if present.
    """
    clean_hex = hex_string.strip().lower().replace("0x", "").replace(" ", "")
    try:
        raw_bytes = binascii.unhexlify(clean_hex)
        return decode_bytes(raw_bytes)
    except (binascii.Error, ValueError) as e:
        raise ValueError(f"RGD CODEC ERROR: Invalid Hex Stream. {e}")

def to_hex(aion: ChrononProtocol) -> str:
    """
    Serializes an Aion into a pure Hex string.
    Useful for logging or feeding back into an LLM context.
    """
    # Duck typing: we assume the object has a .to_bytes() method 
    # (which all our Aions do, even if not explicitly in Protocol)
    if hasattr(aion, 'to_bytes'):
        raw_bytes = aion.to_bytes()
        return binascii.hexlify(raw_bytes).decode('ascii').upper()
    
    raise TypeError(f"Object {type(aion)} does not support binary serialization.")