#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""数据层修复转换器 v2b：两阶段——先收集再批量 UPDATE
修复 v2 的 bug：SELECT 游标迭代期间 commit/BEGIN 会重置游标导致截断。
v2b: 阶段1 全表 fetchmany 只读收集 → 阶段2 executemany 批量 UPDATE。
"""
import sqlite3, re, sys

MD_LINK_RE = re.compile(r'\[([^\]]{1,200})\]\((https?://[^)\s]+)\)')
MD_IMG_RE = re.compile(r'!\[([^\]]*)\]\((https?://[^)\s]+)\)')


def md_table_to_html(text):
    lines = text.split('\n')
    out = []
    i = 0
    n = len(lines)
    while i < n:
        line = lines[i]
        m = re.match(r'^\s*\|(.+)\|\s*$', line)
        if m and '|' in m.group(1):
            rows = []
            j = i
            while j < n:
                mm = re.match(r'^\s*\|(.+)\|\s*$', lines[j])
                if mm and '|' in mm.group(1):
                    rows.append(lines[j])
                    j += 1
                else:
                    break
            if len(rows) >= 2:
                parsed = []
                for r in rows:
                    cells = [c.strip() for c in r.strip().strip('|').split('|')]
                    if all(re.match(r'^:?-{2,}:?$', c) for c in cells if c):
                        continue
                    parsed.append(cells)
                if parsed:
                    trs = []
                    for cells in parsed:
                        tds = ''.join(f'<td>{md_inline_to_html(c)}</td>' for c in cells)
                        trs.append(f'<tr>{tds}</tr>')
                    tbl = '<table><tbody>' + ''.join(trs) + '</tbody></table>'
                    out.append(tbl)
                    i = j
                    continue
        out.append(line)
        i += 1
    return '\n'.join(out)


def md_inline_to_html(cell):
    cell = MD_IMG_RE.sub(lambda m: f'<img src="{m.group(2)}" alt="{m.group(1)}">', cell)
    cell = MD_LINK_RE.sub(lambda m: f'<a href="{m.group(2)}">{m.group(1)}</a>', cell)
    cell = re.sub(r'\*\*([^*]+)\*\*', r'<strong>\1</strong>', cell)
    return cell


def content_to_html(content):
    content = md_table_to_html(content)
    content = MD_IMG_RE.sub(lambda m: f'<img src="{m.group(2)}" alt="{m.group(1)}">', content)
    lines = content.split('\n')
    new_lines = []
    for line in lines:
        m = re.match(r'^\s*\[([^\]]{1,200})\]\((https?://[^)\s]+)\)\s*$', line)
        if m:
            new_lines.append(f'<p><a href="{m.group(2)}">{m.group(1)}</a></p>')
        else:
            new_lines.append(MD_LINK_RE.sub(lambda m2: f'<a href="{m2.group(2)}">{m2.group(1)}</a>', line))
    return '\n'.join(new_lines)


def main():
    dry = '--dry' in sys.argv
    conn = sqlite3.connect("/root/search.db", timeout=60)
    conn.execute("PRAGMA busy_timeout=60000")
    conn.execute("PRAGMA journal_mode=WAL")
    c = conn.cursor()

    c.execute("SELECT COUNT(*) FROM gov_raw")
    total = c.fetchone()[0]
    print(f"总行数: {total}", flush=True)

    # 阶段1：只读收集需要更新的记录
    updates = []
    errors = 0
    c.execute("SELECT rowid, site_name, content, summary FROM gov_raw")
    while True:
        rows = c.fetchmany(10000)
        if not rows:
            break
        for rowid, site, content, summary in rows:
            if content is None:
                continue
            if not ('|' in content or '](http' in content or '![http' in content or ':---' in content):
                continue
            try:
                new_content = content_to_html(content)
                new_summary = summary
                if summary and '](http' in summary:
                    new_summary = MD_LINK_RE.sub(
                        lambda m: f'<a href="{m.group(2)}">{m.group(1)}</a>', summary)
                if new_content != content or new_summary != summary:
                    updates.append((new_content, new_summary, rowid))
            except Exception as e:
                errors += 1
                print(f"  ❌ rowid {rowid}: {e}", flush=True)
        print(f"  已扫描, 收集 {len(updates)} 条...", flush=True)
    print(f"收集完成: {len(updates)} 条待更新 / 错误 {errors}", flush=True)

    # 阶段2：批量 UPDATE
    if not dry:
        conn.execute("BEGIN")
        for i in range(0, len(updates), 5000):
            batch = updates[i:i + 5000]
            c.executemany("UPDATE gov_raw SET content=?, summary=? WHERE rowid=?", batch)
            conn.commit()
            print(f"  已写入 {i + len(batch)} ...", flush=True)
    conn.close()
    print(f"\n=== 完成 === (dry={dry}) 更新: {len(updates)}")


if __name__ == '__main__':
    main()
