"""Shared section builders for prompt assembly.

Each builder returns str | None (None = omit section) or list[str].
These are used by both assemble_static_system_prompt and assemble_system_prompt.
"""
from __future__ import annotations

from typing import Optional

from kokoro_chat.character.model import Character


# ---------------------------------------------------------------------------
# Speech pattern helper (moved from assembler.py)
# ---------------------------------------------------------------------------

def _select_speech_pattern(
    v2_patterns: dict[str, str],
    legacy_patterns: str,
    mood: str,
) -> str:
    """Select speech pattern: V2 mood-based > V2 default > legacy."""
    if v2_patterns:
        pattern = v2_patterns.get(mood) or v2_patterns.get("default", "")
        return pattern.strip() if pattern else ""
    return legacy_patterns.strip() if legacy_patterns else ""


# ---------------------------------------------------------------------------
# Individual section builders
# ---------------------------------------------------------------------------

def build_character_section(character: Character) -> list[str]:
    """[角色設定] + optional [外觀].

    V2 path: uses character.description (single merged block).
    Legacy path: personality/background/speaking_style/mbti + optional appearance.

    Returns a list of section strings (1 or 2 items).
    """
    if character.description:
        return [f"[角色設定]\n你是「{character.name}」。\n{character.description}"]

    char_section = (
        f"[角色設定]\n"
        f"你是「{character.name}」。\n"
        f"性格：{character.personality}\n"
        f"背景：{character.background}\n"
        f"說話風格：{character.speaking_style}\n"
        f"MBTI：{character.mbti}"
    )
    sections = [char_section]
    if character.appearance:
        sections.append(f"[外觀]\n{character.appearance}")
    return sections


def build_personality_summary_section(character: Character) -> Optional[str]:
    """[性格摘要] — returns None when empty."""
    if character.personality_summary:
        return f"[性格摘要]\n{character.personality_summary}"
    return None


def build_traits_section(character: Character) -> Optional[str]:
    """[特質] from likes/dislikes/fears/quirks — returns None when all empty."""
    trait_lines = []
    if character.likes:
        trait_lines.append(f"喜歡的事物：{', '.join(character.likes)}")
    if character.dislikes:
        trait_lines.append(f"討厭的事物：{', '.join(character.dislikes)}")
    if character.fears:
        trait_lines.append(f"害怕的事物：{', '.join(character.fears)}")
    if character.quirks:
        trait_lines.append(f"小癖好：{', '.join(character.quirks)}")
    if trait_lines:
        return "[特質]\n" + "\n".join(trait_lines)
    return None


def build_speech_section(
    character: Character,
    current_mood: Optional[str] = None,
) -> Optional[str]:
    """[語癖] — V2 mood-based, fallback to legacy. Returns None when empty."""
    speech_text = _select_speech_pattern(
        character.speech_patterns_v2,
        character.speech_patterns,
        current_mood or character.default_mood,
    )
    if speech_text:
        return f"[語癖]\n{speech_text}"
    return None


def build_anti_patterns_section(character: Character) -> Optional[str]:
    """[不要這樣說] — returns None when no valid anti-patterns."""
    if not character.anti_patterns:
        return None
    ap_lines = []
    for ap in character.anti_patterns:
        bad = ap.get("bad", "")
        correct = ap.get("correct", "")
        why = ap.get("why", "")
        if bad and correct:
            line = f"\u2717 不要說：「{bad}」\n\u2713 應該說：「{correct}」"
            if why:
                line += f"\n  原因：{why}"
            ap_lines.append(line)
    if ap_lines:
        return "[不要這樣說]\n" + "\n---\n".join(ap_lines)
    return None


def build_mes_example_section(
    character: Character,
    max_examples: int = 1,
) -> Optional[str]:
    """[對話風格示例] — returns None when no valid examples."""
    if not character.mes_example:
        return None
    examples = character.mes_example[:max_examples]
    example_lines = []
    for ex in examples:
        user_text = str(ex.get("user", "")).strip()
        char_text = str(ex.get("char", "")).strip()
        if user_text and char_text:
            example_lines.append(f"用戶：{user_text}\n{character.name}：{char_text}")
    if example_lines:
        return "[對話風格示例]\n" + "\n---\n".join(example_lines)
    return None


def build_chat_mode_section(chat_mode: str, chat_modes: dict[str, str]) -> str:
    """[回覆模式] — always returns a non-empty string."""
    mode_instruction = chat_modes.get(chat_mode, chat_modes.get("short", ""))
    return f"[回覆模式]\n{mode_instruction}"


def build_scene_section(
    scene: Optional[str],
    scenario: Optional[str],
) -> Optional[str]:
    """[當前場景] — scene param takes priority over character.scenario. Returns None if both empty."""
    effective_scene = scene or scenario
    if effective_scene:
        return f"[當前場景]\n{effective_scene}"
    return None


def build_core_character_sections(
    character: Character,
    chat_mode: str,
    chat_modes: dict[str, str],
    scene: Optional[str] = None,
    current_mood: Optional[str] = None,
    max_mes_examples: int = 1,
) -> list[str]:
    """Build all core character sections in assembly order.

    Returns a list of non-None section strings in the correct order:
      1. [角色設定] (+ optional [外觀] in legacy mode)
      2. [性格摘要]
      3. [特質]
      4. [語癖]
      5. [對話風格示例]
      6. [不要這樣說]
      7. [回覆模式]
      8. [當前場景]
    """
    sections: list[str] = []

    # 1. Character settings
    sections.extend(build_character_section(character))

    # 2. Personality summary
    ps = build_personality_summary_section(character)
    if ps is not None:
        sections.append(ps)

    # 3. Traits
    traits = build_traits_section(character)
    if traits is not None:
        sections.append(traits)

    # 4. Speech patterns
    speech = build_speech_section(character, current_mood)
    if speech is not None:
        sections.append(speech)

    # 5. Conversation examples
    mes = build_mes_example_section(character, max_examples=max_mes_examples)
    if mes is not None:
        sections.append(mes)

    # 6. Anti-patterns
    ap = build_anti_patterns_section(character)
    if ap is not None:
        sections.append(ap)

    # 7. Chat mode
    sections.append(build_chat_mode_section(chat_mode, chat_modes))

    # 8. Scene
    scene_section = build_scene_section(scene, character.scenario)
    if scene_section is not None:
        sections.append(scene_section)

    return sections
