"""Tests for theme prompt builder and view helper functions.

Tests build_theme_prompt_vars and get_category_display_name.
All fields asserted on returned dicts. Minimum 1 error test per 2 happy path.
"""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

from unfamiliar.llm.missions.prompts import build_theme_prompt_vars
from unfamiliar.tui.themes.base import NarrativeConfig, ThemeConfig
from unfamiliar.tui.views import get_category_display_name

if TYPE_CHECKING:
    from unfamiliar.tui.themes.registry import ThemeRegistry


class TestBuildThemePromptVars:
    """Tests for build_theme_prompt_vars function."""

    def test_with_film_noir_theme_returns_themed_vars(
        self, theme_registry: ThemeRegistry
    ):
        """Film Noir ThemeConfig returns dict with Film Noir themed values."""
        theme = theme_registry.get("film_noir")

        result = build_theme_prompt_vars(theme)

        assert result["theme_name"] == "Film Noir"
        assert result["theme_title_examples"] == (
            '"The Password Vault", "Shadows in the Login Flow", '
            '"Following the Data Trail", "The Dead Drop in the Config", '
            '"Stakeout on the Event Loop"'
        )
        assert result["theme_intro_style"] == (
            "Set a moody, investigative tone. The detective discovers a new lead, "
            "finds a clue, or gets a tip from an informant."
        )
        assert result["theme_outro_style"] == (
            "Provide closure like a case being solved. The detective pieces together "
            "what they've learned, connecting it to the bigger picture."
        )

    def test_with_none_returns_generic_fallback(self):
        """build_theme_prompt_vars(None) returns dict with generic Investigation
        fallback values.
        """
        result = build_theme_prompt_vars(None)

        assert result["theme_name"] == "Investigation"
        assert (
            result["theme_title_examples"]
            == "Descriptive, engaging titles that reflect the investigation"
        )
        assert result["theme_intro_style"] == "Set the scene for the investigation"
        assert result["theme_outro_style"] == (
            "Summarize what was learned and connect it to the bigger picture"
        )

    def test_always_returns_four_keys(self, theme_registry: ThemeRegistry):
        """Both themed and fallback dicts have exactly the four required keys."""
        theme = theme_registry.get("film_noir")

        themed_result = build_theme_prompt_vars(theme)
        fallback_result = build_theme_prompt_vars(None)

        expected_keys = {
            "theme_name",
            "theme_title_examples",
            "theme_intro_style",
            "theme_outro_style",
        }

        assert set(themed_result.keys()) == expected_keys
        assert set(fallback_result.keys()) == expected_keys
        assert len(themed_result) == 4
        assert len(fallback_result) == 4

    def test_empty_narrative_fields_use_fallback(self):
        """ThemeConfig with empty narrative strings uses per-field fallback to
        generic text.
        """
        theme = ThemeConfig(
            name="empty_theme",
            display_name="Empty Theme",
            css_path=Path("/fake/path.tcss"),
            aliases={},
            vocabulary={},
            narrative=NarrativeConfig(
                tone="",
                title_examples=["Test Title"],
                intro_style="",
                outro_style="",
            ),
            colors={},
            decorations={},
            icons={},
        )

        result = build_theme_prompt_vars(theme)

        assert result["theme_name"] == "Empty Theme"
        assert result["theme_title_examples"] == '"Test Title"'
        assert result["theme_intro_style"] == "Set the scene for the investigation"
        assert result["theme_outro_style"] == (
            "Summarize what was learned and connect it to the bigger picture"
        )

    def test_title_examples_formatted_as_quoted_list(self):
        """title_examples list becomes comma-separated quoted strings."""
        theme = ThemeConfig(
            name="test_theme",
            display_name="Test Theme",
            css_path=Path("/fake/path.tcss"),
            aliases={},
            vocabulary={},
            narrative=NarrativeConfig(
                tone="Test tone",
                title_examples=["First Title", "Second Title", "Third Title"],
                intro_style="Test intro",
                outro_style="Test outro",
            ),
            colors={},
            decorations={},
            icons={},
        )

        result = build_theme_prompt_vars(theme)

        assert result["theme_title_examples"] == (
            '"First Title", "Second Title", "Third Title"'
        )

    def test_empty_title_examples_list_uses_fallback(self):
        """Empty title_examples list triggers fallback to generic text."""
        theme = ThemeConfig(
            name="no_titles",
            display_name="No Titles Theme",
            css_path=Path("/fake/path.tcss"),
            aliases={},
            vocabulary={},
            narrative=NarrativeConfig(
                tone="Test tone",
                title_examples=[],
                intro_style="Test intro",
                outro_style="Test outro",
            ),
            colors={},
            decorations={},
            icons={},
        )

        result = build_theme_prompt_vars(theme)

        assert (
            result["theme_title_examples"]
            == "Descriptive, engaging titles that reflect the investigation"
        )

    def test_none_narrative_uses_all_fallbacks(self):
        """ThemeConfig with narrative=None uses all fallback values except
        display_name.
        """
        theme = ThemeConfig(
            name="no_narrative",
            display_name="No Narrative Theme",
            css_path=Path("/fake/path.tcss"),
            aliases={},
            vocabulary={},
            narrative=None,
            colors={},
            decorations={},
            icons={},
        )

        result = build_theme_prompt_vars(theme)

        assert result["theme_name"] == "No Narrative Theme"
        assert (
            result["theme_title_examples"]
            == "Descriptive, engaging titles that reflect the investigation"
        )
        assert result["theme_intro_style"] == "Set the scene for the investigation"
        assert result["theme_outro_style"] == (
            "Summarize what was learned and connect it to the bigger picture"
        )


class TestGetCategoryDisplayName:
    """Tests for get_category_display_name function."""

    def test_known_category_domain_business_logic_returns_display_name(self):
        """domain_business_logic returns human-readable 'Domain & Business Logic'."""
        result = get_category_display_name("domain_business_logic")

        assert result == "Domain & Business Logic"

    def test_known_category_architecture_returns_display_name(self):
        """architecture returns human-readable 'Architecture'."""
        result = get_category_display_name("architecture")

        assert result == "Architecture"

    def test_known_category_technical_debt_returns_display_name(self):
        """technical_debt returns human-readable 'Technical Debt'."""
        result = get_category_display_name("technical_debt")

        assert result == "Technical Debt"

    def test_unknown_category_returns_key_titlecased(self):
        """Unknown category key returns titlecased version with underscores
        as spaces.
        """
        result = get_category_display_name("new_category")

        assert result == "New Category"

    def test_category_with_multiple_underscores_replaced_with_spaces(self):
        """Multi-word unknown category gets all underscores replaced with spaces."""
        result = get_category_display_name("some_new_thing")

        assert result == "Some New Thing"

    def test_unknown_category_with_special_format_preserves_capitalization(self):
        """Title casing capitalizes first letter of each word."""
        result = get_category_display_name("data_flow_analysis")

        assert result == "Data Flow Analysis"
