"""
CLI table output for SC-F001 logtool.
"""

from parser import LOG_TYPE_BAT, LOG_TYPE_CRASH, LOG_TYPE_BOOT, LOG_TYPE_TIME_SET

try:
    from tabulate import tabulate
    _TABULATE_OK = True
except ImportError:
    _TABULATE_OK = False


_SENSOR_BITS = ['SAFETY', 'JACK', 'DRIVE', 'AUX2']


def _sensor_str(nibble: int) -> str:
    active = [_SENSOR_BITS[i] for i in range(4) if (nibble >> i) & 1]
    return '+'.join(active) if active else '-'


def _row(e: dict) -> list:
    t = e.get('entry_type', -1)
    name = e.get('state_name', '?')

    if 0 <= t <= 12:
        return [
            e.get('time_str', ''),
            name,
            f"{e.get('bat_V', 0):.3f}",
            f"{e.get('drive_A', 0):.2f}",
            f"{e.get('jack_A', 0):.2f}",
            f"{e.get('aux_A', 0):.2f}",
            str(e.get('counter', 0)),
            _sensor_str(e.get('sensors_stable', 0)),
            _sensor_str(e.get('sensors_raw', 0)),
            f"{e.get('drive_heat', 0):.1f}",
            f"{e.get('jack_heat', 0):.1f}",
            f"{e.get('aux_heat', 0):.1f}",
        ]
    elif t == LOG_TYPE_BAT:
        return [
            e.get('time_str', ''),
            'BAT',
            f"{e.get('bat_V', 0):.3f}",
            '—', '—', '—', '—', '—', '—', '—', '—', '—',
        ]
    elif t == LOG_TYPE_CRASH:
        return [
            e.get('time_str', ''),
            f"*** CRASH: {e.get('reason_str', '?')}",
            '—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
        ]
    elif t == LOG_TYPE_BOOT:
        return [
            e.get('time_str', ''),
            f"BOOT  rst={e.get('reason_str', '?')}  wake={e.get('wake_str', '?')}",
            '—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
        ]
    elif t == LOG_TYPE_TIME_SET:
        return [
            e.get('time_str', ''),
            'TIME_SET',
            '—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
        ]
    else:
        return [
            e.get('time_str', ''),
            name,
            '—', '—', '—', '—', '—', '—', '—', '—', '—', '—',
        ]


_HEADERS = ['Time', 'State', 'Bat(V)', 'Drive(A)', 'Jack(A)', 'Aux(A)',
            'Counter', 'Stable', 'Raw', 'DrHeat', 'JkHeat', 'AxHeat']


def print_table(entries: list, type_filter: str = None):
    """Print a tabulate table of log entries to stdout."""
    if type_filter:
        tf = type_filter.lower()
        if tf == 'fsm':
            entries = [e for e in entries if 0 <= e.get('entry_type', -1) <= 12]
        elif tf == 'bat':
            entries = [e for e in entries if e.get('entry_type') == LOG_TYPE_BAT]
        elif tf == 'crash':
            entries = [e for e in entries if e.get('entry_type') == LOG_TYPE_CRASH]

    rows = [_row(e) for e in entries]

    if not rows:
        print("(no entries)")
        return

    if _TABULATE_OK:
        print(tabulate(rows, headers=_HEADERS, tablefmt='simple'))
    else:
        # Manual fallback
        widths = [max(len(str(r[i])) for r in [_HEADERS] + rows) for i in range(len(_HEADERS))]
        fmt = '  '.join(f'{{:<{w}}}' for w in widths)
        print(fmt.format(*_HEADERS))
        print('  '.join('-' * w for w in widths))
        for row in rows:
            print(fmt.format(*row))


def print_summary(entries: list):
    """Print a brief summary: time range, entry counts, voltage range."""
    if not entries:
        print("(empty log)")
        return

    fsm_entries      = [e for e in entries if 0 <= e.get('entry_type', -1) <= 12]
    bat_entries      = [e for e in entries if e.get('entry_type') == LOG_TYPE_BAT]
    crash_entries    = [e for e in entries if e.get('entry_type') == LOG_TYPE_CRASH]
    boot_entries     = [e for e in entries if e.get('entry_type') == LOG_TYPE_BOOT]
    time_set_entries = [e for e in entries if e.get('entry_type') == LOG_TYPE_TIME_SET]

    all_ts = [e.get('ts_ms', 0) for e in entries if e.get('ts_ms')]
    ts_min = min(all_ts) if all_ts else 0
    ts_max = max(all_ts) if all_ts else 0

    all_bat = [e['bat_V'] for e in entries if 'bat_V' in e]

    print(f"Entries : {len(entries)} total  "
          f"({len(fsm_entries)} FSM, {len(bat_entries)} BAT, "
          f"{len(crash_entries)} CRASH, {len(boot_entries)} BOOT, "
          f"{len(time_set_entries)} TIME_SET)")
    if all_ts:
        from parser import _ts_to_str
        print(f"Time    : {_ts_to_str(ts_min)}  →  {_ts_to_str(ts_max)}")
        dur_s = (ts_max - ts_min) / 1000
        print(f"Duration: {dur_s:.1f} s  ({dur_s/60:.1f} min)")
    if all_bat:
        print(f"Battery : {min(all_bat):.3f} V – {max(all_bat):.3f} V")
    if boot_entries:
        print(f"\nBOOT events:")
        for e in boot_entries:
            print(f"  {e.get('time_str', '?')}  rst={e.get('reason_str', '?')}  wake={e.get('wake_str', '?')}")
    if crash_entries:
        print(f"\nCRASH events:")
        for e in crash_entries:
            print(f"  {e.get('time_str', '?')}  reason={e.get('reason_str', '?')}")
    if time_set_entries:
        print(f"\nTIME_SET events:")
        for e in time_set_entries:
            print(f"  {e.get('time_str', '?')}")


def append_rows(new_entries: list):
    """Print new rows without header (for streaming append mode)."""
    for e in new_entries:
        row = _row(e)
        if _TABULATE_OK:
            print(tabulate([row], tablefmt='plain'))
        else:
            print('  '.join(str(c) for c in row))
