#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""浙江清单补齐：坐标窗口解析（覆盖联合基金/地区科学基金尾部章节）
与 pdfplumber 线框结果按序号合并 → 校验 2667
"""
import csv
import io
import re
from collections import defaultdict

import pdfplumber

BASE = '/Users/liuxinyuan/Desktop/Hermes输出-工作类/销售分析/基金源文件'
ZJ = BASE + '/浙江_2026省自然科学基金拟资助项目清单.pdf'


def band(ws, lo, hi, top):
    return ''.join(w['text'] for w in ws if lo <= w['x0'] < hi and abs(w['top'] - top) < 3)


def parse_page(pg):
    ws = pg.extract_words()
    # 按 y 聚类
    rows = defaultdict(list)
    for w in ws:
        rows[round(w['top'] / 2.5)].append(w)
    lines = []
    for k in sorted(rows):
        it = sorted(rows[k], key=lambda z: z['x0'])
        top = it[0]['top']
        lines.append((top, {
            'no': ''.join(w['text'] for w in it if 55 <= w['x0'] < 88),
            'name': ''.join(w['text'] for w in it if 88 <= w['x0'] < 290),
            'code': ''.join(w['text'] for w in it if 290 <= w['x0'] < 348),
            'pi': ''.join(w['text'] for w in it if 348 <= w['x0'] < 382),
            'unit': ''.join(w['text'] for w in it if 382 <= w['x0'] < 445),
            'cat': ''.join(w['text'] for w in it if 445 <= w['x0'] < 483),
            'funder': ''.join(w['text'] for w in it if w['x0'] >= 483),
        }))
    anchors = [i for i, (t, r) in enumerate(lines) if re.fullmatch(r'\d{3,4}', r['no'] or '')]
    out = []
    for k, i in enumerate(anchors):
        t = lines[i][0]
        lo = (lines[anchors[k - 1]][0] + t) / 2 if k else 0
        hi = (t + lines[anchors[k + 1]][0]) / 2 if k + 1 < len(anchors) else 10 ** 6
        win = [r for (tt, r) in lines if lo <= tt < hi]
        rec = {
            'no': lines[i][1]['no'],
            'name': ''.join(r['name'] for r in win),
            'code': ''.join(r['code'] for r in win),
            'pi': ''.join(r['pi'] for r in win),
            'unit': ''.join(r['unit'] for r in win),
            'cat': ''.join(r['cat'] + r['funder'] for r in win),
        }
        if rec['code']:
            out.append(rec)
    return out


coord = []
with pdfplumber.open(ZJ) as pdf:
    for pg in pdf.pages:
        coord.extend(parse_page(pg))
print('█ 坐标解析:', len(coord), '项')

# 读线框解析结果
tab = []
with io.open(BASE + '/parsed/浙江_2026省基金_明细.csv', encoding='utf-8-sig') as f:
    tab = list(csv.DictReader(f))
print('█ 线框解析:', len(tab), '项')

# 合并：以序号为键，线框优先
merged = {r['no']: r for r in coord}
for r in tab:
    merged[r['no']] = r
rows = sorted(merged.values(), key=lambda r: int(r['no']) if r['no'].isdigit() else 9999)
print('█ 合并后:', len(rows), '项（校验 2667）')
print('   类别:', {k: sum(1 for r in rows if k in r['cat']) for k in ('重大', '杰青', '重点', '探索', '青基', '联合', '青稞', '地区')})

with io.open(BASE + '/parsed/浙江_2026省基金_明细.csv', 'w', encoding='utf-8-sig', newline='') as f:
    w = csv.DictWriter(f, fieldnames=['no', 'name', 'code', 'pi', 'unit', 'cat'])
    w.writeheader(); w.writerows(rows)
print('✅ 已回写 CSV')
