"""Helper utilities extracted from monitor.py for formatting and enum lookups.
These functions are UI-agnostic and can be unit-tested independently.
"""
import importlib
import sys

UNSET_TEXT = "<unset>"


def fmt_enum(val, enum_names):
    """Format numeric `val` with possible enum name(s)."""
    try:
        enums_mod = None
        try:
            enums_mod = importlib.import_module('Grifo_E_1553lib.data_types.enums')
        except Exception:
            try:
                enums_mod = importlib.import_module('pybusmonitor1553.Grifo_E_1553lib.data_types.enums')
            except Exception:
                enums_mod = None
        if enums_mod is None:
            return str(val)
        for name in enum_names:
            enum_cls = getattr(enums_mod, name, None)
            if enum_cls is not None:
                try:
                    v = int(val)
                    try:
                        enum_name = enum_cls(v).name
                    except Exception:
                        enum_name = str(getattr(enum_cls, v, ''))
                    try:
                        if not enum_name or str(enum_name).lower() == 'none':
                            return str(v)
                    except Exception:
                        pass
                    return f"{v} ({enum_name})"
                except Exception:
                    continue
    except Exception:
        pass
    return str(val)


def get_enum_items(class_name):
    """Return list of (name, value) tuples for enum class, or None."""
    try:
        enums_mod = None
        try:
            enums_mod = importlib.import_module('Grifo_E_1553lib.data_types.enums')
        except Exception:
            try:
                enums_mod = importlib.import_module('pybusmonitor1553.Grifo_E_1553lib.data_types.enums')
            except Exception:
                enums_mod = None
        if enums_mod is None:
            return None
        enum_cls = getattr(enums_mod, class_name, None)
        if enum_cls is None:
            return None
        items = []
        if hasattr(enum_cls, '__members__'):
            for name, member in enum_cls.__members__.items():
                try:
                    items.append((name, int(member.value)))
                except Exception:
                    try:
                        items.append((name, int(member)))
                    except Exception:
                        pass
            return items
        for a in dir(enum_cls):
            if not a.isupper():
                continue
            try:
                v = getattr(enum_cls, a)
                if isinstance(v, int):
                    items.append((a, int(v)))
            except Exception:
                continue
        return items if items else None
    except Exception:
        return None


def format_ctypes_obj(obj, indent=0, max_depth=3):
    pad = '  ' * indent
    if obj is None:
        return f"{pad}{UNSET_TEXT}\n"
    try:
        if hasattr(obj, 'value') and not hasattr(obj, '__dict__'):
            try:
                return f"{pad}{int(obj.value)}\n"
            except Exception:
                return f"{pad}{obj}\n"
        if isinstance(obj, (int, float, str)):
            return f"{pad}{obj}\n"
    except Exception:
        pass

    if hasattr(obj, 'raw') and not hasattr(obj, '__dict__'):
        try:
            raw = int(obj.raw)
            cls_name = obj.__class__.__name__
            enum_str = fmt_enum(raw, [cls_name])
            if enum_str == str(raw):
                return f"{pad}{raw}\n"
            else:
                return f"{pad}{enum_str}\n"
        except Exception:
            return f"{repr(obj)}\n"

    if max_depth <= 0:
        return f"{pad}{obj}\n"

    names = [n for n in dir(obj) if not n.startswith('_')]
    simple_fields = []
    for n in names:
        try:
            v = getattr(obj, n)
        except Exception:
            continue
        if callable(v):
            continue
        if isinstance(v, (int, float, str)) or hasattr(v, 'raw') or hasattr(v, 'value'):
            try:
                nested = format_ctypes_obj(v, indent=indent+1, max_depth=max_depth-1)
                simple_fields.append(f"{pad}{n}:\n{nested}")
            except Exception:
                simple_fields.append(f"{pad}{n}: <error>\n")
        else:
            try:
                nested = format_ctypes_obj(v, indent=indent+1, max_depth=max_depth-1)
                simple_fields.append(f"{pad}{n}:\n{nested}")
            except Exception:
                simple_fields.append(f"{pad}{n}: <error>\n")

    if simple_fields:
        return '\n'.join(simple_fields) + '\n'
    return f"{pad}{repr(obj)}\n"


def format_value_for_table(val):
    try:
        if val is None:
            return UNSET_TEXT
        if isinstance(val, (int, float, str)):
            return str(val)
        if hasattr(val, 'raw'):
            try:
                return fmt_enum(int(getattr(val, 'raw')), [val.__class__.__name__])
            except Exception:
                try:
                    return str(getattr(val, 'raw'))
                except Exception:
                    return repr(val)
        if hasattr(val, 'value'):
            try:
                return str(int(val.value))
            except Exception:
                try:
                    return str(val.value)
                except Exception:
                    return repr(val)
        try:
            s = format_ctypes_obj(val, indent=0, max_depth=1)
            return s.strip().splitlines()[0]
        except Exception:
            return repr(val)
    except Exception:
        return '<unrepresentable>'


def coerce_text_to_type(text: str):
    try:
        if text.startswith('0x'):
            return int(text, 16)
    except Exception:
        pass
    try:
        return int(text)
    except Exception:
        try:
            return float(text)
        except Exception:
            return text
