"""월드 가이드 생성 모듈 — OpenAI 구조화 출력을 사용한 세계관 가이드 생성."""

import json
from pathlib import Path
from typing import Any, Dict, List

from app.modules.llm.openai_client import OpenAIClient

PROMPTS_BASE = Path(__file__).resolve().parent.parent.parent.parent / "prompts" / "_base" / "prototype_prompts"

def _get_prompts_dir():
    versions = sorted([d.name for d in PROMPTS_BASE.iterdir() if d.is_dir()], reverse=True)
    if not versions:
        return PROMPTS_BASE / "v5"  # fallback
    return PROMPTS_BASE / versions[0]

WORLD_GUIDE_SCHEMA: Dict[str, Any] = {
    "type": "object",
    "additionalProperties": False,
    "properties": {
        "world_time_period": {"type": "string"},
        "world_setting_summary": {"type": "string"},
        "technology_level": {"type": "string"},
        "era_guardrails": {"type": "array", "minItems": 3, "maxItems": 8, "items": {"type": "string"}},
        "costume_guardrails": {"type": "array", "minItems": 3, "maxItems": 8, "items": {"type": "string"}},
        "location_guardrails": {"type": "array", "minItems": 2, "maxItems": 6, "items": {"type": "string"}},
        "prop_guardrails": {"type": "array", "minItems": 2, "maxItems": 6, "items": {"type": "string"}},
        "prohibited_visual_misreads": {"type": "array", "minItems": 4, "maxItems": 12, "items": {"type": "string"}},
        "continuity_guardrails": {"type": "array", "minItems": 3, "maxItems": 8, "items": {"type": "string"}},
        "image_generation_notes": {"type": "array", "minItems": 2, "maxItems": 6, "items": {"type": "string"}},
        "style_rules": {
            "type": "object",
            "additionalProperties": False,
            "properties": {
                "must_maintain": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "이미지 생성 시 반드시 유지해야 할 시각 규칙 (3-5개)"
                },
                "must_avoid": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "이미지 생성 시 반드시 피해야 할 시각 요소 (3-5개)"
                },
            },
            "required": ["must_maintain", "must_avoid"],
        },
    },
    "required": [
        "world_time_period",
        "world_setting_summary",
        "technology_level",
        "era_guardrails",
        "costume_guardrails",
        "location_guardrails",
        "prop_guardrails",
        "prohibited_visual_misreads",
        "continuity_guardrails",
        "image_generation_notes",
        "style_rules",
    ],
}

LANGUAGE_NAMES = {
    "ko": ("ko", "Korean"),
    "en": ("en", "English"),
}


def _load_prompt(filename: str) -> str:
    return (_get_prompts_dir() / filename).read_text(encoding="utf-8").strip()


def _compact_entities(entities: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """Compact entity dicts for world guide input."""
    compact = []
    for item in entities:
        compact.append({
            "name": item.get("name", ""),
            "entity_type": item.get("entity_type", ""),
            "description": item.get("description", ""),
            "stable_traits": item.get("stable_traits", "{}"),
        })
    return compact


def _compact_stills(stills: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """Compact scene still dicts for world guide input."""
    compact = []
    for s in stills:
        compact.append({
            "still_index": s.get("still_index", 0),
            "screenplay_scene_heading": s.get("screenplay_scene_heading", ""),
            "beat_title": s.get("beat_title", ""),
            "still_frame_prompt": s.get("still_frame_prompt", ""),
        })
    return compact


class WorldGuideGenerator:
    """세계관 가이드 생성기."""

    def __init__(self, llm_client: OpenAIClient | None = None) -> None:
        self._llm = llm_client or OpenAIClient()

    def generate(
        self,
        fulltext: str,
        language: str,
        source_file: str,
        entities: List[Dict[str, Any]],
        stills: List[Dict[str, Any]],
    ) -> Dict[str, Any]:
        """Generate a world guide from screenplay text and extracted data."""
        lang_code, lang_name = LANGUAGE_NAMES.get(language, ("ko", "Korean"))

        system_prompt = _load_prompt("world_guide_system.md").format(
            source_language_code=lang_code,
            source_language_name=lang_name,
        )
        user_prompt = _load_prompt("world_guide_user.md").format(
            source_file=source_file,
            screenplay_text=fulltext,
            entities_json=json.dumps(_compact_entities(entities), ensure_ascii=False, indent=2),
            scene_stills_json=json.dumps(_compact_stills(stills), ensure_ascii=False, indent=2),
        )

        return self._llm.generate_structured(
            system_prompt=system_prompt,
            user_prompt=user_prompt,
            response_schema=WORLD_GUIDE_SCHEMA,
            schema_name="prototype_world_guide",
        )
