#!/usr/bin/env python3
"""Сравнение трасс decode по carraw3 vs pointraw_3 для кадра pkt[33] (car: CRC fail)."""
from __future__ import annotations

import sys
from pathlib import Path

_TOOLS = Path(__file__).resolve().parent
if str(_TOOLS) not in sys.path:
    sys.path.insert(0, str(_TOOLS))

from ir_decoder_raw_sim import (
    BIT_TIME_US,
    RISE_MAX,
    RISE_MIN,
    SimState,
    first_rx,
    parse_raw_csv,
    segments_to_edges,
    tick,
)


def run_traced(path: Path) -> tuple[SimState, list[dict]]:
    rows = parse_raw_csv(path)
    assert rows is not None
    edges = segments_to_edges(rows)
    st = SimState()
    tr: list[dict] = []
    for t_us, rising in edges:
        tick(st, t_us, rising, BIT_TIME_US, trace_rise=tr)
    return st, tr


def main() -> None:
    root = Path(__file__).resolve().parents[1] / "Analyzer" / "raw"
    car_p = root / "carraw3.txt"
    pt_p = root / "pointraw_3.txt"
    st_c, tr_c = run_traced(car_p)
    st_p, tr_p = run_traced(pt_p)

    bad_i = next(i for i, x in enumerate(st_c.packets) if not x[0])
    print(f"carraw3: bad packet index {bad_i}, bytes {st_c.packets[bad_i][2].hex()}")
    print(f"carraw3 packets={len(st_c.packets)} ok={sum(1 for x in st_c.packets if x[0])}")
    print(f"pointraw_3 packets={len(st_p.packets)} ok={sum(1 for x in st_p.packets if x[0])}")
    print(f"rise window us: min={RISE_MIN} max={RISE_MAX} bit={BIT_TIME_US}")
    print()

    # Пока кадр №bad_i собирается, в списке уже bad_i завершённых пакетов → len(packets)==bad_i.
    build_i = bad_i

    def frame_trace(tr: list[dict]) -> list[dict]:
        return [r for r in tr if r["n_pkt"] == build_i]

    fc = frame_trace(tr_c)
    fp = frame_trace(tr_p)
    print(
        f"decode rises while building packet[{bad_i}] (trace n_pkt=={build_i}): "
        f"car {len(fc)} vs point {len(fp)} lines"
    )
    print("--- car (first 40 decode steps of this frame) ---")
    for i, r in enumerate(fc[:40]):
        br = r["branch"]
        ex = ""
        if br == "ceil":
            ex = f" hc={r['hc']} lc={r['lc']} ac={r['ac']}"
        print(
            f"  {i:2} t={r['t_us'] / 1e6:.6f}s rp={r['rp']} ht={r['ht']} lt={r['lt']} "
            f"{br} bits_out={r['bits_out']} i_buf={r['i_buf']}{ex}"
        )
    print("--- point (first 40) ---")
    for i, r in enumerate(fp[:40]):
        br = r["branch"]
        ex = ""
        if br == "ceil":
            ex = f" hc={r['hc']} lc={r['lc']} ac={r['ac']}"
        print(
            f"  {i:2} t={r['t_us'] / 1e6:.6f}s rp={r['rp']} ht={r['ht']} lt={r['lt']} "
            f"{br} bits_out={r['bits_out']} i_buf={r['i_buf']}{ex}"
        )

    print()
    # Первое расхождение по (rp, ht, lt, branch, bits_out)
    for i, (a, b) in enumerate(zip(fc, fp)):
        ka = (a["rp"], a["ht"], a["lt"], a["branch"], a["bits_out"])
        kb = (b["rp"], b["ht"], b["lt"], b["branch"], b["bits_out"])
        if ka != kb:
            print(f"First decode diff at step {i} within frame:")
            print(f"  car   {a}")
            print(f"  point {b}")
            break
    else:
        if len(fc) != len(fp):
            print(f"Same tuples for min(len)={min(len(fc), len(fp))}; length car={len(fc)} point={len(fp)}")
        else:
            print("Identical decode trace for full frame (unexpected if CRC differs)")


if __name__ == "__main__":
    main()
