"""요소 추출 v4 — 3턴 타입별 순차 추출."""
import logging
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 = "entity_extract_v4"


def extract_entities_by_type(
    fulltext: str,
    entity_type: str,
    visual_rules: str = "",
    segments_json: str = "",
    project_config: Optional[Dict] = None,
    opik_metadata: Optional[Dict] = None,
) -> List[Dict]:
    """단일 타입 요소 추출. entity_type: character|location|prop"""
    system = load_prompt(_MODULE, "system")
    type_prompt = load_prompt(_MODULE, entity_type)
    schema = load_schema(_MODULE, f"{entity_type}_schema")

    user_prompt = (
        f"시각적 규칙:\n{visual_rules}\n\n"
        f"시나리오 전문:\n{fulltext}\n\n"
        f"{type_prompt}"
    )

    # 타입별 스텝명 — 모델 분리 가능 (character=gpt, location/prop=gemini-pro)
    step_name = f"entity_extract_{entity_type}"

    result = call_structured(
        step=step_name,
        system_prompt=system,
        user_prompt=user_prompt,
        response_schema=schema,
        project_config=project_config,
        schema_name=f"entity_{entity_type}",
        opik_metadata=opik_metadata,
    )

    # Root key varies: characters / locations / props
    key = f"{entity_type}s" if entity_type != "prop" else "props"
    entities = result.get(key, [])

    return entities


def extract_entities_by_type_with_list(
    fulltext: str,
    entity_type: str,
    name_list: List[Dict],
    visual_rules: str = "",
    project_config: Optional[Dict] = None,
    opik_metadata: Optional[Dict] = None,
) -> List[Dict]:
    """entity_all 리스트 기반 상세 추출.

    name_list: [{"name": ...}, ...]
    LLM에게 이 목록의 인물/배경/소품에 대해 설명만 추가하도록 요청.
    """
    system = load_prompt(_MODULE, "system")
    type_prompt = load_prompt(_MODULE, entity_type)
    schema = load_schema(_MODULE, f"{entity_type}_schema")

    # 리스트를 텍스트로 변환하여 프롬프트에 포함
    names_text = "\n".join(f"- {e['name']}" for e in name_list)

    user_prompt = (
        f"시각적 규칙:\n{visual_rules}\n\n"
        f"시나리오 전문:\n{fulltext}\n\n"
        f"## 이미 확정된 목록 — 아래 목록의 요소에 대해서만 상세 설명을 작성하세요\n"
        f"새로 추가하거나 제거하지 마세요. 이름도 그대로 유지하세요.\n\n"
        f"{names_text}\n\n"
        f"{type_prompt}"
    )

    step_name = f"entity_extract_{entity_type}"

    result = call_structured(
        step=step_name,
        system_prompt=system,
        user_prompt=user_prompt,
        response_schema=schema,
        project_config=project_config,
        schema_name=f"entity_{entity_type}",
        opik_metadata=opik_metadata,
    )

    key = f"{entity_type}s" if entity_type != "prop" else "props"
    entities = result.get(key, [])


    return entities


def extract_all_entities(
    fulltext: str,
    visual_rules: str = "",
    segments_json: str = "",
    project_config: Optional[Dict] = None,
    opik_metadata: Optional[Dict] = None,
) -> Dict[str, List[Dict]]:
    """3턴 순차: 인물 -> 배경 -> 소품."""
    characters = extract_entities_by_type(
        fulltext, "character", visual_rules, segments_json, project_config, opik_metadata,
    )
    locations = extract_entities_by_type(
        fulltext, "location", visual_rules, segments_json, project_config, opik_metadata,
    )
    props = extract_entities_by_type(
        fulltext, "prop", visual_rules, segments_json, project_config, opik_metadata,
    )
    return {"characters": characters, "locations": locations, "props": props}
