"""Tests for content generator module."""

from src.content_generator.geo_optimizer import GEOOptimizer, GEOResult
from src.content_generator.schema_builder import FAQItem, SchemaBuilder
from src.content_generator.seo_optimizer import SEOOptimizer, SEOResult
from src.content_generator.template_engine import TemplateEngine


class TestSEOOptimizer:
    """Test SEO Optimizer."""

    def test_initialization(self):
        """Test optimizer initialization."""
        opt = SEOOptimizer()
        assert opt.ideal_keyword_density == 1.5
        assert opt.title_max_length == 60
        assert opt.meta_max_length == 160

    def test_calculate_keyword_density(self):
        """Test keyword density calculation."""
        opt = SEOOptimizer()
        content = "SEO is important for SEO. SEO helps with SEO."
        density = opt.calculate_keyword_density(content, "SEO")
        assert density > 0
        assert isinstance(density, float)

    def test_calculate_keyword_density_zero(self):
        """Test keyword density with no matches."""
        opt = SEOOptimizer()
        content = "This content has no keyword."
        density = opt.calculate_keyword_density(content, "missing")
        assert density == 0.0

    def test_calculate_readability(self):
        """Test readability calculation."""
        opt = SEOOptimizer()
        content = "This is a simple sentence. It is easy to read."
        score = opt.calculate_readability(content)
        assert 0 <= score <= 100
        assert isinstance(score, float)

    def test_calculate_readability_empty(self):
        """Test readability with empty content."""
        opt = SEOOptimizer()
        assert opt.calculate_readability("") == 0.0

    def test_optimize_title(self):
        """Test title optimization."""
        opt = SEOOptimizer()
        result = opt.optimize_title("Best SEO Tools for 2024", "SEO tools")
        assert isinstance(result, dict)
        assert "score" in result
        assert "length" in result
        assert result["length"] == len("Best SEO Tools for 2024")

    def test_optimize_title_too_long(self):
        """Test title optimization with long title."""
        opt = SEOOptimizer()
        long_title = "a" * 70
        result = opt.optimize_title(long_title, "keyword")
        assert result["score"] < 100  # Penalty for long title

    def test_optimize_title_missing_keyword(self):
        """Test title optimization without keyword."""
        opt = SEOOptimizer()
        result = opt.optimize_title("Best Tools for 2024", "SEO")
        assert result["score"] < 100  # Penalty for missing keyword

    def test_generate_meta_description(self):
        """Test meta description generation."""
        opt = SEOOptimizer()
        content = "This is a test content about digital marketing strategies."
        meta = opt.generate_meta_description(content, "digital marketing")
        assert len(meta) <= 160
        assert "digital marketing" in meta.lower()

    def test_optimize(self):
        """Test full SEO optimization."""
        opt = SEOOptimizer()
        content = "SEO is important. SEO helps websites rank better. SEO is essential."
        result = opt.optimize(content, "SEO", "SEO Guide")
        assert isinstance(result, SEOResult)
        assert result.keyword_density > 0
        assert 0 <= result.readability_score <= 100
        assert isinstance(result.suggestions, list)

    def test_optimize_suggestions_low_density(self):
        """Test suggestions for low keyword density."""
        opt = SEOOptimizer()
        content = "This content has very few mentions of the keyword."
        result = opt.optimize(content, "missing", "Title")
        assert any("偏低" in s or "low" in s.lower() for s in result.suggestions)


