#!/usr/bin/env python3
"""Simulate a Dymind DH36 sending a CBC result over MLLP/HL7.

Lets you test the middleware end-to-end WITHOUT the physical analyzer.

Usage:
    python tools/simulate_analyzer.py --host 127.0.0.1 --port 5600 --barcode LR-2026-00259-1
"""

from __future__ import annotations

import argparse
import socket
import time

VT, FS, CR = b"\x0b", b"\x1c", b"\x0d"

# A representative DH36 CBC panel.
PARAMS = [
    ("WBC", "7.4", "10*3/uL", "N"),
    ("RBC", "5.10", "10*6/uL", "N"),
    ("HGB", "14.2", "g/dL", "N"),
    ("HCT", "42.1", "%", "N"),
    ("MCV", "82.5", "fL", "N"),
    ("MCH", "27.8", "pg", "N"),
    ("MCHC", "33.7", "g/dL", "N"),
    ("PLT", "250", "10*3/uL", "N"),
    ("MPV", "9.8", "fL", "N"),
]


def build_message(barcode: str) -> str:
    ts = time.strftime("%Y%m%d%H%M%S")
    segs = [
        f"MSH|^~\\&|DH36|LAB|LIS|LAB|{ts}||ORU^R01|MSG{ts}|P|2.3.1",
        "PID|1||MRN-000013||EMAD AHMED||19900101|M",
        f"OBR|1||{barcode}|CBC^Complete Blood Count|||{ts}",
    ]
    # Field layout: OBX-5 value, OBX-6 unit, OBX-8 abnormal flag, OBX-11 status.
    for i, (code, val, unit, flag) in enumerate(PARAMS, start=1):
        segs.append(f"OBX|{i}|NM|{code}^{code}||{val}|{unit}||{flag}|||F")
    return "\r".join(segs)


def main() -> int:
    ap = argparse.ArgumentParser(description="Dymind DH36 analyzer simulator")
    ap.add_argument("--host", default="127.0.0.1")
    ap.add_argument("--port", type=int, default=5600)
    ap.add_argument("--barcode", default="LR-2026-00259-1")
    args = ap.parse_args()

    message = build_message(args.barcode)
    frame = VT + message.encode("utf-8") + FS + CR

    print(f"connecting to {args.host}:{args.port} …")
    with socket.create_connection((args.host, args.port), timeout=10) as sock:
        sock.sendall(frame)
        print(f"sent CBC result for barcode {args.barcode} ({len(PARAMS)} params)")
        sock.settimeout(5)
        try:
            ack = sock.recv(4096)
            print("ACK:", ack.replace(VT, b"").replace(FS, b"").replace(CR, b" ").decode(errors="replace").strip())
        except socket.timeout:
            print("no ACK received (send_ack may be disabled)")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
