# -*- 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 PIL import Image,ImageDraw
versions=[{'id':'v0','parent':None,'response_id':'resp_synthetic_0','image':'v0.png','intent':'原始蓝方块'},{'id':'v1','parent':'v0','response_id':'resp_synthetic_1','image':'v1.png','intent':'改为绿色'},{'id':'v2','parent':'v0','response_id':'resp_synthetic_2','image':'v2.png','intent':'改为圆形'}]
for v,color in zip(versions,['blue','green','orange']):
    if not (BASE/v['image']).exists():
        im=Image.new('RGBA',(64,64),'white');d=ImageDraw.Draw(im)
        if v['id']=='v2':d.ellipse((12,12,52,52),fill=color)
        else:d.rectangle((12,12,52,52),fill=color)
        im.save(BASE/v['image'])
    v['sha256']=hashlib.sha256((BASE/v['image']).read_bytes()).hexdigest()
jseed('versions.json',versions);versions=load('versions.json')
for version in versions:
    file=BASE/version['image']
    if not file.exists():raise FileNotFoundError('版本源图缺失：'+version['image'])
    if hashlib.sha256(file.read_bytes()).hexdigest()!=version['sha256']:raise ValueError('版本源图摘要变化，请另建版本，不覆盖历史')
lookup={v['id']:v for v in versions};selected='v0';requests=[]
for child in ['v1','v2']:
    parent=lookup[lookup[child]['parent']]
    if NEG and child=='v2':parent={'id':'missing','image':'missing.png'}
    if not (BASE/parent['image']).exists():raise ValueError('父版本原图缺失，不能继续编辑')
    requests.append({'local_child':child,'model':'REPLACE_SUPPORTED_MODEL','previous_response_id':parent['response_id'],'input':lookup[child]['intent'],'tools':[{'type':'image_generation','action':'edit'}]})
jwrite('unsent-requests.json',requests);page('version-tree.html','图像版本分叉','<p>v1 与 v2 都来自 v0。以下为本地合成图片，不是模型效果。</p>'+''.join(f'<figure><img src="{v["image"]}" width="160"><figcaption>{html.escape(v["id"]+": "+v["intent"])}，父版本 {v["parent"]}</figcaption></figure>' for v in versions));emit({'parents':{v['id']:v['parent'] for v in versions},'request_parent_ids':[r['previous_response_id'] for r in requests]})
