#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""从中国福彩官网拉取最新双色球开奖，合并进主数据集（只增不改）。

为什么要它：预测挑战的判定必须建立在**最新**的全量数据上；每期开奖后跑一次即可。

数据来源：中国福利彩票官网 开奖公告接口（官方）
    https://www.cwl.gov.cn/cwl_admin/front/cwlkj/search/kjxx/findDrawNotice?name=ssq&issueCount=N

用法：
    python 更新开奖数据.py            # 拉最近 30 期，补齐缺的
    python 更新开奖数据.py --count 5
    python 更新开奖数据.py --dry-run  # 只看会加什么，不落盘

落盘前会自动备份为 ssq_history_parsed.csv.bak-<时间戳>。
"""

from __future__ import annotations

import argparse
import csv
import json
import shutil
import sys
import urllib.request
from datetime import datetime
from pathlib import Path

HERE = Path(__file__).resolve().parent
DATA = HERE / "_C3_evidence" / "ssq_history_parsed.csv"
API = ("https://www.cwl.gov.cn/cwl_admin/front/cwlkj/search/kjxx/findDrawNotice"
       "?name=ssq&issueCount={n}")
HEADER = ["期号", "r1", "r2", "r3", "r4", "r5", "r6", "蓝球", "奖池",
          "一等奖注数", "一等奖单注奖金", "二等奖注数", "二等奖单注奖金",
          "总投注额", "开奖日期"]


def fetch(count: int) -> list[dict]:
    req = urllib.request.Request(API.format(n=count), headers={
        "User-Agent": "Mozilla/5.0",
        "Referer": "https://www.cwl.gov.cn/ygkj/wqkjgg/",
    })
    with urllib.request.urlopen(req, timeout=30) as resp:
        payload = json.loads(resp.read().decode("utf-8"))
    if payload.get("state") != 0:
        raise RuntimeError(f"官方接口返回异常：{payload.get('message')}")
    return payload.get("result") or []


def grade(item: dict, level: int) -> tuple[int, int]:
    """取某一等奖级的 (注数, 单注奖金)；官方缺失时返回 (0, 0)。"""
    for g in item.get("prizegrades") or []:
        if int(g.get("type") or 0) == level:
            n = int(str(g.get("typenum") or "0").replace(",", "") or 0)
            money = int(str(g.get("typemoney") or "0").replace(",", "") or 0)
            return n, money
    return 0, 0


def to_row(item: dict) -> list[str]:
    """官方 JSON → 本数据集的一行（金额带千分位，与既有文件风格一致）。"""
    issue = norm_issue(item["code"])
    reds = [f"{int(x):02d}" for x in str(item["red"]).split(",")]
    blue = f"{int(item['blue']):02d}"
    first_n, first_prize = grade(item, 1)
    second_n, second_prize = grade(item, 2)
    date = str(item["date"]).split("(")[0]
    sales = int(str(item.get("sales") or "0").replace(",", "") or 0)
    pool = int(str(item.get("poolmoney") or "0").replace(",", "") or 0)
    return [issue, *reds, blue,
            f"{pool:,}", str(first_n), f"{first_prize:,}",
            str(second_n), f"{second_prize:,}", f"{sales:,}", date]


def norm_issue(code: object) -> str:
    """统一期号格式：本数据集用 5 位（YY + 三位期序，如 2026 年第 108 期 = 26108），
    官方接口给的是 7 位（2026108）。不统一就会把同一期当成两期、重复入库。"""
    s = str(code).strip()
    if len(s) == 7 and s.startswith("20"):
        return s[2:]
    return s


def main() -> int:
    try:
        sys.stdout.reconfigure(encoding="utf-8", errors="replace")
    except Exception:
        pass

    ap = argparse.ArgumentParser()
    ap.add_argument("--count", type=int, default=30, help="向官方接口请求最近多少期")
    ap.add_argument("--dry-run", action="store_true", help="只打印，不写文件")
    args = ap.parse_args()

    if not DATA.exists():
        print(f"找不到数据集：{DATA}")
        return 2

    # 读取时保留原始文本，避免把 CRLF 顺手改成 LF（那会让对外公布的指纹变掉）
    raw = DATA.read_bytes().decode("utf-8")
    lines = raw.split("\r\n") if "\r\n" in raw else raw.split("\n")
    head, body = lines[0], [ln for ln in lines[1:] if ln.strip()]
    have = {ln.split(",", 1)[0] for ln in body}

    items = fetch(args.count)
    fresh = [it for it in items if norm_issue(it["code"]) not in have]
    if not fresh:
        print(f"数据已是最新（{len(body)} 期，最新 {body[0].split(',')[0]}）")
        return 0

    new_rows = []
    for it in fresh:
        row = to_row(it)
        print(f"新增 {row[0]}  {row[14]}  {' '.join(row[1:7])} + {row[7]}")
        new_rows.append(",".join(
            [row[0], *row[1:8], f'"{row[8]}"', row[9], f'"{row[10]}"',
             row[11], f'"{row[12]}"', f'"{row[13]}"', row[14]]))

    # 数据集按"新→旧"排列，新行插到最前面
    merged = [head] + new_rows + body
    if args.dry_run:
        print("\n--dry-run：未写盘。以上行会插到数据集最前面。")
        return 0

    stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
    backup = DATA.with_suffix(DATA.suffix + f".bak-{stamp}")
    shutil.copy2(DATA, backup)
    DATA.write_bytes("\r\n".join(merged).encode("utf-8"))
    print(f"\n已写入 {DATA.name}：{len(body)} → {len(merged) - 1} 期；备份 {backup.name}")
    return 0


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