"""母题库模块TDD测试

测试策略：
- 测试母题模板数据结构
- 测试Prompt渲染逻辑
- 不使用Mock进行业务逻辑测试
"""
import pytest

from app.services.content.topic_templates import (
    TopicTemplate,
    TOPIC_TEMPLATES,
    get_topic_template,
    list_topic_templates,
    render_topic_prompt,
)


# ============================================================================
# 母题模板测试
# ============================================================================

class TestTopicTemplate:
    """母题模板数据结构测试"""

    def test_topic_template_attributes(self):
        """测试母题模板属性"""
        template = TOPIC_TEMPLATES["product_comparison"]

        assert template.id == "product_comparison"
        assert template.name == "产品对比"
        assert template.icon == "⚖️"
        assert "prompt_template" in template.prompt_template
        assert len(template.seo_tips) > 0
        assert len(template.recommended_platforms) > 0
        assert template.word_count_range[0] < template.word_count_range[1]

    def test_topic_template_required_params(self):
        """测试母题必填参数"""
        template = TOPIC_TEMPLATES["product_comparison"]

        assert "brand_name" in template.required_params
        assert "competitor_name" in template.required_params
        assert "comparison_dimensions" in template.required_params
        assert "keywords" in template.required_params

    def test_topic_template_optional_params(self):
        """测试母题可选参数"""
        template = TOPIC_TEMPLATES["product_comparison"]

        assert "content_style" in template.optional_params
        assert "word_count" in template.optional_params


class TestAllTopicTemplates:
    """所有母题模板测试"""

    def test_all_templates_have_valid_structure(self):
        """测试所有模板具有有效结构"""
        for topic_id, template in TOPIC_TEMPLATES.items():
            assert template.id == topic_id
            assert template.name
            assert template.description
            assert template.icon
            assert template.prompt_template
            assert len(template.seo_tips) > 0
            assert len(template.recommended_platforms) > 0
            assert template.word_count_range[0] > 0
            assert template.word_count_range[1] > template.word_count_range[0]
            assert len(template.required_params) > 0

    def test_all_templates_have_prompt_placeholders(self):
        """测试所有模板包含Prompt占位符"""
        for topic_id, template in TOPIC_TEMPLATES.items():
            prompt = template.prompt_template
            for param in template.required_params:
                assert f"{{{param}}}" in prompt, f"Template {topic_id} missing placeholder {{{param}}}"

    def test_all_templates_referenced_in_prompt(self):
        """测试所有参数都在Prompt中使用"""
        for topic_id, template in TOPIC_TEMPLATES.items():
            prompt = template.prompt_template
            all_params = template.required_params + template.optional_params

            for param in all_params:
                if "{" + param + "}" in prompt:
                    # 如果占位符存在，它应该被正确使用
                    pass


# ============================================================================
# 母题模板列表测试
# ============================================================================

class TestTopicTemplateFunctions:
    """母题模板函数测试"""

    def test_get_existing_template(self):
        """测试获取已存在的模板"""
        template = get_topic_template("product_comparison")

        assert template is not None
        assert template.id == "product_comparison"

    def test_get_nonexistent_template(self):
        """测试获取不存在的模板"""
        template = get_topic_template("nonexistent")

        assert template is None

    def test_list_topic_templates(self):
        """测试列出所有模板"""
        templates = list_topic_templates()

        assert len(templates) == 8
        assert all(isinstance(t, TopicTemplate) for t in templates)

    def test_list_templates_contains_all_ids(self):
        """测试列出所有模板ID"""
        templates = list_topic_templates()
        template_ids = [t.id for t in templates]

        for topic_id in TOPIC_TEMPLATES.keys():
            assert topic_id in template_ids


# ============================================================================
# Prompt渲染测试
# ============================================================================

class TestRenderTopicPrompt:
    """Prompt渲染测试"""

    def test_render_product_comparison_prompt(self):
        """测试渲染产品对比Prompt"""
        params = {
            "brand_name": "华为",
            "competitor_name": "小米",
            "comparison_dimensions": "性能、价格、外观",
            "keywords": "手机,5G,性价比",
            "content_style": "专业",
            "word_count": 2000,
        }

        prompt = render_topic_prompt("product_comparison", params)

        assert "华为" in prompt
        assert "小米" in prompt
        assert "性能、价格、外观" in prompt
        assert "手机,5G,性价比" in prompt
        assert "2000" in prompt

    def test_render_how_to_guide_prompt(self):
        """测试渲染使用指南Prompt"""
        params = {
            "product_name": "iPhone 15",
            "core_features": "拍照、续航、系统",
            "keywords": "iPhone,苹果,手机",
        }

        prompt = render_topic_prompt("how_to_guide", params)

        assert "iPhone 15" in prompt
        assert "拍照、续航、系统" in prompt

    def test_render_industry_trends_prompt(self):
        """测试渲染行业趋势Prompt"""
        params = {
            "industry_name": "新能源汽车",
            "brand_perspective": "技术创新",
            "keywords": "电动车,电池,自动驾驶",
        }

        prompt = render_topic_prompt("industry_trends", params)

        assert "新能源汽车" in prompt
        assert "技术创新" in prompt

    def test_render_with_default_params(self):
        """测试使用默认参数渲染"""
        params = {
            "brand_name": "测试品牌",
            "competitor_name": "竞品",
            "comparison_dimensions": "功能",
            "keywords": "关键词",
        }

        prompt = render_topic_prompt("product_comparison", params)

        # content_style和word_count应有默认值
        assert "content_style" not in params or "专业" in prompt or "专业" in params.get("content_style", "")

    def test_render_nonexistent_template_raises_error(self):
        """测试渲染不存在的模板抛出错误"""
        with pytest.raises(ValueError, match="Unknown topic"):
            render_topic_prompt("nonexistent_topic", {})


