#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Triage 20261030 candidate pool from 4 sources."""
import json, io, os, re, datetime, html
from collections import Counter

BASE = "/data/www/files"
START = datetime.date(2026, 9, 30)
END = datetime.date(2026, 10, 30)

CORE_KW = ["党校", "干部学院", "行政学院", "干部教育", "干部培训", "党员教育", "党建",
           "组织部", "党群", "融媒体", "展陈", "展览", "布展", "陈列", "宣传片", "专题片",
           "纪录片", "微短剧", "宣传视频", "视频拍摄", "视频制作", "课件", "微课", "课程",
           "智慧校园", "教育信息化", "思政", "红色", "纪念馆", "廉政", "廉洁", "培训",
           "能力提升", "信息化", "数字化", "智慧", "直播", "录制", "演播", "摄制",
           "文化馆", "文史", "宣传", "平台建设", "系统建设", "运维", "新媒体", "教育基地"]
NOISE = ["印刷", "复印纸", "打印纸", "食堂", "餐饮", "食材", "配餐", "家具", "空调",
         "物业", "保洁", "桌椅", "宿舍", "床上用品", "被褥", "后勤用品", "办公耗材",
         "医疗设备", "药品", "疫苗", "试剂", "车辆", "加油", "保险", "绿化", "苗木",
         "污水处理", "道路", "路灯", "管网", "取暖", "煤", "安保", "消防维保",
         "电梯", "垃圾", "化肥", "饲料", "种公畜", "藏羊", "牛", "羊", "地勘",
         "皮卡", "货车", "多功能一体机", "复印机", "计算机采购", "打印机", "扫描仪",
         "血液透析", "影像设备", "白大褂", "工作服", "健身器材", "体育器材", "玩具",
         "窗帘", "门头", "标牌", "广告", "体检", "健康体检", "审计服务", "法律服务",
         "慰问品", "投诉处理", "决定书", "预留项目", "框架协议", "硒鼓", "医共体",
         "招租", "转让", "报废", "废旧", "供水", "供电", "排水", "桥梁", "隧道",
         "水库", "河道", "灌溉", "棚改", "安置", "老旧小区", "养护", "维修维护",
         "视频监控", "污染源", "人工影响天气", "卫生", "急救", "巡回医疗",
         "森林草原", "应急抢险", "自然资源", "城中村", "公开招聘", "招标代理",
         "监理", "造价咨询", "工程结算", "环评", "勘测"]


def parse_d(s):
    if not s:
        return None
    m = re.search(r"(20\d{2})[-/年.](\d{1,2})[-/月.](\d{1,2})", s)
    if not m:
        return None
    try:
        return datetime.date(int(m.group(1)), int(m.group(2)), int(m.group(3)))
    except Exception:
        return None


def clean(t):
    t = re.sub(r"<[^>]+>", "", t or "")
    return html.unescape(t).strip()


def norm_budget(b):
    if b is None or b == "":
        return "未披露"
    try:
        v = float(str(b).replace(",", "").replace("元", "").strip())
    except Exception:
        return "未披露"
    if v <= 0:
        return "未披露"
    if v > 10000:
        v = v / 10000.0
    return round(v, 2)


cands = []
seen = set()


def add(title, buyer, budget, pub, url, source, ptype, prov, content=""):
    title = clean(title)
    if not title or not url or not url.startswith("http"):
        return
    key = title[:26] + "|" + url.split("?")[0][-24:]
    if key in seen:
        return
    if not any(k in title for k in CORE_KW):
        return
    if any(n in title for n in NOISE):
        return
    d = parse_d(pub)
    if d and (d < START or d > END):
        return
    seen.add(key)
    cands.append({"title": title, "buyer": clean(buyer), "budget": budget,
                  "pub_date": pub or "", "url": url, "source": source, "type": ptype,
                  "province": prov, "content": (content or "")[:8000]})


