"""种草图（Seed Shot）生成。

- 模板：configs/seed_shot_templates.yaml（可自定义，占位符 [商品名称]/[材质]/[模特特征]）
- 模特特征：configs/model_features.yaml（可自定义，随机取一条）
- 生成：以 product 合成图（图1）为参考，img2img 生成 N 张种草图（保留衣服外观、换场景/模特）
- 占位替换：[商品名称]→cn_title（缺省回退 topic）；[材质]→SPU.material；[模特特征]→随机
"""
import random
from pathlib import Path
from typing import Any, Dict, List, Optional

import yaml

from graph.paths import project_root


def _load_yaml(rel: str) -> Dict[str, Any]:
    for root in (project_root(),):
        p = root / rel
        if p.exists():
            try:
                return yaml.safe_load(p.read_text(encoding="utf-8")) or {}
            except Exception as e:  # noqa: BLE001
                print(f"[seed_shot] 读取 {rel} 失败: {e}")
    return {}


def load_templates() -> List[Dict[str, str]]:
    """种草图提示词模板列表（无配置时给内置兜底）。"""
    data = _load_yaml("configs/seed_shot_templates.yaml")
    tpls = data.get("seed_shot_templates") or []
    if not tpls:
        tpls = [{
            "name": "default",
            "prompt": (
                "【最高优先级约束】请严格保留参考图1中模特所穿衣服的完整外观，包括其原有的颜色、"
                "印花图案、版型款式、材质纹理与缝线细节，绝对禁止对衣服本身进行任何形式的修改、"
                "重新设计、变色或改变图案。仅提取这件[商品名称]，将其穿在一位[模特特征]的身上。"
                "全身动态抓拍构图，行走在阳光斑驳的城市林荫道上，微微低头微笑，凸显[材质]的透气与百搭。"
                "徕卡Q2摄影质感，高对比度色彩，35mm镜头，f/1.7大光圈，8k分辨率。"
            ),
        }]
    return [{"name": str(t.get("name", "default")), "prompt": str(t.get("prompt", ""))}
            for t in tpls if t.get("prompt")]


def load_model_features() -> List[str]:
    """模特特征列表（无配置时给内置兜底）。"""
    data = _load_yaml("configs/model_features.yaml")
    feats = [str(f) for f in (data.get("model_features") or []) if str(f).strip()]
    if not feats:
        feats = ["20岁清新少女，素颜通透感", "25岁都市职场女性，干练气质"]
    return feats


def load_style_features() -> List[str]:
    """服装风格列表（style_features.yaml，随机取一条替换 [服装风格]；无配置时内置兜底）。"""
    data = _load_yaml("configs/style_features.yaml")
    feats = [str(f) for f in (data.get("style_features") or []) if str(f).strip()]
    if not feats:
        feats = ["极简基础款风格，干净纯粹，无过多繁复装饰",
                 "日系City Boy/Girl风，微宽松版型，注重舒适度与层次感"]
    return feats


def render_prompt(template_prompt: str, cn_title: str, material: str, model_feature: str,
                  style_feature: str = "") -> str:
    """占位替换：[商品名称]/[材质]/[模特特征]/[服装风格]"""
    out = template_prompt.replace("[商品名称]", (cn_title or "").strip() or "这件衣服")
    out = out.replace("[材质]", (material or "").strip() or "面料")
    out = out.replace("[模特特征]", (model_feature or "").strip() or "模特")
    out = out.replace("[服装风格]", (style_feature or "").strip() or "日常休闲风")
    return out


def generate_seed_shots(image_backend, base_image: str, cn_title: str, material: str,
                        count: int, out_dir: str, negative: str = "",
                        size: str = "1504x2000", prefix: str = "") -> List[str]:
    """生成 count 张种草图（img2img，图1=合成图）。返回产物路径列表。
    size: 种草图统一 1504x2000。
    prefix: 货号前缀（对应产品货号，命名 {prefix}_seedshot_{n}.png，不覆盖旧文件）。
    占位符 [商品名称]/[材质]/[模特特征]/[服装风格] 均随机组合（模板/模特/服装风格各随机取一条）。"""
    templates = load_templates()
    features = load_model_features()
    style_features = load_style_features()
    out = Path(out_dir)
    out.mkdir(parents=True, exist_ok=True)
    paths: List[str] = []
    for i in range(count):
        tpl = random.choice(templates)
        feat = random.choice(features)
        style_feat = random.choice(style_features)
        prompt = render_prompt(tpl["prompt"], cn_title, material, feat, style_feat)
        out_path = str(out / f"{prefix}_seedshot_{i + 1:02d}.png" if prefix
                       else out / f"seed_shot_{i + 1:02d}.png")
        try:
            image_backend.print(prompt, base_image, out_path, negative, size=size)
            paths.append(out_path)
            print(f"[seed_shot] 已生成种草图 {i + 1}/{count}: {out_path}"
                  f"（模板={tpl['name']}，模特={feat[:14]}…，风格={style_feat[:14]}…）")
        except Exception as e:  # noqa: BLE001
            print(f"[seed_shot] 种草图 {i + 1} 生成失败: {e}")
    return paths
