"""
app/services/fission_images.py — 第11环裂变 逐套生图（从 fission_pipeline 拆出）

复用单篇 generate_storyboard_images（codeproxy edits 带产品参考图），结果存
FissionNote.images_json。拆分原因：fission_pipeline.py 超 200 行红线上限。
🔴 生图引擎零改动；串行跑各套（套内 storyboard 已 asyncio.gather 并发）避免打爆中转站。
"""
import logging

from sqlalchemy.orm import Session

logger = logging.getLogger(__name__)


def generate_fission_images(
    db: Session, clients, ft, product: dict, image_count: int, note_ids: list[int],
) -> None:
    """逐套生图，结果存 FissionNote.images_json。

    每套用该套自己的 note_json（含定制 imagePlan）当 note 喂生图引擎。
    产品参考图沿用源产品同一张，与单篇一致。
    """
    import asyncio
    import json as _json
    import os

    from app.models.fission import FissionNote
    from app.core.config import get_settings
    from app.services.ai_engine.image_gen import generate_storyboard_images
    from app.services.ai_engine.image_postprocessor import process_image
    from app.workers.pipeline_io import _resolve_image_path

    reference_images = None
    _img_path = _resolve_image_path(product.get("image_path", ""))
    if _img_path and os.path.isfile(_img_path):
        try:
            with open(_img_path, "rb") as f:
                reference_images = [f.read()]
        except Exception as e:  # noqa: BLE001
            logger.warning("裂变参考图读取失败，无参考图模式: %s", e)

    upload_base = get_settings().UPLOAD_ABS_ROOT
    for nid in note_ids:
        fn = db.query(FissionNote).filter(FissionNote.id == nid).first()
        if not fn:
            continue
        try:
            note = _json.loads(fn.note_json) if fn.note_json else {}
        except (ValueError, TypeError):
            note = {}
        try:
            results = asyncio.run(generate_storyboard_images(
                client=clients, note=note, product=product,
                image_count=image_count, reference_images=reference_images,
            ))
        except Exception as exc:  # noqa: BLE001
            logger.error("裂变套 seq=%s 生图失败: %s", fn.seq, exc)
            fn.status = "failed"; db.commit()
            continue

        img_dir = os.path.join(upload_base, str(ft.workspace_id), f"fission_{ft.id}", str(fn.seq))
        os.makedirs(img_dir, exist_ok=True)
        images: list[dict] = []
        for i, r in enumerate(results):
            if r.get("error") or not r.get("image_bytes"):
                images.append({"role": r.get("role", ""), "error": str(r.get("error", "生图失败"))[:64]})
                continue
            try:
                processed = process_image(r["image_bytes"], aspect_ratio="3:4", resample_strength=1)
            except Exception:  # noqa: BLE001
                processed = r["image_bytes"]
            fname = f"{i + 1:02d}_{r['role']}.jpg"
            with open(os.path.join(img_dir, fname), "wb") as f:
                f.write(processed)
            images.append({
                "role": r["role"], "seq": i + 1,
                "url": f"/uploads/{ft.workspace_id}/fission_{ft.id}/{fn.seq}/{fname}",
            })
        fn.images_json = _json.dumps(images, ensure_ascii=False)
        fn.status = "image_done"
        db.commit()
