import pytest
from aura_core.validator.engine import (
    validate_analysis,
    validate_brand,
    validate_site_copy,
    validate_package,
    ValidationReporter,
)


class TestValidationReporter:
    def test_empty_report_is_valid(self):
        r = ValidationReporter("test")
        assert r.is_valid is True
        assert r.score == 100

    def test_error_invalidates(self):
        r = ValidationReporter("test")
        r.error("field", "broken")
        assert r.is_valid is False
        assert r.score < 100

    def test_warning_reduces_score(self):
        r = ValidationReporter("test")
        r.warn("field", "odd")
        assert r.is_valid is True
        assert r.score < 100

    def test_repair_tracked(self):
        r = ValidationReporter("test")
        r.repair("field", "fixed it")
        assert r.is_valid is True
        assert len(r.repairs) == 1

    def test_to_dict(self):
        r = ValidationReporter("ctx")
        r.error("a", "bad")
        r.warn("b", "meh")
        r.repair("a", "fixed")
        d = r.to_dict()
        assert d["context"] == "ctx"
        assert d["valid"] is False
        assert d["error_count"] == 1
        assert d["warning_count"] == 1
        assert d["repair_count"] == 1


class TestValidateAnalysis:
    def test_valid_analysis(self):
        data = {
            "domain": "test.com",
            "keywords": ["test"],
            "niches": [{"name": "N", "description": "D"}],
        }
        result, report = validate_analysis(data)
        assert report.is_valid is True

    def test_missing_required_domain(self):
        data = {"keywords": ["test"], "niches": [{"name": "N", "description": "D"}]}
        result, report = validate_analysis(data)
        assert report.is_valid is False

    def test_missing_keywords(self):
        data = {"domain": "test.com", "niches": [{"name": "N", "description": "D"}]}
        result, report = validate_analysis(data)
        assert report.is_valid is False

    def test_missing_niches(self):
        data = {"domain": "test.com", "keywords": ["test"]}
        result, report = validate_analysis(data)
        assert report.is_valid is False

    def test_auto_repair_coerces_string_to_list(self):
        data = {"domain": "test.com", "keywords": "singleword", "niches": [{"name": "N", "description": "D"}]}
        result, report = validate_analysis(data, auto_repair=True)
        assert isinstance(result["keywords"], list)
        assert len(report.repairs) > 0

    def test_auto_repair_wraps_single_niche_dict(self):
        data = {"domain": "test.com", "keywords": ["test"], "niches": {"name": "N", "description": "D"}}
        result, report = validate_analysis(data, auto_repair=True)
        assert isinstance(result["niches"], list)

    def test_niche_defaults_applied(self):
        data = {"domain": "test.com", "keywords": ["test"], "niches": [{"name": "N", "description": "D"}]}
        result, report = validate_analysis(data, auto_repair=True)
        niche = result["niches"][0]
        assert "score" in niche
        assert "monetization_model" in niche

    def test_non_dict_rejected(self):
        result, report = validate_analysis("not a dict")
        assert report.is_valid is False

    def test_empty_dict(self):
        result, report = validate_analysis({})
        assert report.is_valid is False


class TestValidateBrand:
    def test_valid_brand(self):
        data = {"options": [{"name": "Brand", "tagline": "Tag"}], "recommended": 0}
        result, report = validate_brand(data)
        assert report.is_valid is True

    def test_missing_options(self):
        data = {"recommended": 0}
        result, report = validate_brand(data)
        assert report.is_valid is False

    def test_auto_repair_non_dict(self):
        result, report = validate_brand("broken", auto_repair=True)
        assert isinstance(result, dict)
        assert "options" in result

    def test_recommended_out_of_range(self):
        data = {"options": [{"name": "A"}], "recommended": 5}
        result, report = validate_brand(data, auto_repair=True)
        assert result["recommended"] == 0

    def test_color_defaults(self):
        data = {"options": [{"name": "A"}]}
        result, report = validate_brand(data, auto_repair=True)
        assert "color_primary" in result


class TestValidateSiteCopy:
    def test_valid_site_copy(self):
        data = {"headline": "Welcome", "subheadline": "Hello"}
        result, report = validate_site_copy(data)
        assert report.is_valid is True

    def test_non_dict_repaired(self):
        result, report = validate_site_copy("broken", auto_repair=True)
        assert isinstance(result, dict)

    def test_string_field_coercion(self):
        data = {"headline": 12345}
        result, report = validate_site_copy(data, auto_repair=True)
        assert isinstance(result["headline"], str)

    def test_list_field_validation(self):
        data = {"features": [{"title": "F1", "description": "D1"}]}
        result, report = validate_site_copy(data)
        assert report.is_valid is True

    def test_nested_wrapper_unwrap(self):
        data = {"features": {"features": [{"title": "F1", "description": "D1"}]}}
        result, report = validate_site_copy(data, auto_repair=True)
        assert isinstance(result["features"], list)

    def test_alias_resolution(self):
        data = {"features": [{"heading": "F1", "text": "D1"}]}
        result, report = validate_site_copy(data, auto_repair=True)
        assert result["features"][0].get("title") == "F1"
        assert result["features"][0].get("description") == "D1"

    def test_misplacement_detection(self):
        data = {"features": [{"question": "Q?", "answer": "A."}]}
        result, report = validate_site_copy(data, auto_repair=True)
        assert len(result.get("faq_items", [])) > 0


class TestValidatePackage:
    def test_full_package(self):
        data = {
            "brand": {"options": [{"name": "B"}]},
            "site_copy": {"headline": "Hi"},
            "sales_letter": "Buy now",
        }
        result, report = validate_package(data)
        assert report.is_valid is True

    def test_sales_letter_coercion(self):
        data = {
            "brand": {"options": [{"name": "B"}]},
            "site_copy": {"headline": "Hi"},
            "sales_letter": 12345,
        }
        result, report = validate_package(data, auto_repair=True)
        assert isinstance(result["sales_letter"], str)
