"""
app/services/fission_service.py — 第11环裂变 service 入口（对齐上线版 split.js）

裂变 = 1爆款 → 一次 LLM 出 N 套完整笔记包（N=1~5）。
本文件只留 API 入口：
  - create_fission：建 FissionTask 后丢 run_fission_pipeline.delay，不再扇出 GenerationTask
编排层（解析/评分/落库/生图）在 app/services/fission_pipeline.py（红线≤200行已拆）。
"""
import json
import logging

from sqlalchemy.orm import Session

from app.core.response import raise_business
from app.middleware.workspace_guard import CurrentUser
from app.models.fission import FissionTask
from app.models.task import GenerationTask
from app.services.ai_engine.fission_prompt import valid_level
from app.services.task_service import _check_user_has_key

logger = logging.getLogger(__name__)

MAX_FANOUT = 5  # 每用户并发上限5(红线)；裂变 N 套直出受同等约束


def create_fission(
    db: Session, current_user: CurrentUser,
    source_task_id: int, reference_level: str, fanout_count: int,
) -> tuple[int, list[int]]:
    """
    从一个源任务建裂变任务，丢 Celery 一次出 N 套笔记包。
    返回 (fission_id, [])。子笔记落 FissionNote，不再扇出 GenerationTask，
    故第二个返回值恒为空列表（保留签名兼容旧调用方）。
    """
    _check_user_has_key(db, current_user.user_id, current_user.workspace_id)

    level = valid_level(reference_level)
    n = max(1, min(fanout_count or 3, MAX_FANOUT))

    # 读源任务（取产品+主题+已选文案作为爆款源）
    src = db.query(GenerationTask).filter(
        GenerationTask.id == source_task_id,
        GenerationTask.workspace_id == current_user.workspace_id,
    ).first()
    if not src:
        raise_business("裂变源任务不存在")

    source_note = {"title": src.theme or "", "content": _extract_source_copy(db, src)}

    # 建 fission_task 记录（带 source_task_id 供 pipeline 取产品/张数）
    ft = FissionTask(
        workspace_id=current_user.workspace_id,
        source_note=json.dumps(source_note, ensure_ascii=False),
        reference_level=level, fanout_count=n, status="generating",
    )
    db.add(ft); db.commit(); db.refresh(ft)

    # 丢 Celery：一次 LLM 出 N 套（不扇出 GenerationTask）
    from app.workers.tasks import run_fission_pipeline
    run_fission_pipeline.delay(ft.id, source_task_id)

    logger.info("fission created id=%s level=%s n=%s src_task=%s",
                ft.id, level, n, source_task_id)
    return ft.id, []


def _extract_source_copy(db: Session, src: GenerationTask) -> str:
    """取源任务已选/最高分文案当爆款正文；无则用主题兜底。"""
    from app.models.task import TextCandidate
    c = (db.query(TextCandidate)
         .filter(TextCandidate.task_id == src.id)
         .order_by(TextCandidate.is_selected.desc(), TextCandidate.id.asc())
         .first())
    if c and c.content:
        return c.content
    return src.theme or ""
