"""씬별 요약 모듈 -- ThreadPool 병렬 처리."""

import logging
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Dict, List, Optional

from app.modules.llm.llm_client import call_structured
from app.modules.prompt_loader import load_prompt, load_schema

logger = logging.getLogger(__name__)

_MODULE = "scene_summary"


def summarize_scene(
    scene_text: str,
    prev_scenes_text: str,
    episode_summary: str,
    visual_rules: str,
    max_length: int = 200,
    project_config: Optional[Dict] = None,
    opik_metadata: Optional[Dict] = None,
) -> str:
    """단일 씬 요약.

    Args:
        scene_text: 현재 씬 텍스트
        prev_scenes_text: 이전 3개 씬 텍스트 (결합)
        episode_summary: 에피소드 요약
        visual_rules: 시각적 세계관 규칙
        max_length: 최대 글자 수
        project_config: 프로젝트별 모델 오버라이드
        opik_metadata: Opik 추적 메타데이터

    Returns:
        씬 요약 문자열
    """
    system = load_prompt(_MODULE, "system", max_length=max_length)
    schema = load_schema(_MODULE, "summary_schema")

    user_prompt = (
        f"에피소드 요약:\n{episode_summary}\n\n"
        f"시각적 규칙:\n{visual_rules}\n\n"
        f"이전 씬:\n{prev_scenes_text}\n\n"
        f"현재 씬:\n{scene_text}\n\n"
        f"{max_length}자 이내로 요약해주세요."
    )

    result = call_structured(
        step="scene_summary",
        system_prompt=system,
        user_prompt=user_prompt,
        response_schema=schema,
        project_config=project_config,
        schema_name="scene_summary",
        opik_metadata=opik_metadata,
    )
    return result.get("scene_summary", "")


def summarize_scenes(
    segments: List[Dict],
    fulltext: str = "",
    episode_summary: str = "",
    visual_rules: str = "",
    max_length: int = 200,
    project_config: Optional[Dict] = None,
    opik_metadata: Optional[Dict] = None,
    max_workers: int = 5,
) -> List[Dict]:
    """모든 씬을 병렬로 요약.

    Args:
        segments: 씬 세그먼트 목록 (scene_index, text 포함)
        fulltext: (deprecated) 하위호환용 — seg["text"] 우선
        episode_summary: 에피소드 요약
        visual_rules: 시각적 세계관 규칙
        max_length: 씬당 최대 글자 수
        project_config: 프로젝트별 모델 오버라이드
        opik_metadata: Opik 추적 메타데이터
        max_workers: ThreadPool 최대 워커 수

    Returns:
        [{scene_index, scene_summary}, ...]
    """
    results: List[Dict] = []

    def _do_one(idx: int, seg: Dict) -> Dict:
        scene_text = seg.get("text") or fulltext[seg.get("start_char", 0):seg.get("end_char", 0)]

        # 이전 3개 씬 텍스트 수집
        prev_texts = []
        for j in range(max(0, idx - 3), idx):
            ps = segments[j]
            prev_texts.append(ps.get("text") or fulltext[ps.get("start_char", 0):ps.get("end_char", 0)])
        prev_combined = "\n---\n".join(prev_texts) if prev_texts else "(없음)"

        summary = summarize_scene(
            scene_text,
            prev_combined,
            episode_summary,
            visual_rules,
            max_length,
            project_config,
            opik_metadata,
        )
        return {
            "scene_index": seg.get("scene_index", idx + 1),
            "scene_summary": summary,
        }

    with ThreadPoolExecutor(max_workers=max_workers) as pool:
        futures = {
            pool.submit(_do_one, i, seg): i for i, seg in enumerate(segments)
        }
        for f in as_completed(futures):
            try:
                results.append(f.result())
            except Exception as exc:
                idx = futures[f]
                logger.warning("Scene %d summary failed: %s", idx, exc)
                results.append({"scene_index": idx + 1, "scene_summary": ""})

    results.sort(key=lambda r: r["scene_index"])
    return results