import pytest
from aura_core.valuation.engine import (
    compute_domain_intrinsic,
    classify_monetization,
    estimate_monthly_traffic,
    compute_revenue_by_model,
    valuate_domain,
    BUSINESS_MODELS,
    TLD_MULTIPLIERS,
)
from aura_core.types import DomainIntrinsic, ValuationResult


class TestDomainIntrinsic:
    def test_short_com_domain(self):
        result = compute_domain_intrinsic("ai.com")
        assert result.tld == ".com"
        assert result.tld_multiplier == 1.0
        assert result.length <= 3
        assert result.length_score == 1.0
        assert result.has_hyphens is False
        assert result.domain_only_value > 100000

    def test_medium_com_domain(self):
        result = compute_domain_intrinsic("fitness.com")
        assert result.length == 7
        assert result.length_score == 0.65
        assert result.domain_only_value > 10000

    def test_long_domain_penalty(self):
        result = compute_domain_intrinsic("superlongdomainnamehere.com")
        assert result.length_score == 0.15
        assert result.domain_only_value < 5000

    def test_hyphen_penalty(self):
        clean = compute_domain_intrinsic("mysite.com")
        hyphenated = compute_domain_intrinsic("my-site.com")
        assert hyphenated.has_hyphens is True
        assert hyphenated.domain_only_value < clean.domain_only_value

    def test_number_penalty(self):
        clean = compute_domain_intrinsic("tools.com")
        numbered = compute_domain_intrinsic("tools123.com")
        assert numbered.has_numbers is True
        assert numbered.domain_only_value < clean.domain_only_value

    def test_unknown_tld(self):
        result = compute_domain_intrinsic("test.xyz")
        assert result.tld == ".xyz"
        assert result.tld_multiplier == 0.20

    def test_fallback_tld(self):
        result = compute_domain_intrinsic("test.museum")
        assert result.tld_multiplier == 0.25

    def test_no_tld_defaults_com(self):
        result = compute_domain_intrinsic("nodot")
        assert result.tld == ".com"

    def test_raw_score_capped_at_one(self):
        result = compute_domain_intrinsic("ai.com")
        assert result.raw_score <= 1.0


class TestClassifyMonetization:
    def test_affiliate(self):
        assert classify_monetization("affiliate marketing") == "affiliate"

    def test_saas(self):
        assert classify_monetization("SaaS subscription") == "saas"

    def test_digital(self):
        assert classify_monetization("digital products") == "digital"

    def test_ecommerce(self):
        assert classify_monetization("ecommerce store") == "ecommerce_dropship"

    def test_services(self):
        assert classify_monetization("consulting services") == "services"

    def test_empty_defaults_affiliate(self):
        assert classify_monetization("") == "affiliate"
        assert classify_monetization(None) == "affiliate"

    def test_unknown_defaults_affiliate(self):
        assert classify_monetization("something random") == "affiliate"


class TestTrafficEstimate:
    def test_basic_traffic(self):
        domain_score = DomainIntrinsic(
            domain_name="test.com", name_part="test", tld=".com",
            length=4, tld_multiplier=1.0, length_score=0.85,
            has_hyphens=False, has_numbers=False, raw_score=0.85,
            domain_only_value=50000,
        )
        niche = {
            "target_audience": "Developers, Testers",
            "affiliate_programs": ["Prog1", "Prog2"],
            "time_to_revenue": "fast",
        }
        traffic = estimate_monthly_traffic(niche, domain_score)
        assert traffic.monthly_visitors_low >= 200
        assert traffic.monthly_visitors_high > traffic.monthly_visitors_low
        assert traffic.monthly_visitors_mid == (traffic.monthly_visitors_low + traffic.monthly_visitors_high) // 2

    def test_slow_market_heat(self):
        domain_score = DomainIntrinsic(
            domain_name="test.com", name_part="test", tld=".com",
            length=4, tld_multiplier=1.0, length_score=0.85,
            has_hyphens=False, has_numbers=False, raw_score=0.85,
            domain_only_value=50000,
        )
        niche_fast = {"target_audience": "Dev", "affiliate_programs": [], "time_to_revenue": "fast"}
        niche_slow = {"target_audience": "Dev", "affiliate_programs": [], "time_to_revenue": "slow"}
        fast = estimate_monthly_traffic(niche_fast, domain_score)
        slow = estimate_monthly_traffic(niche_slow, domain_score)
        assert fast.monthly_visitors_high > slow.monthly_visitors_high


