# -*- coding: utf-8 -*-
"""原创离线合成样例；不连接模型、不读取账户。输出位于脚本旁。
已有输入保留，修改输入后可以重跑。失败边界由 --negative 单独演示。
"""
from pathlib import Path
import sys, json, csv, math, io, hashlib, html, base64, re
sys.stdout.reconfigure(encoding='utf-8')
sys.stderr.reconfigure(encoding='utf-8')
BASE = Path(__file__).resolve().parent
NEG = '--negative' in sys.argv
def write(name, value):
    p=BASE/name; p.parent.mkdir(parents=True,exist_ok=True)
    if isinstance(value,bytes): p.write_bytes(value)
    else: p.write_text(value,encoding='utf-8',newline='')
def seed(name,value):
    if not (BASE/name).exists(): write(name,value)
def jwrite(name,value): write(name,json.dumps(value,ensure_ascii=False,indent=2))
def jseed(name,value):
    if not (BASE/name).exists(): jwrite(name,value)
def load(name): return json.loads((BASE/name).read_text(encoding='utf-8'))
def table(name,heads,rows):
    f=io.StringIO(newline='');w=csv.writer(f);w.writerow(heads);w.writerows(rows);write(name,f.getvalue())
def page(name,title,body):
    write(name,'<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>'+html.escape(title)+'</title><style>body{max-width:1000px;margin:2rem auto;padding:0 1rem;font:17px/1.7 system-ui}table{border-collapse:collapse}td,th{border:1px solid #aaa;padding:.5rem}pre{white-space:pre-wrap;overflow-wrap:anywhere}img,svg{max-width:100%;height:auto}a{color:#125caa}</style><h1>'+html.escape(title)+'</h1>'+body+'</html>')
def emit(data): print(json.dumps(data,ensure_ascii=False))

import fitz
if not (BASE/'five-pages.pdf').exists():
    doc=fitz.open()
    for i in range(5):
        p=doc.new_page(width=400,height=500);p.insert_text((30,25),'SYNTHETIC REPORT',fontsize=10);p.insert_text((30,110),f'Chapter {i+1}: body content.',fontsize=12);p.insert_text((30,180),'SYNTHETIC REPORT appears in body too.',fontsize=10);p.insert_text((30,480),f'Page {i+1}',fontsize=10)
    doc.save(BASE/'five-pages.pdf');doc.close()
doc=fitz.open(BASE/'five-pages.pdf');records=[]
for pi,p in enumerate(doc):
    for block in p.get_text('blocks'):
        x0,y0,x1,y1,text,*_=block;zone='top' if y1<50 else ('bottom' if y0>450 else 'body');norm=re.sub(r'Page \d+','Page #',text.strip());records.append({'page':pi+1,'zone':zone,'text':text.strip(),'norm':norm,'rect':[x0,y0,x1,y1]})
candidates={r['norm'] for r in records if r['zone']!='body' and len({z['page'] for z in records if z['norm']==r['norm'] and z['zone']==r['zone']})/len(doc)>=.8}
if NEG: candidates.add('Chapter 1: body content.')
accepted=candidates & {'SYNTHETIC REPORT','Page #'}
table('margin-candidates.csv',['page','zone','text','proposed','confirmed'],[[r['page'],r['zone'],r['text'],r['norm'] in candidates,r['norm'] in accepted and r['zone']!='body'] for r in records])
clean=[]
for pi,p in enumerate(doc):
    clean.append(f'--- page_id={pi+1} ---')
    for r in [r for r in records if r['page']==pi+1]:
        if r['zone']!='body' and r['norm'] in accepted: p.draw_rect(fitz.Rect(r['rect']),color=(1,0,0),width=1)
        else: clean.append(r['text'])
    if pi==0:p.get_pixmap().save(BASE/'marked-preview.png')
write('clean-reading.txt','\n'.join(clean));emit({'confirmed':sorted(accepted),'body_same_words_preserved':sum('appears in body' in s for s in clean),'unconfirmed_body_candidate':NEG})
