# -*- coding: utf-8 -*-
"""把上传的手抄报截图 → ①裁出海报本体 ②放大到 A4/300dpi 高清图 ③AI重绘高清版 ④线条图"""
import base64, io, json, os, time, requests
from PIL import Image, ImageEnhance, ImageFilter, ImageDraw, ImageFont
from concurrent.futures import ThreadPoolExecutor

CFG = json.load(open('/data/www/files/LhyjdesignPro/config.json'))
API_KEY, BASE, MODEL = CFG['api_key'], CFG['base_url'], CFG['models']['image_gen']
SRC = '/root/.hermes/webui/attachments/d7fb35486610/screenshot-1789268930955.jpeg'
OUT = '/data/www/files/pandaReadArt/convert'
os.makedirs(OUT, exist_ok=True)
FONT = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'

# ---------- ① 裁出海报本体（去掉边缘杂线 + 底部约6px桌面） ----------
im = Image.open(SRC).convert('RGB')
W, H = im.size
crop = im.crop((2, 1, W - 3, H - 7))          # 1144 x 812
CW, CH = crop.size
# 微调到 A4 横版比例 3508:2480 = 1.41452
target_ar = 3508 / 2480
if CW / CH > target_ar:
    nw = int(round(CH * target_ar)); x0 = (CW - nw) // 2
    crop = crop.crop((x0, 0, x0 + nw, CH))
else:
    nh = int(round(CW / target_ar)); y0 = (CH - nh) // 2
    crop = crop.crop((0, y0, CW, y0 + nh))
crop_path = os.path.join(OUT, '00_海报本体_裁切.jpg')
crop.save(crop_path, quality=97)
print(f'CROP  {crop.size}  aspect={crop.size[0]/crop.size[1]:.4f}')

# ---------- ② 放大到 A4/300dpi 并增强 ----------
hd = crop.resize((3508, 2480), Image.LANCZOS)
hd = hd.filter(ImageFilter.UnsharpMask(radius=2.2, percent=105, threshold=3))
hd = ImageEnhance.Color(hd).enhance(1.06)
hd = ImageEnhance.Contrast(hd).enhance(1.05)
hd = ImageEnhance.Sharpness(hd).enhance(1.18)
hd_path = os.path.join(OUT, '01_高清图_A4_300dpi.jpg')
hd.save(hd_path, quality=95, subsampling=0)
print(f'HD    {hd.size}  {os.path.getsize(hd_path)/1024/1024:.2f}MB  {hd_path}')

NOTEXT = (" Absolutely NO TEXT anywhere: no letters, no Chinese characters, no numbers, no calligraphy, no "
          "captions, no titles, no labels, no writing on any plaque, sign, banner or flag, no logos, no "
          "watermarks, no signature, no seals. Every plaque, sign and banner must be completely blank. ")

# ---------- ③ AI 重绘高清版（低 strength，尽量保留原构图） ----------
REDRAW = NOTEXT + (
 " Faithfully reproduce this exact children's poster as a clean high-quality version, preserving the same "
 "composition, the same layout, the same number of objects and the same positions. Bold uniform black outlines "
 "with flat bright marker colouring neatly filled inside, crisp clean boundaries, no shading, no gradients. "
 "Keep: the thick wavy red ribbon border, the yellow five-pointed star with red outline in the bottom-left "
 "corner, the red and white swirling clouds along the bottom, the light blue sky with white clouds and small \
red five-pointed stars, the two white doves, the four cartoon child soldiers in blue uniforms with red collar "
 "tabs and caps with red stars marching on a yellow path, the leading boy carrying a large red flag with a plain "
 "white circular emblem containing a small neat symmetrical hammer-and-sickle symbol, the girl with pigtails and "
 "two boys behind him, the three-arch grey stone bridge over the blue river, the winding yellow path up the "
 "green hill, the small red flags planted along the path, and the tall white stone monument on the hilltop. "
 "Remove all handwriting, labels and watermarks entirely; leave every sign blank. ")

# ---------- ④ 线条图（保留构图，转为纯线稿） ----------
LINE = NOTEXT + (
 " Convert this exact poster into a pure black-and-white LINE DRAWING for a children's colouring template. Keep "
 "EXACTLY the same shapes, the same positions, the same proportions, the same number of objects and the same "
 "composition — do not add, remove, move or redraw anything. Uniform bold black outlines only on a pure white "
 "background: no colour at all, no grey tones, no shading, no cross-hatching, no stippling, no gradients, no "
 "filled dark areas — every region left pure white with clean closed outlines. Draw the thick wavy ribbon border "
 "and the bottom clouds and the corner star as simple black outlines too. The flag carries a plain white circular "
 "emblem with a small neat symmetrical hammer-and-sickle symbol drawn in clean black lines. Leave the top sky "
 "area free of any text so a title can be added. ")


def call(prompt, ref_path, size, strength, name, retries=3):
    b64 = base64.b64encode(open(ref_path, 'rb').read()).decode()
    for a in range(retries):
        try:
            r = requests.post(f"{BASE}/images/generations",
                headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
                json={"model": MODEL, "prompt": prompt, "size": size, "n": 1, "watermark": False,
                      "image": f"data:image/jpeg;base64,{b64}", "strength": strength}, timeout=300)
            d = r.json()
            if d.get('data'):
                img = requests.get(d['data'][0]['url'], timeout=200).content
                p = os.path.join(OUT, name)
                Image.open(io.BytesIO(img)).convert('RGB').save(p, quality=95, subsampling=0)
                print(f'OK  {name}  s={strength}  {os.path.getsize(p)/1024/1024:.2f}MB', flush=True)
                return p
            print(f'ERR {name} #{a}: {json.dumps(d, ensure_ascii=False)[:200]}', flush=True)
        except Exception as e:
            print(f'EXC {name} #{a}: {e}', flush=True)
        time.sleep(6)
    return None


if __name__ == '__main__':
    import sys
    which = sys.argv[1] if len(sys.argv) > 1 else 'all'
    jobs = []
    if which in ('all', 'redraw'):
        jobs.append(('redraw', REDRAW, 0.25, '02_AI重绘高清版.jpg'))
    if which in ('all', 'line'):
        jobs.append(('line', LINE, 0.60, '03_线条图.jpg'))
    with ThreadPoolExecutor(max_workers=2) as ex:
        print(list(ex.map(lambda j: call(j[1], crop_path, '2400x1700', j[2], j[3]), jobs)))
