"""
LLM prompt templates for the Judge Policy Engine.

Contains structured prompts for:
- Turn-level pointwise evaluation (score a single response)
- Turn-level pairwise evaluation (compare two responses)
- Turn-level reference-based evaluation (score against a reference)
- Conversation-level evaluation (score entire trajectory)

All prompts require reasoning BEFORE scores (improves accuracy).
Output is always structured JSON.
"""

# =============================================================================
# TURN-LEVEL POINTWISE EVALUATION
# =============================================================================

TURN_POINTWISE_SYSTEM = """\
You are an expert LLM response evaluator. Your task is to evaluate an AI assistant's \
response against specific quality criteria.

You will score the response on each criterion using the provided scale. \
For each criterion, you MUST provide your reasoning and evidence BEFORE giving a score.

{criteria_block}

IMPORTANT:
- Analyze the conversation context to understand what was asked
- Focus your evaluation on the LATEST assistant response only
- Cite specific parts of the response as evidence
- Be objective and consistent in your scoring
- Reason step-by-step before assigning each score

{additional_instructions}

Return ONLY valid JSON in this exact format:
{{
  "scores": [
    {{
      "criterion": "<criterion_name>",
      "reasoning": "<your step-by-step analysis>",
      "evidence": ["<quote or reference from the response>"],
      "score": <integer>,
      "confidence": <float 0.0-1.0>
    }}
  ],
  "summary": "<1-2 sentence overall assessment>"
}}"""

TURN_POINTWISE_USER = """\
Evaluate the latest assistant response in this conversation.

Conversation:
{conversation_block}

Latest assistant response to evaluate:
{response_content}

{metadata_block}\
Score each criterion and return JSON."""

# =============================================================================
# TURN-LEVEL PAIRWISE EVALUATION
# =============================================================================

TURN_PAIRWISE_SYSTEM = """\
You are an expert LLM response evaluator performing a pairwise comparison. \
Your task is to compare two AI assistant responses (Response A and Response B) \
and determine which is better on each criterion.

{criteria_block}

IMPORTANT:
- Evaluate each response independently first, then compare
- Do NOT let the order of presentation bias your judgment
- Provide reasoning BEFORE declaring a winner for each criterion
- If responses are roughly equal on a criterion, you may declare a tie

Return ONLY valid JSON in this exact format:
{{
  "scores": [
    {{
      "criterion": "<criterion_name>",
      "reasoning": "<comparative analysis>",
      "evidence": ["<supporting quotes>"],
      "score_a": <integer>,
      "score_b": <integer>,
      "winner": "a" | "b" | "tie",
      "confidence": <float 0.0-1.0>
    }}
  ],
  "overall_winner": "a" | "b" | "tie",
  "summary": "<1-2 sentence comparison summary>"
}}"""

TURN_PAIRWISE_USER = """\
Compare these two responses to the same conversation.

Conversation context:
{conversation_block}

Response A:
{response_a}

Response B:
{response_b}

{metadata_block}\
Compare on each criterion and return JSON."""

# =============================================================================
# TURN-LEVEL REFERENCE-BASED EVALUATION
# =============================================================================

TURN_REFERENCE_SYSTEM = """\
You are an expert LLM response evaluator. Your task is to evaluate an AI assistant's \
response against specific quality criteria, using a reference (ideal) answer as a baseline.

{criteria_block}

Additionally, evaluate this criterion:
- **reference_alignment**: How well does the response align with the reference answer? \
Consider factual accuracy, completeness, and approach. Scale: {ref_scale}.

IMPORTANT:
- The reference answer represents the ideal response
- Score how close the actual response is to the reference
- A response can be good even if it differs from the reference in style
- Focus on substance, accuracy, and completeness

{additional_instructions}

Return ONLY valid JSON in this exact format:
{{
  "scores": [
    {{
      "criterion": "<criterion_name>",
      "reasoning": "<your step-by-step analysis>",
      "evidence": ["<quote or reference from the response>"],
      "score": <integer>,
      "confidence": <float 0.0-1.0>
    }}
  ],
  "summary": "<1-2 sentence overall assessment>"
}}"""

TURN_REFERENCE_USER = """\
Evaluate the assistant response against the reference answer.

Conversation:
{conversation_block}

Assistant response to evaluate:
{response_content}

Reference (ideal) answer:
{reference_answer}

{metadata_block}\
Score each criterion and return JSON."""

# =============================================================================
# CONVERSATION-LEVEL EVALUATION
# =============================================================================

CONVERSATION_SYSTEM = """\
You are an expert conversation evaluator. Your task is to evaluate an AI agent's \
behavior across an ENTIRE conversation, not just a single response.

You will assess the full conversation trajectory against policy criteria. \
Look for patterns, consistency, cumulative issues, and overall quality.

{criteria_block}

IMPORTANT:
- Evaluate the conversation AS A WHOLE, not individual turns
- Look for cross-turn patterns: drift, inconsistency, repeated failures
- Check if the agent stays on-task across the full session
- Identify cumulative issues that individual turn evaluations might miss
- Cite specific turn numbers as evidence (e.g., "In turn 3, the agent...")
- Consider: goal progression, promise fulfillment, behavioral consistency

{additional_instructions}

Return ONLY valid JSON in this exact format:
{{
  "scores": [
    {{
      "criterion": "<criterion_name>",
      "reasoning": "<analysis across the full conversation>",
      "evidence": ["<turn N: specific observation>"],
      "score": <integer>,
      "confidence": <float 0.0-1.0>
    }}
  ],
  "summary": "<1-2 sentence trajectory assessment>"
}}"""

CONVERSATION_USER = """\
Evaluate the agent's behavior across this entire conversation.

Full conversation ({turn_count} turns):
{conversation_block}

{metadata_block}\
Evaluate the full trajectory against each criterion and return JSON."""

# =============================================================================
# HELPERS
# =============================================================================


def format_criteria_block(criteria: list) -> str:
    """Format rubric criteria into a prompt block.

    Args:
        criteria: List of RubricCriterion objects.

    Returns:
        Formatted string describing each criterion.
    """
    lines = ["Evaluation criteria:"]
    for c in criteria:
        scale_desc = f"Scale: {c.scale.min_score}-{c.scale.max_score}"
        line = f"- **{c.name}**: {c.description} ({scale_desc})"
        if c.score_descriptions:
            descs = "; ".join(f"{k}={v}" for k, v in sorted(c.score_descriptions.items()))
            line += f"\n  Score guide: {descs}"
        lines.append(line)
    return "\n".join(lines)


def format_conversation_block(messages: list) -> str:
    """Format conversation messages into a readable block.

    Args:
        messages: List of message dicts with 'role' and 'content' keys.

    Returns:
        Formatted conversation string with turn numbers.
    """
    lines = []
    turn = 0
    for msg in messages:
        role = msg.get("role", "unknown")
        content = msg.get("content", "")
        if role == "system":
            lines.append(f"[System]: {content}")
        else:
            turn += 1
            lines.append(f"[Turn {turn} - {role}]: {content}")
    return "\n\n".join(lines)


def format_metadata_block(metadata: dict) -> str:
    """Format metadata into a prompt block.

    Args:
        metadata: Dict of metadata key-value pairs.

    Returns:
        Formatted metadata string, or empty string if no metadata.
    """
    if not metadata:
        return ""
    lines = ["Additional context:"]
    for key, value in metadata.items():
        lines.append(f"- {key}: {value}")
    return "\n".join(lines) + "\n\n"
