import pytest
from app.services.blueprint import (
    get_default_blueprint, validate_blueprint, calculate_completeness,
    blueprint_to_prompt_spec, DEFAULT_SECTIONS, CONTENT_DEPTH_PRESETS,
)


class TestDefaultBlueprint:
    def test_returns_dict(self):
        bp = get_default_blueprint()
        assert isinstance(bp, dict)

    def test_has_sections(self):
        bp = get_default_blueprint()
        assert "sections" in bp
        assert len(bp["sections"]) > 0

    def test_has_global_settings(self):
        bp = get_default_blueprint()
        assert "global_settings" in bp
        assert "visual_settings" in bp

    def test_comprehensive_depth(self):
        bp = get_default_blueprint("comprehensive")
        assert bp["depth"] == "comprehensive"

    def test_legendary_depth(self):
        bp = get_default_blueprint("legendary")
        assert bp["depth"] == "legendary"

    def test_minimal_depth(self):
        bp = get_default_blueprint("minimal")
        assert bp["depth"] == "minimal"

    def test_unknown_depth_falls_back(self):
        bp = get_default_blueprint("nonexistent")
        assert bp["depth"] == "nonexistent"
        assert "sections" in bp

    def test_sections_have_required_keys(self):
        bp = get_default_blueprint()
        for section in bp["sections"]:
            assert "key" in section
            assert "label" in section
            assert "enabled" in section

    def test_all_depth_presets_exist(self):
        expected = {"minimal", "standard", "comprehensive", "legendary"}
        assert expected.issubset(set(CONTENT_DEPTH_PRESETS.keys()))


class TestValidateBlueprint:
    def test_valid_blueprint_passes(self):
        bp = get_default_blueprint()
        result = validate_blueprint(bp)
        assert result["valid"] is True
        assert len(result["errors"]) == 0

    def test_empty_sections_fails(self):
        result = validate_blueprint({"sections": []})
        assert result["valid"] is False

    def test_no_sections_key_fails(self):
        result = validate_blueprint({})
        assert result["valid"] is False

    def test_all_disabled_fails(self):
        bp = get_default_blueprint()
        for s in bp["sections"]:
            s["enabled"] = False
        result = validate_blueprint(bp)
        assert result["valid"] is False

    def test_missing_hero_fails(self):
        bp = get_default_blueprint()
        for s in bp["sections"]:
            if s["key"] == "hero":
                s["enabled"] = False
        result = validate_blueprint(bp)
        assert result["valid"] is False
        assert any("hero" in e for e in result["errors"])

    def test_missing_footer_fails(self):
        bp = get_default_blueprint()
        for s in bp["sections"]:
            if s["key"] == "footer":
                s["enabled"] = False
        result = validate_blueprint(bp)
        assert result["valid"] is False


class TestBlueprintToPromptSpec:
    def test_returns_tuple(self):
        bp = get_default_blueprint()
        result = blueprint_to_prompt_spec(bp)
        assert isinstance(result, tuple)
        assert len(result) == 2

    def test_prompt_spec_not_empty(self):
        bp = get_default_blueprint()
        prompt_spec, json_schema = blueprint_to_prompt_spec(bp)
        assert len(prompt_spec) > 0
        assert len(json_schema) > 0

    def test_legendary_uses_overrides(self):
        bp = get_default_blueprint("legendary")
        prompt_spec, _ = blueprint_to_prompt_spec(bp)
        assert "Fortune 500" in prompt_spec

    def test_disabled_sections_excluded(self):
        bp = get_default_blueprint()
        for s in bp["sections"]:
            if s["key"] == "gallery":
                s["enabled"] = False
        prompt_spec, json_schema = blueprint_to_prompt_spec(bp)
        assert "gallery" not in json_schema.lower()


class TestCalculateCompleteness:
    def test_empty_returns_zero(self):
        result = calculate_completeness({}, get_default_blueprint())
        assert result["score"] == 0 or result["filled"] == 0

    def test_none_inputs(self):
        result = calculate_completeness(None, None)
        assert result["score"] == 0

    def test_partial_fill(self):
        bp = get_default_blueprint()
        site_copy = {"hero": {"headline": "Test", "subheadline": "World"}}
        result = calculate_completeness(site_copy, bp)
        assert result["filled"] > 0
        assert result["total"] > result["filled"]


class TestDefaultSections:
    def test_section_count(self):
        assert len(DEFAULT_SECTIONS) >= 16

    def test_hero_and_footer_present(self):
        keys = [s["key"] for s in DEFAULT_SECTIONS]
        assert "hero" in keys
        assert "footer" in keys

    def test_all_sections_have_fields(self):
        for section in DEFAULT_SECTIONS:
            assert "fields" in section
            assert len(section["fields"]) > 0
