# -*- coding: utf-8 -*-
"""
JV-Link O1 生レコードをファイルに書き出す（目視・件数確認用）

- o1_raw_index.txt  : 全 O1 のレースキー一覧 + オッズ値あり/なし
- o1_raw_sample.txt : 先頭3件 + オッズあり1件 + オッズなし1件 の生文字列

編集: FROM_TO / OPTION
実行: venv32\\Scripts\\python.exe dump_o1_raw.py
"""
from __future__ import annotations

import platform
import sys
import time

FROM_TO = "20260101000000-20260611000000"
OPTION = 4
BUFSIZE = 300000
PROGIDS = ("JVDTLab.JVLink", "JVDTLabLib.JVLink")
INDEX_PATH = "o1_raw_index.txt"
SAMPLE_PATH = "o1_raw_sample.txt"


def _race_key(raw: str) -> str:
    return raw[11:27] if len(raw) >= 27 else "?"


def _fmt_key(k: str) -> str:
    if len(k) < 16:
        return k
    return f"{k[0:4]}/{k[4:6]}/{k[6:8]} 場{k[8:10]} {k[10:12]}回{k[12:14]}日 {k[14:16]}R"


def _o1_has_tanodds(raw: str) -> bool:
    hdr, bpc = 43, 8
    if len(raw) < hdr + bpc:
        return False
    data = raw[hdr:]
    for i in range(0, len(data) - bpc + 1, bpc):
        odds_s = data[i + 2 : i + 6].strip()
        if odds_s and odds_s.strip("0"):
            try:
                if int(odds_s) > 0:
                    return True
            except ValueError:
                pass
    return False


def _dispatch(win32):
    for progid in PROGIDS:
        try:
            return win32.Dispatch(progid), progid
        except Exception:
            pass
    return None, ""


def main() -> None:
    if platform.architecture()[0] != "32bit":
        print("ERROR: venv32\\Scripts\\python.exe を使う")
        sys.exit(1)
    import win32com.client as win32

    jv, progid = _dispatch(win32)
    if jv is None:
        print("ERROR: JV-Link COM を開けない")
        sys.exit(1)
    print("ProgID:", progid)

    if jv.JVInit("UNKNOWN") != 0:
        print("JVInit failed")
        sys.exit(1)

    r = jv.JVOpen("RACE", FROM_TO, OPTION, 0, 0, "")
    rc, readcount, dlcount = r[0], r[1], r[2]
    print(f"JVOpen rc={rc} read={readcount} dl={dlcount}")
    if rc < 0 or readcount == 0:
        jv.JVClose()
        sys.exit(1)

    while dlcount > 0:
        st = jv.JVStatus()
        if st < 0 or st >= dlcount:
            break
        time.sleep(1)

    records: list[tuple[str, str, bool]] = []
    ra_k7: set[str] = set()

    while True:
        r = jv.JVRead(" " * BUFSIZE, BUFSIZE, "")
        rc, data = r[0], r[1]
        if rc == 0:
            break
        if rc in (-1, -3):
            if rc == -3:
                time.sleep(1)
            continue
        if rc < 0:
            break
        if len(data) < 2:
            continue
        if data[:2] == "RA" and len(data) > 2 and data[2] == "7":
            ra_k7.add(_race_key(data))
        if data[:2] != "O1":
            continue
        key = _race_key(data)
        has = _o1_has_tanodds(data)
        records.append((key, data, has))

    jv.JVClose()

    with_odds = [x for x in records if x[2]]
    without = [x for x in records if not x[2]]
    o1_keys = {x[0] for x in records}

    with open(INDEX_PATH, "w", encoding="utf-8") as f:
        f.write(f"FROM_TO={FROM_TO}\n")
        f.write(f"O1 raw records: {len(records)}\n")
        f.write(f"  with odds bytes: {len(with_odds)}\n")
        f.write(f"  without odds bytes: {len(without)}\n")
        f.write(f"RA k7 races: {len(ra_k7)}\n")
        f.write(f"k7 without O1 record: {len(ra_k7 - o1_keys)}\n")
        f.write(f"O1 without odds value: {len(without)}\n")
        f.write("\n--- all O1 keys (key, has_odds) ---\n")
        for key, _, has in sorted(records, key=lambda x: x[0]):
            f.write(f"{_fmt_key(key)}\t{has}\n")

    samples: list[tuple[str, str]] = []
    for key, data, has in records[:3]:
        samples.append((f"head #{len(samples)+1} key={_fmt_key(key)} odds={has}", data))
    if with_odds:
        k, d, _ = with_odds[0]
        samples.append((f"with_odds key={_fmt_key(k)}", d))
    if without:
        k, d, _ = without[0]
        samples.append((f"without_odds key={_fmt_key(k)}", d))

    with open(SAMPLE_PATH, "w", encoding="utf-8") as f:
        f.write(f"FROM_TO={FROM_TO}\n\n")
        for title, data in samples:
            f.write("=" * 60 + "\n")
            f.write(title + "\n")
            f.write(f"len={len(data)} DataKubun={data[2:3]!r}\n")
            f.write("--- raw (repr, first 800 chars) ---\n")
            f.write(repr(data[:800]) + "\n")
            f.write("--- odds region from byte 43 (repr 200) ---\n")
            f.write(repr(data[43:243]) + "\n\n")

    print("")
    print(f"O1 raw records: {len(records)}")
    print(f"  with odds: {len(with_odds)}")
    print(f"  without:   {len(without)}")
    print(f"RA k7: {len(ra_k7)}  k7 missing O1: {len(ra_k7 - o1_keys)}")
    print("")
    print("Wrote:", INDEX_PATH, SAMPLE_PATH)
    print("")
    if len(without) == 0 and len(ra_k7 - o1_keys) == 0:
        print("=> ①欠落なし。JV-Link 生データは揃っている => ②展開側を疑う")
    elif len(ra_k7 - o1_keys) > 0:
        print(f"=> ① O1レコード自体が {len(ra_k7 - o1_keys)} レース欠落 => JV-Link側")
    elif len(without) > 0:
        print(f"=> ① O1はあるがオッズ値が空の塊が {len(without)} 件 => JV配信内容を確認")


if __name__ == "__main__":
    main()
