"""Prompt templates for mission generation.

Defines the ChatPromptTemplate used to generate structured investigation missions
for each category. Theme-specific narrative is injected via template variables.
"""

# ruff: noqa: E501 (long lines in prompt text are intentional for LLM consumption)
from __future__ import annotations

from typing import TYPE_CHECKING

from langchain_core.prompts import ChatPromptTemplate

if TYPE_CHECKING:
    from unfamiliar.tui.themes import ThemeConfig


def build_theme_prompt_vars(
    theme_config: ThemeConfig | None = None,
) -> dict[str, str]:
    """Build template variable dict for mission prompt from theme config.

    Args:
        theme_config: Optional theme configuration. If None or missing fields,
            generic investigation language is used as fallback.

    Returns:
        Dict with keys: theme_name, theme_title_examples, theme_intro_style,
        theme_outro_style. All values are guaranteed non-empty strings.
    """
    # Fallback defaults for generic investigation theme
    defaults = {
        "theme_name": "Investigation",
        "theme_title_examples": "Descriptive, engaging titles that reflect the investigation",
        "theme_intro_style": "Set the scene for the investigation",
        "theme_outro_style": (
            "Summarize what was learned and connect it to the bigger picture"
        ),
    }

    if theme_config is None:
        return defaults

    result = {"theme_name": theme_config.display_name}

    narrative = theme_config.narrative
    if narrative is not None:
        # Title examples: join list into formatted string
        if narrative.title_examples:
            result["theme_title_examples"] = ", ".join(
                f'"{ex}"' for ex in narrative.title_examples
            )
        else:
            result["theme_title_examples"] = defaults["theme_title_examples"]

        # Intro/outro styles: use if non-empty, else fallback
        result["theme_intro_style"] = (
            narrative.intro_style
            if narrative.intro_style
            else defaults["theme_intro_style"]
        )
        result["theme_outro_style"] = (
            narrative.outro_style
            if narrative.outro_style
            else defaults["theme_outro_style"]
        )
    else:
        # No narrative config at all
        result["theme_title_examples"] = defaults["theme_title_examples"]
        result["theme_intro_style"] = defaults["theme_intro_style"]
        result["theme_outro_style"] = defaults["theme_outro_style"]

    return result


MISSION_SYSTEM_PROMPT = """You are an expert mission designer for codebase investigation. Your task is to create engaging, educational missions that help developers understand unfamiliar codebases.

## Output Requirements

You will produce a structured JSON response with:
- **missions**: 3-8 investigation missions for the specified category
- **chains**: Optional groupings of related missions (0-3 chains)

## {theme_name} Theming

All mission titles and narrative text should use {theme_name} language:
- Example titles: {theme_title_examples}
- Narrative intros: {theme_intro_style}
- Narrative outros: {theme_outro_style}

## Difficulty Guidelines

- **quick** (10-15 min): Single file focus, straightforward investigation
- **medium** (20-30 min): 2-3 files, moderate complexity
- **deep_dive** (30-45 min): Multiple modules, complex patterns, architectural understanding

## Mission Design Principles

1. **Specific file references**: Use ONLY file paths from the "VALID FILE PATHS" list in the context. Never invent or guess paths.
2. **Conservative line numbers**: When specifying line ranges, be conservative — use ranges you're confident exist. If unsure, omit line numbers entirely rather than guessing.
3. **Clear completion conditions**: User should know when they've learned the concept
4. **Prerequisite logic**: Entry points before handlers, core before utilities
5. **Root missions**: At least 1-2 missions with no prerequisites (entry points to the category)
6. **Security awareness**: Mark missions involving auth, encryption, validation, or secrets

## Prerequisites

- Only reference missions within this same category (previous_missions list)
- Maximum 2 prerequisites per mission
- Create a learning progression: roots -> intermediate -> advanced
- Previous category missions are available for cross-category awareness but don't use them as prerequisites
- **CRITICAL: Every prerequisite_titles value MUST match the title_plain of another mission in THIS response.** Before finalizing, verify each prerequisite exists in your mission list.

## Module Linking

Use the module_index to link each mission to its primary module:
- Reference the module_descriptions list (0-indexed)
- Choose the most relevant module for the mission's focus
- If unsure or spanning modules, use index 0

## Chains

Chains group related missions into learning paths:
- Each chain has a `mission_titles` array listing the missions in order
- **CRITICAL: The `mission_titles` array MUST contain the exact `title_plain` values, NOT the {theme_name} themed `title` values
- For example, if a mission has `title_plain="Understand Factory Pattern"`, the chain must use `mission_titles=["Understand Factory Pattern"]`, not `["The Factory Floor"]`
- **CRITICAL: Every mission_titles value MUST match the title_plain of a mission in THIS response.** Only chain missions you actually created.
"""

MISSION_HUMAN_PROMPT = """Generate investigation missions for the **{category}** category.

## Codebase Briefing Summary

{briefing_summary}

## Category-Specific Context

{category_context}

## Module Descriptions (use index in module_index field)

{module_descriptions}

## Previous Mission Titles (from earlier categories, for awareness only)

{previous_missions}

---

Remember:
- Generate 3-8 missions specific to the {category} category
- At least 1-2 root missions (empty prerequisite_titles)
- Use ONLY file paths from the "VALID FILE PATHS" list — never invent paths
- Use {theme_name} theming for titles and narrative
- Maximum 2 prerequisites per mission (only from this category)
- **Self-consistency check:** Every prerequisite and chain reference MUST match a title_plain you create in this response"""

MISSION_PROMPT = ChatPromptTemplate.from_messages(
    [
        ("system", MISSION_SYSTEM_PROMPT),
        ("human", MISSION_HUMAN_PROMPT),
    ]
)
