#!/usr/bin/env python3
"""
Golden value generator for the simplified FIX message parser (Problem 023).

Messages are ASCII TAG=VALUE<SOH> pairs. Tag 10 is always the final field
and acts only as the end-of-message marker. Its 3-digit value is ignored by
the DUT.
"""

SOH = 0x01


def build_message(fields: list[tuple[int, str]], tag10: str) -> tuple[bytes, dict]:
    raw = bytearray()
    expected = {"msg_type": 0, "sender_id": 0, "msg_seq_num": 0}

    for tag, value in fields:
        raw.extend(f"{tag}={value}".encode("ascii"))
        raw.append(SOH)

        if tag == 35:
            expected["msg_type"] = ord(value[0]) if value else 0
        elif tag == 49:
            padded = value[:8].ljust(8, "\x00")
            expected["sender_id"] = int.from_bytes(padded.encode("latin-1"), "big")
        elif tag == 34:
            expected["msg_seq_num"] = int(value)

    raw.extend(f"10={tag10}".encode("ascii"))
    raw.append(SOH)

    return bytes(raw), expected


tests = [
    ("Basic ordered", build_message([(8, "FIX.4.2"), (35, "D"), (49, "SENDER01"), (34, "1")], "172")),
    ("Short sender", build_message([(8, "FIX.4.2"), (35, "8"), (49, "AB"), (34, "42")], "005")),
    ("Unusual order", build_message([(8, "FIX.4.2"), (49, "REORDER"), (34, "77"), (35, "D")], "218")),
    ("Extra ignored tags", build_message([(8, "FIX.4.2"), (9, "120"), (35, "D"), (49, "ALPHA"), (34, "500"), (11, "ORD123"), (55, "AAPL")], "152")),
    ("Large seq", build_message([(8, "FIX.4.2"), (35, "D"), (49, "BIGSEQ"), (34, "16777300")], "179")),
    ("One-char ID", build_message([(8, "FIX.4.2"), (35, "0"), (49, "A"), (34, "12345")], "333")),
    ("Max-length ID", build_message([(8, "FIX.4.2"), (35, "F"), (49, "ABCDEFGH"), (34, "256")], "151")),
    ("FIX44 extras", build_message([(8, "FIX.4.4"), (35, "A"), (49, "INIT"), (34, "1"), (98, "0"), (108, "30")], "214")),
    ("Tag10 ignored", build_message([(8, "FIX.4.2"), (35, "5"), (49, "LOGOUT_S"), (34, "0")], "999")),
]


def main():
    print("=" * 60)
    print("FIX Message Parser — Golden Vector Summary")
    print("=" * 60)

    max_len = 0
    for i, (name, (raw, exp)) in enumerate(tests):
        ml = len(raw)
        max_len = max(max_len, ml)
        print(f"  [{i:2d}] {name:20s}  len={ml:3d}  seq={exp['msg_seq_num']:>10d}")

    print(f"\n  Total: {len(tests)} tests,  max len: {max_len} bytes\n")

    print("// Verilog golden vectors")
    print(f"localparam NUM_TESTS = {len(tests)};")
    print(f"localparam MAX_MSG_LEN = {max_len};\n")

    for i, (name, (raw, exp)) in enumerate(tests):
        print(f"// Test {i}: {name} ({len(raw)} bytes)")
        print(f"test_msg_len[{i}] = {len(raw)};")
        print(f"exp_msg_type[{i}] = 8'h{exp['msg_type']:02X};")
        print(f"exp_sender_id[{i}] = 64'h{exp['sender_id']:016X};")
        print(f"exp_msg_seq_num[{i}] = 32'd{exp['msg_seq_num']};")
        for j, b in enumerate(raw):
            print(f"test_data[{i}][{j}] = 8'h{b:02X};", end="  ")
            if (j + 1) % 8 == 0:
                print()
        print("\n")


if __name__ == "__main__":
    main()
