"""
Constitution Formatters - Convert composed constitution to system prompt.

These formatters take the composed constitution and generate formatted
text suitable for inclusion in an agent's system prompt.
"""

from __future__ import annotations

from lightwave.schema.pydantic.models.constitution import (
    ComposedConstitution,
    Principle,
    SecondBrainEntryContext,
    UserIdentityContext,
    UserPrincipleEntry,
    VoiceModel,
)


def format_constitution_prompt(constitution: ComposedConstitution) -> str:
    """
    Convert a composed constitution to a complete system prompt section.

    This is the main formatter that combines all sections into a coherent
    constitution prompt for the agent.

    Args:
        constitution: The composed constitution

    Returns:
        Formatted system prompt string
    """
    sections: list[str] = []

    # Header
    sections.append("# Constitution Context")
    sections.append("")

    # Identity section (if available)
    if constitution.identity:
        sections.append(format_identity_section(constitution.identity))
        sections.append("")

    # Voice model section
    if constitution.voice_model:
        sections.append(format_voice_section(constitution.voice_model))
        sections.append("")

    # Principles section
    if constitution.principles:
        sections.append(
            format_principles_section(
                constitution.principles,
                constitution.user_principles,
            )
        )
        sections.append("")

    # Knowledge section (if available)
    if constitution.knowledge:
        sections.append(format_knowledge_section(constitution.knowledge))
        sections.append("")

    # Reference books (if available)
    if constitution.reference_books:
        sections.append(format_reference_section(constitution.reference_books))
        sections.append("")

    # Constraints
    if constitution.absolute_constraints or constitution.soft_constraints:
        sections.append(
            format_constraints_section(
                [c.description for c in constitution.absolute_constraints],
                [(c.description, c.weight) for c in constitution.soft_constraints],
            )
        )

    return "\n".join(sections)


def format_identity_section(identity: UserIdentityContext) -> str:
    """
    Format the user identity section.

    This provides context about who the user is - their legal structure,
    financial situation, and professional context.
    """
    lines = [
        "## User Context",
        "",
    ]

    # Legal entity
    legal = identity.legal_entity
    if legal.type != "individual":
        entity_desc = f"a {legal.type.replace('_', ' ').title()}"
        if legal.name:
            entity_desc = f"{legal.name}, {entity_desc}"
        if legal.jurisdiction:
            entity_desc += f" in {legal.jurisdiction}"
        lines.append(f"- Business: {entity_desc}")

    # Financial context
    fin = identity.financial
    if fin.accounting_method:
        lines.append(f"- Accounting: {fin.accounting_method.title()} basis")
    if fin.fiscal_year_end and fin.fiscal_year_end != "12-31":
        lines.append(f"- Fiscal year ends: {fin.fiscal_year_end}")
    if fin.credit_profile and fin.credit_profile != "unknown":
        lines.append(f"- Credit profile: {fin.credit_profile.title()}")

    # Professional context
    prof = identity.professional
    if prof.industry:
        lines.append(f"- Industry: {prof.industry}")
    if prof.team_size and prof.team_size != "solo":
        lines.append(f"- Team size: {prof.team_size.title()}")

    # Verification status (affects trust level)
    ver = identity.verification
    if ver.identity and ver.business:
        lines.append("- Verification: Identity and business verified")
    elif ver.identity:
        lines.append("- Verification: Identity verified")

    return "\n".join(lines)


def format_voice_section(voice: VoiceModel) -> str:
    """
    Format the voice model section.

    This guides the agent's communication style and tone.
    """
    lines = [
        "## Communication Style",
        "",
        f"Voice: {voice.name}",
    ]

    if voice.tone:
        lines.append(f"Tone: {voice.tone}")

    if voice.characteristics:
        chars = ", ".join(voice.characteristics)
        lines.append(f"Characteristics: {chars}")

    return "\n".join(lines)


def format_principles_section(
    base_principles: list[Principle],
    user_principles: list[UserPrincipleEntry],
) -> str:
    """
    Format the principles section.

    Shows the guiding principles for agent behavior, with both
    base principles and user-defined additions.
    """
    lines = [
        "## Guiding Principles",
        "",
    ]

    # Show top principles (by weight)
    top_principles = sorted(base_principles, key=lambda p: p.weight, reverse=True)[:5]

    for p in top_principles:
        weight_indicator = ""
        if p.weight >= 1.5:
            weight_indicator = " [HIGH PRIORITY]"
        elif p.weight <= 0.5:
            weight_indicator = " [secondary]"

        lines.append(f"- **{p.name}**{weight_indicator}: {p.description}")

    # Add user principles that aren't overrides
    user_additions = [p for p in user_principles if not p.overrides_base]
    if user_additions:
        lines.append("")
        lines.append("### Personal Principles")
        lines.append("")
        for p in user_additions[:3]:  # Limit to top 3
            lines.append(f"- **{p.name}**: {p.description}")

    return "\n".join(lines)


def format_knowledge_section(knowledge: list[SecondBrainEntryContext]) -> str:
    """
    Format the second brain knowledge section.

    This provides relevant knowledge from the user's second brain
    that may be useful for the current context.
    """
    lines = [
        "## Relevant Knowledge",
        "",
        "The following knowledge may be relevant to this conversation:",
        "",
    ]

    for entry in knowledge[:5]:  # Limit display
        # Use summary if available, otherwise truncate content
        content = entry.summary if entry.summary else entry.content[:200]
        if len(content) > 200:
            content = content[:197] + "..."

        weight_str = f"[relevance: {entry.effective_weight:.1f}]"
        lines.append(f"### {entry.title} {weight_str}")
        lines.append(f"{content}")
        lines.append("")

    return "\n".join(lines)


def format_reference_section(books: list) -> str:
    """
    Format the reference material section.

    Shows books/resources that inform the agent's perspective.
    """
    lines = [
        "## Reference Material",
        "",
        "Your responses should draw on insights from:",
        "",
    ]

    for book in books[:3]:  # Limit to top 3
        if book.key_insights:
            insight = book.key_insights[0]
            lines.append(f'- **{book.title}** ({book.author}): "{insight}"')
        else:
            lines.append(f"- **{book.title}** by {book.author}")

    return "\n".join(lines)


def format_constraints_section(
    absolute: list[str],
    soft: list[tuple[str, float]],
) -> str:
    """
    Format the constraints section.

    Absolute constraints are hard rules; soft constraints are preferences.
    """
    lines = [
        "## Behavioral Boundaries",
        "",
    ]

    if absolute:
        lines.append("### Absolute Rules (Never violate)")
        lines.append("")
        for constraint in absolute:
            lines.append(f"- {constraint}")
        lines.append("")

    if soft:
        lines.append("### Preferences")
        lines.append("")
        # Sort by weight descending
        sorted_soft = sorted(soft, key=lambda x: x[1], reverse=True)
        for constraint, _weight in sorted_soft[:5]:
            lines.append(f"- {constraint}")

    return "\n".join(lines)
