import unittest

from h8536.bench_connect_lcd import (
    CONNECT_LCD_SEQUENCE,
    FrameDetector,
    format_frame,
    frame_checksum,
    frame_checksum_ok,
    label_frame,
    parse_frame,
)


class BenchConnectLcdTest(unittest.TestCase):
    def test_connect_sequence_matches_emulator_preset(self):
        self.assertEqual(
            [format_frame(frame) for frame in CONNECT_LCD_SEQUENCE],
            [
                "04 00 00 40 00 1E",
                "04 00 00 80 00 DE",
                "04 00 00 C0 00 9E",
            ],
        )

    def test_parse_frame_appends_xor_checksum(self):
        frame = parse_frame("04 00 00 80 00")

        self.assertEqual(frame, bytes.fromhex("0400008000DE"))
        self.assertEqual(frame_checksum(frame), 0xDE)
        self.assertTrue(frame_checksum_ok(frame))

    def test_detector_recombines_split_rx_chunks(self):
        detector = FrameDetector()

        self.assertEqual(detector.feed(bytes.fromhex("000000")), [])
        detected = detector.feed(bytes.fromhex("0080DA02000200005A"))

        self.assertEqual(
            [(format_frame(frame), label) for frame, label in detected],
            [
                ("00 00 00 00 80 DA", "heartbeat"),
                ("02 00 02 00 00 5A", "connect_ok_path_response_candidate"),
            ],
        )

    def test_detector_resyncs_to_checksum_valid_frame(self):
        detector = FrameDetector()

        detected = detector.feed(bytes.fromhex("FF0000000080DA"))

        self.assertEqual([(format_frame(frame), label) for frame, label in detected], [
            ("00 00 00 00 80 DA", "heartbeat")
        ])
        self.assertEqual(detector.dropped_bytes, 1)
        self.assertEqual(detector.resync_events, 1)

    def test_detector_prefers_labeled_heartbeat_over_shifted_valid_window(self):
        detector = FrameDetector()
        heartbeat = bytes.fromhex("0000000080DA")

        detected = detector.feed(heartbeat[1:] + heartbeat)

        self.assertEqual([(format_frame(frame), label) for frame, label in detected], [
            ("00 00 00 00 80 DA", "heartbeat")
        ])
        self.assertEqual(detector.dropped_bytes, 5)

    def test_label_frame_marks_unlabeled_checksum_ok_frame(self):
        self.assertEqual(label_frame(bytes.fromhex("01000000005B")), "checksum_ok_unlabeled")

    def test_label_frame_marks_table_readback_candidate(self):
        self.assertEqual(label_frame(bytes.fromhex("04001280804C")), "table_readback_candidate")

    def test_label_frame_marks_real_bench_c0_6020_response(self):
        self.assertEqual(label_frame(bytes.fromhex("0780C060205D")), "visible_C0_6020_family_candidate")

    def test_label_frame_marks_visible_retry_ack_target(self):
        self.assertEqual(label_frame(bytes.fromhex("07804020902D")), "visible_retry_0040_2090_candidate")


if __name__ == "__main__":
    unittest.main()
