# -*- 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
im=Image.new('RGB',(180,100),'white');ImageDraw.Draw(im).rectangle((25,30,130,80),fill='#357cb0');buf=io.BytesIO();im.save(buf,format='PNG');raw=buf.getvalue()
jseed('interaction-fixture.json',{'fixture_only':True,'steps':[{'type':'model_output','content':[{'type':'text','text':'原创合成说明：下图为本地产生的矩形。'}]},{'type':'code_execution_call','arguments':{'code':'# fixture only; this code was not run by a model\nprint(12 + 18)'}},{'type':'code_execution_result','is_error':False,'result':'30'},{'type':'model_output','content':[{'type':'image','mime_type':'image/png','data':base64.b64encode(raw).decode()}]}]});data=load('interaction-fixture.json')
if NEG:data['steps'][2]={'type':'code_execution_result','is_error':True,'result':'Synthetic execution failure'}
body=['<p>此包消费合成响应，代码片段不代表执行服务已运行。</p>'];images=[]
for i,step in enumerate(data['steps']):
    body.append('<h2>'+html.escape(step['type'])+'</h2>')
    if step['type']=='code_execution_call':body.append('<pre>'+html.escape(step.get('arguments',{}).get('code',''))+'</pre>')
    elif step['type']=='code_execution_result':body.append('<p>'+('执行失败：' if step.get('is_error') else '合成执行结果：')+html.escape(step.get('result',''))+'</p>')
    elif step['type']=='model_output':
        for j,c in enumerate(step['content']):
            if c['type']=='text':body.append('<p>'+html.escape(c['text'])+'</p>')
            elif c['type']=='image':
                if c.get('mime_type')!='image/png':raise ValueError('本例只导出PNG块')
                content=base64.b64decode(c['data'],validate=True);Image.open(io.BytesIO(content)).verify();name=f'step-{i}-image-{j}.png';write('analysis-pack/'+name,content);images.append({'file':name,'sha256':hashlib.sha256(content).hexdigest()});body.append(f'<img src="{name}" alt="原创合成矩形图">')
page('analysis-pack/index.html','离线分析结果包',''.join(body));jwrite('media-manifest.json',images);emit({'images':images,'execution_failure_visible':NEG})