# ---- 1. Sichuan ----
raw = json.load(io.open(os.path.join(BASE, "ggzy_raw_1030.json"), encoding="utf-8"))
CATMAP = {"002002001": "招标公告", "002002003": "中标公告"}
for u, v in (raw.get("records") or {}).items():
    cat = v.get("cat")
    if cat not in CATMAP:
        continue
    if u.startswith("/"):
        u = "https://ggzyjy.sc.gov.cn" + u
    add(v.get("title"), "", "未披露", v.get("date"), u,
        "四川省公共资源交易信息网", CATMAP[cat], "四川", v.get("content") or "")

# ---- 2. Gansu ----
GMAP = {"001011": "招标公告", "001016": "招标公告", "001021": "中标公告",
        "001026": "中标公告", "001006": "中标公告", "59": "意向公开",
        "001051": "单一来源公示", "001031": "招标公告", "001033": "中标公告"}
gp = os.path.join(BASE, "gansu_raw_1030.json")
if os.path.exists(gp):
    for _, r in json.load(io.open(gp, encoding="utf-8")).items():
        nt = r.get("noticeType") or ""
        if nt not in GMAP:
            continue
        url = "https://www.ccgp-gansu.gov.cn/maincms-web/articleGs?type=article&id=" + r["id"]
        add(r.get("title"), r.get("purchaser"), norm_budget(r.get("budget")),
            (r.get("noticeTime") or "")[:10], url, "甘肃省政府采购网", GMAP[nt],
            "甘肃", r.get("desc") or "")

# ---- 3. Chongqing ----
KEEP_CQ = ("政府采购>采购公告", "政府采购>单一来源公示", "阳光采购>招标采购公告",
           "中介超市>采购公告", "工程招投标>招标计划", "政府采购>采购结果公告",
           "工程招投标>中标结果公告", "工程招投标>招标公告")
cp = os.path.join(BASE, "cq_raw_1030.json")
if os.path.exists(cp):
    for r in json.load(io.open(cp, encoding="utf-8")):
        ty = r.get("type") or ""
        if ty not in KEEP_CQ:
            continue
        t = r.get("title", "")
        if t.startswith("关于为【") and any(k in t for k in ("招标代理", "监理", "造价", "审计", "物业")):
            continue
        ptype = "招标公告"
        if "结果公告" in ty or "中选公告" in ty or "中标结果" in ty:
            ptype = "中标公告"
        elif "单一来源" in ty:
            ptype = "意向公开"
        add(t, r.get("buyer"), norm_budget(r.get("budget")), r.get("pub_date"), r.get("url"),
            "重庆市公共资源交易网", ptype, "重庆", "")

# ---- 4. National platform ----
np_ = os.path.join(BASE, "ggzy_nat_raw_1030.json")
if os.path.exists(np_):
    for r in json.load(io.open(np_, encoding="utf-8")):
        t = r.get("title", "")
        if t.endswith(".BZBJ") or "澄清" in t or "答疑" in t or "更正" in t:
            continue
        ty = r.get("type") or ""
        if ty == "工程建设" and not any(k in t for k in ("党校", "党建", "党员教育", "展陈", "布展")):
            continue
        prov = (r.get("province") or "").replace("省", "").replace("壮族自治区", "").replace("自治区", "")
        add(t, "", "未披露", (r.get("pub_date") or "")[:10], r.get("url"),
            "全国公共资源交易平台(ggzy.gov.cn)", "招标公告", prov, r.get("kws") and "")

print("candidates:", len(cands))
print(Counter(c["province"] for c in cands))
print(Counter(c["source"] for c in cands))
json.dump(cands, io.open(os.path.join(BASE, "cand_pool_1030.json"), "w", encoding="utf-8"),
          ensure_ascii=False, indent=1)
for c in sorted(cands, key=lambda x: (x["province"], x["pub_date"])):
    print("%-6s | %-10s | %-9s | %-56s | %s" % (
        c["province"], c["type"], c["budget"], c["title"][:56], c["pub_date"]))
