"""真实出图验证（正式留存版，不带_tmp，勿当临时文件清理）
用法: cd Clover/backend && python3 scripts/real_image_check.py
key 只从 ../.env 读，不硬编码不打印明文。
"""
from __future__ import annotations
import asyncio, base64, io, logging, os, sys, time
from pathlib import Path
import httpx

ROOT = Path(__file__).resolve().parents[2]
_env = ROOT / ".env"
if _env.exists():
    for _l in _env.read_text().splitlines():
        _l = _l.strip()
        if _l and not _l.startswith("#") and "=" in _l:
            k, _, v = _l.partition("=")
            os.environ.setdefault(k.strip(), v.strip())

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger("img")

TEST_PROMPT = "\n".join([
    "生成一张小红书可上传的独立竖版3:4图文海报，目标1024x1536，不是App截图。",
    "产品：倍分子素颜霜（美妆护肤·素颜霜）。",
    "画面角色：封面-钩子。画面主体：自然光生活场景，手持素颜霜或产品在桌面前景，像iPhone实拍封面。",
    "图上文字：主标题「黄黑皮逆袭｜伪素颜天花板」，点位「黄黑皮也能拥有的妈生好皮」。",
    "核心卖点：黄黑皮提亮、伪素颜自然、不假白不卡纹、洗面奶就能卸、懒人必备。",
    "成分：烟酰胺(改善暗沉)、水解珍珠(锁水保湿)、角鲨烷(不卡纹)。",
    "视觉风格：小红书种草风，明亮干净，暖色调，模拟iPhone主摄浅景深。",
    "重要限制：禁止生成App截图/界面元素；禁止肤色变白/功效前后对比；"
    "避免美白/祛斑/速效/医用等违规词；必须保持产品包装与参考图一致。",
])

_REF = ROOT / "test/output/01_连通测试.png"


async def _apiports(key, url, ref, model, size):
    payload = {"model": model, "prompt": TEST_PROMPT, "n": 1, "size": size,
               "image": base64.b64encode(ref).decode()}
    async with httpx.AsyncClient(timeout=300.0) as c:
        r = await c.post(url, json=payload, headers={"Authorization": f"Bearer {key}"})
    if r.status_code != 200:
        raise RuntimeError(f"HTTP {r.status_code}: {r.text[:200]}")
    return _parse(r.json())


async def _codeproxy(key, base, ref, model, size):
    files = [("model", (None, model)), ("prompt", (None, TEST_PROMPT)),
             ("size", (None, size)), ("n", (None, "1")),
             ("image[]", ("ref.png", io.BytesIO(ref), "image/png"))]
    async with httpx.AsyncClient(timeout=300.0) as c:
        r = await c.post(f"{base}/images/edits", files=files,
                         headers={"Authorization": f"Bearer {key}"})
    if r.status_code != 200:
        raise RuntimeError(f"HTTP {r.status_code}: {r.text[:200]}")
    return _parse(r.json())


def _parse(j):
    item = (j.get("data") or [{}])[0]
    if "b64_json" in item:
        return base64.b64decode(item["b64_json"])
    if "url" in item:
        rr = httpx.get(item["url"], timeout=30.0); rr.raise_for_status()
        return rr.content
    raise ValueError(f"无法解析: {list(item.keys())}")


async def run():
    model = os.environ.get("MODEL_IMAGE", "gpt-image-2")
    size = os.environ.get("IMAGE_SIZE", "1024x1536")
    primary = os.environ.get("IMAGE_PROVIDER_PRIMARY", "apiports").lower()
    fallback = os.environ.get("IMAGE_PROVIDER_FALLBACK", "codeproxy").lower()
    out_dir = Path(__file__).parent.parent / "verify_output"
    out_dir.mkdir(parents=True, exist_ok=True)
    ref = _REF.read_bytes()
    t0 = time.time(); img = None; used = None
    for prov in [primary, fallback]:
        key = os.environ.get(f"{prov.upper()}_KEY", "")
        url = os.environ.get(f"{prov.upper()}_BASE_URL", "")
        if not key or not url:
            continue
        logger.info("[%s] 出图中 model=%s size=%s", prov, model, size)
        try:
            img = await (_apiports(key, url, ref, model, size) if prov == "apiports"
                         else _codeproxy(key, url, ref, model, size))
            used = prov; break
        except Exception as e:
            logger.error("[%s] 失败: %s", prov, e)
    dt = time.time() - t0
    print("\n===== 出图结果 =====")
    if img:
        out = out_dir / "素颜霜_封面hook.png"
        out.write_bytes(img)
        print(f"  provider: {used}\n  耗时: {dt:.1f}s\n  大小: {len(img)//1024}KB\n  路径: {out}")
    else:
        print(f"  耗时: {dt:.1f}s\n  状态: 全失败")
    print("====================\n")
    return img is not None


if __name__ == "__main__":
    sys.exit(0 if asyncio.run(run()) else 1)