# ============================================================================
# 各母题模板内容测试
# ============================================================================

class TestProductComparison:
    """产品对比母题测试"""

    def test_template_has_comparison_structure(self):
        """测试模板包含对比结构"""
        template = TOPIC_TEMPLATES["product_comparison"]

        prompt = template.prompt_template

        # 验证包含对比维度
        assert "对比" in prompt
        # 验证包含SEO提示
        assert any("对比" in tip for tip in template.seo_tips)


class TestHowToGuide:
    """使用指南母题测试"""

    def test_template_has_step_structure(self):
        """测试模板包含步骤结构"""
        template = TOPIC_TEMPLATES["how_to_guide"]

        prompt = template.prompt_template

        # 验证包含步骤相关关键词
        assert "步骤" in prompt or "教程" in prompt or "使用" in prompt


class TestIndustryTrends:
    """行业趋势母题测试"""

    def test_template_has_trend_analysis(self):
        """测试模板包含趋势分析"""
        template = TOPIC_TEMPLATES["industry_trends"]

        prompt = template.prompt_template

        # 验证包含趋势相关关键词
        assert "趋势" in prompt or "分析" in prompt or "预测" in prompt


class TestExpertOpinion:
    """专家观点母题测试"""

    def test_template_has_expert_identity(self):
        """测试模板包含专家身份"""
        template = TOPIC_TEMPLATES["expert_opinion"]

        assert "expert_identity" in template.required_params
        assert "core_opinion" in template.required_params


class TestCaseStudy:
    """案例研究母题测试"""

    def test_template_has_case_structure(self):
        """测试模板包含案例结构"""
        template = TOPIC_TEMPLATES["case_study"]

        prompt = template.prompt_template

        assert "case_name" in template.required_params
        assert "company_background" in template.required_params


class TestDataReport:
    """数据报告母题测试"""

    def test_template_has_data_structure(self):
        """测试模板包含数据报告结构"""
        template = TOPIC_TEMPLATES["data_report"]

        assert "report_topic" in template.required_params
        assert "data_scope" in template.required_params
        assert "core_findings" in template.required_params

        # 数据报告字数范围应较大
        assert template.word_count_range[0] >= 2000


class TestFAQ:
    """问题解答母题测试"""

    def test_template_has_faq_structure(self):
        """测试模板包含FAQ结构"""
        template = TOPIC_TEMPLATES["faq"]

        prompt = template.prompt_template

        assert "questions" in template.required_params
        # FAQ字数范围应较小
        assert template.word_count_range[1] <= 2500


class TestReview:
    """评测报告母题测试"""

    def test_template_has_review_structure(self):
        """测试模板包含评测结构"""
        template = TOPIC_TEMPLATES["review"]

        prompt = template.prompt_template

        assert "product_name" in template.required_params
        assert "review_dimensions" in template.required_params
        # 评测应包含优缺点
        assert "优" in prompt or "缺" in prompt or "评测" in prompt


# ============================================================================
# SEO提示测试
# ============================================================================

class TestSEOTips:
    """SEO提示测试"""

    def test_all_templates_have_seo_tips(self):
        """测试所有模板都有SEO提示"""
        for topic_id, template in TOPIC_TEMPLATES.items():
            assert len(template.seo_tips) > 0, f"Template {topic_id} missing SEO tips"

    def test_seo_tips_are_descriptive(self):
        """测试SEO提示具有描述性"""
        for topic_id, template in TOPIC_TEMPLATES.items():
            for tip in template.seo_tips:
                assert len(tip) > 5, f"Template {topic_id} has too short SEO tip"


# ============================================================================
# 推荐平台测试
# ============================================================================

class TestRecommendedPlatforms:
    """推荐平台测试"""

    def test_all_templates_have_recommended_platforms(self):
        """测试所有模板都有推荐平台"""
        for topic_id, template in TOPIC_TEMPLATES.items():
            assert len(template.recommended_platforms) > 0, f"Template {topic_id} missing platforms"

    def test_platforms_are_valid(self):
        """测试平台名称有效"""
        common_platforms = {"知乎", "百家号", "公众号", "小红书", "简书", "微博"}

        for topic_id, template in TOPIC_TEMPLATES.items():
            for platform in template.recommended_platforms:
                # 平台应该在常见平台列表中或是有效的
                assert platform, f"Template {topic_id} has empty platform name"