class TestGEOOptimizer:
    """Test GEO Optimizer."""

    def test_initialization(self):
        """Test optimizer initialization."""
        opt = GEOOptimizer()
        assert len(opt.question_patterns) == 3

    def test_extract_entities(self):
        """Test entity extraction."""
        opt = GEOOptimizer()
        content = "Google and Microsoft are tech companies. Amazon is also big."
        entities = opt.extract_entities(content)
        assert "Google" in entities
        assert "Microsoft" in entities
        assert "Amazon" in entities

    def test_extract_entities_empty(self):
        """Test entity extraction with no entities."""
        opt = GEOOptimizer()
        content = "this is just lowercase text"
        entities = opt.extract_entities(content)
        assert len(entities) == 0

    def test_calculate_entity_density(self):
        """Test entity density calculation."""
        opt = GEOOptimizer()
        content = "Google and Microsoft released new products today."
        density = opt.calculate_entity_density(content)
        assert density > 0
        assert isinstance(density, float)

    def test_calculate_entity_density_zero(self):
        """Test entity density with no entities."""
        opt = GEOOptimizer()
        content = "this has no proper nouns"
        density = opt.calculate_entity_density(content)
        assert density == 0.0

    def test_calculate_semantic_completeness(self):
        """Test semantic completeness calculation."""
        opt = GEOOptimizer()
        content = "# Title\\n\\n1. First point\\n\\nDetailed paragraph here."
        score = opt.calculate_semantic_completeness(content)
        assert 0 <= score <= 100

    def test_calculate_semantic_completeness_low(self):
        """Test semantic completeness with poor structure."""
        opt = GEOOptimizer()
        content = "Just a short text without structure."
        score = opt.calculate_semantic_completeness(content)
        assert score < 100

    def test_optimize(self):
        """Test full GEO optimization."""
        opt = GEOOptimizer()
        content = "Google and Microsoft are leading AI development."
        result = opt.optimize(content)
        assert isinstance(result, GEOResult)
        assert 0 <= result.score <= 100
        assert isinstance(result.entity_density, float)
        assert isinstance(result.ai_summary, str)

    def test_optimize_suggestions(self):
        """Test GEO suggestions."""
        opt = GEOOptimizer()
        content = "this is just regular text without many entities"
        result = opt.optimize(content)
        assert len(result.suggestions) > 0


class TestSchemaBuilder:
    """Test Schema Builder."""

    def test_initialization(self):
        """Test builder initialization."""
        builder = SchemaBuilder()
        assert builder is not None

    def test_build_faq_schema(self):
        """Test FAQ schema generation."""
        builder = SchemaBuilder()
        items = [
            FAQItem("What is SEO?", "SEO is search engine optimization."),
            FAQItem("Why SEO matters?", "It helps websites rank better."),
        ]
        schema = builder.build_faq_schema(items)
        assert schema["@context"] == "https://schema.org"
        assert schema["@type"] == "FAQPage"
        assert len(schema["mainEntity"]) == 2

    def test_build_howto_schema(self):
        """Test HowTo schema generation."""
        builder = SchemaBuilder()
        steps = ["Step 1: Do this", "Step 2: Do that", "Step 3: Finish"]
        schema = builder.build_howto_schema("How to Learn SEO", steps)
        assert schema["@context"] == "https://schema.org"
        assert schema["@type"] == "HowTo"
        assert schema["name"] == "How to Learn SEO"
        assert len(schema["step"]) == 3

    def test_build_article_schema(self):
        """Test Article schema generation."""
        builder = SchemaBuilder()
        schema = builder.build_article_schema(
            "Test Article", "This is a description.", "Author Name", "2024-01-01"
        )
        assert schema["@type"] == "Article"
        assert schema["headline"] == "Test Article"


class TestTemplateEngine:
    """Test Template Engine."""

    def test_initialization(self):
        """Test engine initialization."""
        engine = TemplateEngine()
        assert engine is not None

    def test_render(self):
        """Test template rendering."""
        engine = TemplateEngine()
        template = "Hello {{ name }}!"
        result = engine.render(template, {"name": "World"})
        assert result == "Hello World!"

    def test_render_with_condition(self):
        """Test template with condition."""
        engine = TemplateEngine()
        template = "{% if show %}Visible{% endif %}"
        result = engine.render(template, {"show": True})
        assert result == "Visible"

    def test_render_with_loop(self):
        """Test template with loop."""
        engine = TemplateEngine()
        template = "{% for item in items %}{{ item }}{% endfor %}"
        result = engine.render(template, {"items": ["a", "b", "c"]})
        assert result == "abc"