class TestRevenueByModel:
    def test_returns_models(self):
        from aura_core.types import TrafficEstimate
        traffic = TrafficEstimate(
            audience_segments=2, affiliate_count=3, market_heat=1.0,
            monthly_visitors_low=500, monthly_visitors_high=2000,
            monthly_visitors_mid=1250,
        )
        niche = {"monetization_model": "affiliate", "requires_inventory": False}
        models = compute_revenue_by_model(traffic, niche)
        assert len(models) >= 2
        assert models[0].is_primary_fit is True

    def test_primary_model_first(self):
        from aura_core.types import TrafficEstimate
        traffic = TrafficEstimate(
            audience_segments=2, affiliate_count=3, market_heat=1.0,
            monthly_visitors_low=500, monthly_visitors_high=2000,
            monthly_visitors_mid=1250,
        )
        niche = {"monetization_model": "saas", "requires_inventory": False}
        models = compute_revenue_by_model(traffic, niche)
        primary = [m for m in models if m.is_primary_fit]
        assert len(primary) == 1
        assert primary[0].model_key == "saas"


class TestValuateDomain:
    def test_full_valuation(self):
        analysis = {
            "niches": [{
                "name": "Test Niche", "monetization_model": "affiliate",
                "target_audience": "Developers", "time_to_revenue": "medium",
                "valuation_band": "5000-20000",
                "affiliate_programs": ["Prog1"], "requires_inventory": False,
            }]
        }
        result = valuate_domain("test.com", analysis)
        assert isinstance(result, ValuationResult)
        assert result.domain == "test.com"
        assert result.niches_evaluated == 1
        assert result.domain_only_value > 0
        assert result.best_developed_value >= 0
        assert len(result.niche_valuations) == 1

    def test_empty_niches(self):
        result = valuate_domain("test.com", {"niches": []})
        assert result.niches_evaluated == 0
        assert result.best_developed_value == 0

    def test_missing_niches_key(self):
        result = valuate_domain("test.com", {})
        assert result.niches_evaluated == 0

    def test_multiple_niches(self):
        analysis = {
            "niches": [
                {"name": "Niche A", "monetization_model": "affiliate",
                 "target_audience": "Group A", "time_to_revenue": "fast",
                 "valuation_band": "10000-30000", "affiliate_programs": ["X"],
                 "requires_inventory": False},
                {"name": "Niche B", "monetization_model": "saas",
                 "target_audience": "Group B", "time_to_revenue": "slow",
                 "valuation_band": "20000-80000", "affiliate_programs": [],
                 "requires_inventory": False},
            ]
        }
        result = valuate_domain("premium.com", analysis)
        assert result.niches_evaluated == 2
        assert result.best_developed_value > 0


class TestBusinessModelsData:
    def test_all_models_have_required_fields(self):
        required = ["label", "fulfillment_cost_pct", "startup_cost_low",
                     "startup_cost_high", "margin_pct", "monthly_overhead_low",
                     "monthly_overhead_high", "scalability", "risk_factor"]
        for key, model in BUSINESS_MODELS.items():
            for field in required:
                assert field in model, f"{key} missing {field}"

    def test_six_models(self):
        assert len(BUSINESS_MODELS) == 6

    def test_tld_multipliers_com_is_one(self):
        assert TLD_MULTIPLIERS[".com"] == 1.0
