"""PersonaContextProvider -- character persona section of the system prompt.

Extracted from app/providers/persona.py.
No sqlalchemy / fastapi / redis imports allowed.

Responsible for:
  - Character base settings (V2 description or legacy personality/background/appearance)
  - Personality summary (V2 personality_summary)
  - Traits (likes, dislikes, fears, quirks)
  - Speech patterns (V2 speech_patterns_v2 or legacy speech_patterns)
  - Anti-patterns (V2)
  - Unlocked secrets
"""
from __future__ import annotations

from kokoro_chat.character.model import Character
from kokoro_chat.prompt.assembler import (
    _get_unlocked_secrets,
    _select_speech_pattern,
)


class PersonaContextProvider:
    """Build the persona section of the system prompt.

    Created per-request with all needed state via constructor injection.
    """

    def __init__(
        self,
        character: Character,
        affection_score: int = 50,
        trust_score: int = 50,
        current_mood: str | None = None,
    ):
        self._character = character
        self._affection_score = affection_score
        self._trust_score = trust_score
        self._current_mood = current_mood

    async def build(self, query: str) -> str:
        """Build the persona context string.

        ``query`` is accepted for protocol compliance but not used --
        persona context is static per request.
        """
        sections: list[str] = []
        c = self._character

        # Character settings -- V2 uses description, fallback to legacy fields
        if c.description:
            sections.append(f"[角色設定]\n你是「{c.name}」。\n{c.description}")
        else:
            sections.append(
                f"[角色設定]\n"
                f"你是「{c.name}」。\n"
                f"性格：{c.personality}\n"
                f"背景：{c.background}\n"
                f"說話風格：{c.speaking_style}\n"
                f"MBTI：{c.mbti}"
            )

            # Appearance (only in legacy mode)
            if c.appearance:
                sections.append(f"[外觀]\n{c.appearance}")

        # Personality summary (V2)
        if c.personality_summary:
            sections.append(f"[性格摘要]\n{c.personality_summary}")

        # Traits
        trait_lines: list[str] = []
        if c.likes:
            trait_lines.append(f"喜歡的事物：{', '.join(c.likes)}")
        if c.dislikes:
            trait_lines.append(f"討厭的事物：{', '.join(c.dislikes)}")
        if c.fears:
            trait_lines.append(f"害怕的事物：{', '.join(c.fears)}")
        if c.quirks:
            trait_lines.append(f"小癖好：{', '.join(c.quirks)}")
        if trait_lines:
            sections.append("[特質]\n" + "\n".join(trait_lines))

        # Speech patterns -- V2 mood-based, fallback to legacy
        mood = self._current_mood or c.default_mood
        speech_text = _select_speech_pattern(
            c.speech_patterns_v2, c.speech_patterns, mood,
        )
        if speech_text:
            sections.append(f"[語癖]\n{speech_text}")

        # Anti-patterns (V2)
        if c.anti_patterns:
            ap_lines = []
            for ap in c.anti_patterns:
                bad = ap.get("bad", "")
                correct = ap.get("correct", "")
                why = ap.get("why", "")
                if bad and correct:
                    line = f"\u2717 \u4e0d\u8981\u8aaa\uff1a\u300c{bad}\u300d\n\u2713 \u61c9\u8a72\u8aaa\uff1a\u300c{correct}\u300d"
                    if why:
                        line += f"\n  \u539f\u56e0\uff1a{why}"
                    ap_lines.append(line)
            if ap_lines:
                sections.append("[\u4e0d\u8981\u9019\u6a23\u8aaa]\n" + "\n---\n".join(ap_lines))

        # Unlocked secrets
        unlocked = _get_unlocked_secrets(
            c.secrets, self._affection_score, self._trust_score,
        )
        if unlocked:
            secret_lines = [f"- {s}" for s in unlocked]
            sections.append(
                "[\u5df2\u89e3\u9396\u7684\u79d8\u5bc6]\n"
                "\u4ee5\u4e0b\u662f\u89d2\u8272\u9858\u610f\u900f\u9732\u7684\u79d8\u5bc6\uff0c\u53ef\u4ee5\u5728\u5c0d\u8a71\u4e2d\u81ea\u7136\u5730\u63d0\u53ca\u6216\u6697\u793a\uff1a\n"
                + "\n".join(secret_lines)
            )

        return "\n\n".join(sections)
