# -*- 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))

from citeproc import CitationStylesStyle,CitationStylesBibliography,Citation,CitationItem
from citeproc.source.json import CiteProcJSON
from citeproc import formatter
jseed('references.json',[{'id':'alpha','type':'book','title':'Synthetic Alpha','author':[{'family':'Chen','given':'A'}],'issued':{'date-parts':[[2024]]}},{'id':'beta','type':'book','title':'Synthetic Beta','author':[{'family':'Lin','given':'B'}],'issued':{'date-parts':[[2025]]}}])
seed('draft.md','First statement [@alpha].\nSecond statement [@beta].\nRepeat [@alpha].\n')
style="""<?xml version="1.0" encoding="utf-8"?><style xmlns="http://purl.org/net/xbiblio/csl" version="1.0" class="in-text"><info><title>Original numeric example</title><id>https://example.invalid/styles/original</id><updated>2026-10-24T00:00:00+00:00</updated></info><citation><layout prefix="[" suffix="]"><text variable="citation-number"/></layout></citation><bibliography><layout suffix="."><text variable="citation-number" suffix=". "/><text variable="title"/></layout></bibliography></style>"""
seed('numeric.csl',style);refs=load('references.json');draft=(BASE/'draft.md').read_text(encoding='utf-8');keys=re.findall(r'\[@([^]]+)\]',draft)
if NEG: keys.append('unknown')
ids=[r['id'] for r in refs]
if len(ids)!=len(set(ids)) or any(k not in ids for k in keys) or any(not r.get('title') for r in refs): raise ValueError('引用键缺失、重复或缺标题')
def render(keys):
    bibliography=CitationStylesBibliography(CitationStylesStyle(str(BASE/'numeric.csl')),CiteProcJSON(refs),formatter.html);citations=[Citation([CitationItem(k)]) for k in keys]
    for citation in citations:bibliography.register(citation)
    labels=[str(bibliography.cite(c,lambda x:None)) for c in citations];entries=[str(x) for x in bibliography.bibliography()];return labels,entries
labels,entries=render(keys);reordered,_=render([keys[1],keys[0],keys[2]])
page('references.html','稳定引用键生成书目','<h2>正文顺序</h2><pre>'+html.escape('\n'.join(f'{k}: {v}' for k,v in zip(keys,labels)))+'</pre><h2>参考文献</h2><ol>'+''.join('<li>'+x+'</li>' for x in entries)+'</ol>');jwrite('reordered.json',{'keys':[keys[1],keys[0],keys[2]],'labels':reordered});emit({'labels':labels,'entries':entries,'reordered':reordered})
