#!/usr/bin/env python3
"""三动态 case 批：H3无损单采 × case08(高)/case07(中)/case06(低)
15s 满长片=360帧(17n+5吸附), 冒烟期四轴已过, 本批唯一变量=case 难度。
"""
import json, sys, copy, urllib.request, urllib.error

BASE = json.load(open('/home/kai/shared/2026-10-17/h3_lossless_fusion_api.json'))

def grid_len(dur_s: float) -> int:
    L = max(5, round(dur_s * 24))
    return L + (5 - (L % 17)) % 17

def build(case: str, dur_s: float, prompt: str, seed: int, out_prefix: str,
          ref_files: list):
    api = copy.deepcopy(BASE)
    api['227']['inputs']['value'] = dur_s
    api['136']['inputs']['length'] = grid_len(dur_s)
    # FIX(满长批三连败真根因): BASE 的 136.w/h=1344x1792 竖屏2.4MP字面量(228 ResolutionSelector
    # 在API图也是孤儿), 362f→272k tokens爆OOM。统一钉在冒烟已验包络 960x544。
    api['136']['inputs']['width'] = 960
    api['136']['inputs']['height'] = 544
    api['238']['inputs']['value'] = prompt
    api['129']['inputs']['noise_seed'] = seed
    api['148']['inputs']['filename_prefix'] = out_prefix
    mapping = [('199','ref_images.ref_image_0'), ('188','ref_images.ref_image_1'),
               ('189','ref_images.ref_image_2'), ('190','ref_images.ref_image_3'),
               ('191','ref_images.ref_image_4'), ('192','ref_images.ref_image_5')]
    # 先全部断链 ref 槽
    for nid, key in mapping:
        api['136']['inputs'].pop(key, None)
    # 重新布线
    node_ids = ['199','188','189','190','191','192']
    for i, fname in enumerate(ref_files):
        nid, key = mapping[i]
        if fname:
            api[nid]['inputs'] = {'image': fname}
            api['136']['inputs'][key] = [nid, 0]
        else:
            api.pop(nid, None)
    return api

def submit(api, port=8190):
    body = json.dumps({'prompt': api, 'client_id': 'h3lossless'}).encode()
    req = urllib.request.Request(f'http://127.0.0.1:{port}/prompt', data=body,
                                 headers={'Content-Type': 'application/json'})
    try:
        r = urllib.request.urlopen(req, timeout=120)
        return json.loads(r.read().decode())
    except urllib.error.HTTPError as e:
        return {'ERROR': json.loads(e.read().decode())}

CASES = {
    'case08': dict(dur_s=15.0, seed=20261017,
                   refs=['h3lossless/case08/ref0.jpg','h3lossless/case08/ref1.jpg',
                         'h3lossless/case08/scene.png',None,None,None],
                   pfile='/home/kai/文档/LTX/validition_v1/08/prompt.txt'),
    'case07': dict(dur_s=15.0, seed=20261017,
                   refs=['h3lossless/case07/ref0.jpg','h3lossless/case07/ref1.jpg',
                         'h3lossless/case07/scene.png',None,None,None],
                   pfile='/home/kai/文档/LTX/validition_v1/07/prompt.txt'),
    'case06': dict(dur_s=15.0, seed=20261017,
                   refs=['h3lossless/case06/ref0.png','h3lossless/case06/ref1.png',
                         'h3lossless/case06/ref2.png','h3lossless/case06/scene.png',
                         None,None],
                   pfile='/home/kai/文档/LTX/validition_v1/06/prompt.txt'),
}

if __name__ == '__main__':
    target = sys.argv[1] if len(sys.argv) > 1 else None
    for case, cfg in CASES.items():
        if target and case != target:
            continue
        prompt = open(cfg['pfile']).read().replace('\r\n', ' ').strip()
        api = build(case, cfg['dur_s'], prompt, cfg['seed'],
                    f'h3lossless/full_{case}_15s', cfg['refs'])
        resp = submit(api)
        print(case, '->', json.dumps(resp, ensure_ascii=False)[:300])
        if 'prompt_id' in resp:
            json.dump(api, open(f'/home/kai/shared/2026-10-17/h3lossless/api_full_{case}_15s.json','w'),
                      ensure_ascii=False, indent=1)
