"""Prompt injection/composition logic."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from sigil.models import Persona


def compose_prompt(persona: Persona, base: str | None = None) -> str:
    """
    Compose a system prompt from persona fields.

    Order:
    1. Base prompt (if provided)
    2. Soul text
    3. Voice rules (dos/donts)
    4. Values (sorted by priority)
    5. Behavioral map entries

    Args:
        persona: The persona to compose from.
        base: Optional base prompt to prepend.

    Returns:
        A formatted system prompt string.
    """
    sections: list[str] = []

    # 1. Base prompt
    if base:
        sections.append(base.strip())

    # 2. Soul text
    if persona.soul:
        sections.append(persona.soul.strip())

    # 3. Voice rules
    voice_section = _format_voice(persona)
    if voice_section:
        sections.append(voice_section)

    # 4. Values (sorted by priority, highest first)
    values_section = _format_values(persona)
    if values_section:
        sections.append(values_section)

    # 5. Behavioral map
    behavioral_section = _format_behavioral_map(persona)
    if behavioral_section:
        sections.append(behavioral_section)

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


def _format_voice(persona: Persona) -> str:
    """Format voice rules into a string."""
    lines: list[str] = []
    voice = persona.voice

    if voice.tone:
        lines.append("## Tone")
        for t in voice.tone:
            lines.append(f"- {t}")

    if voice.dos:
        lines.append("")
        lines.append("## Do")
        for do in voice.dos:
            lines.append(f"- {do}")

    if voice.donts:
        lines.append("")
        lines.append("## Don't")
        for dont in voice.donts:
            lines.append(f"- {dont}")

    if voice.example_phrases:
        lines.append("")
        lines.append("## Example Phrases")
        for phrase in voice.example_phrases:
            lines.append(f'- "{phrase}"')

    return "\n".join(lines) if lines else ""


def _format_values(persona: Persona) -> str:
    """Format values into a string, sorted by priority (highest first)."""
    if not persona.values:
        return ""

    sorted_values = sorted(persona.values, key=lambda v: v.priority, reverse=True)

    lines = ["## Values"]
    for value in sorted_values:
        lines.append(f"- **{value.name}**: {value.description}")

    return "\n".join(lines)


def _format_behavioral_map(persona: Persona) -> str:
    """Format behavioral map into a string."""
    if not persona.behavioral_map:
        return ""

    lines = ["## Behavioral Guidelines"]
    for key, entry in persona.behavioral_map.items():
        lines.append(f"### {key}")
        lines.append(f"**Posture**: {entry.posture}")
        if entry.example:
            lines.append(f"**Example**: {entry.example}")
        lines.append("")

    return "\n".join(lines).rstrip()
