"""Comprehensive tests for new B2B transform operators."""

import pytest
import sys
import os

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
os.environ.setdefault("FM_COMPANY_TO_DOMAIN_REGISTRY", "false")
os.environ.setdefault("FM_COMPANY_TO_DOMAIN_WIKIDATA", "false")

from fmatch.saas.operators.detect_parent_company import detect_parent_company
from fmatch.saas.operators.classify_lead_source import classify_lead_source
from fmatch.saas.operators.company_size_bucket import company_size_bucket
from fmatch.saas.operators.normalize_phone_to_e164 import normalize_phone_to_e164


class TestDetectParentCompany:
    """Test parent company detection with B2B scenarios."""

    def test_domain_family_detection(self):
        """Test detection via domain families."""
        # WhatsApp -> Meta
        result = detect_parent_company(domain="whatsapp.com")
        assert result["parent"] == "Meta"
        assert result["ultimate_parent"] == "Meta Platforms Inc."
        assert result["confidence"] == 1.0
        assert result["relationship"] == "subsidiary"

        # LinkedIn -> Microsoft
        result = detect_parent_company(domain="linkedin.com")
        assert result["parent"] == "Microsoft"
        assert result["ultimate_parent"] == "Microsoft Corporation"
        assert result["confidence"] == 1.0

        # Subdomain detection
        result = detect_parent_company(domain="api.linkedin.com")
        assert result["parent"] == "Microsoft"
        assert result["confidence"] == 0.9

    def test_company_alias_detection(self):
        """Test detection via company aliases."""
        # WhatsApp company name
        result = detect_parent_company(company="WhatsApp")
        assert result["parent"] == "Meta"
        assert result["confidence"] == 0.8
        assert result["relationship"] == "brand"

        # AWS -> Amazon
        result = detect_parent_company(company="AWS")
        assert result["parent"] == "Amazon"
        assert result["ultimate_parent"] == "Amazon.com Inc."

        # Case insensitive
        result = detect_parent_company(company="amazon web services")
        assert result["parent"] == "Amazon"

    def test_combined_detection(self):
        """Test detection with multiple signals."""
        result = detect_parent_company(
            company="GitHub Inc.",
            website="https://github.com"
        )
        assert result["parent"] == "Microsoft"
        assert result["confidence"] == 1.0  # Domain match has highest confidence

    def test_no_parent_detection(self):
        """Test when no parent is detected."""
        result = detect_parent_company(company="Acme Corp")
        assert result["parent"] is None
        assert result["relationship"] == "unknown"
        assert result["confidence"] == 0.0

    def test_edge_cases(self):
        """Test edge cases and error handling."""
        # Empty inputs
        result = detect_parent_company()
        assert result["parent"] is None

        # None values
        result = detect_parent_company(company=None, domain=None)
        assert result["parent"] is None

        # Invalid domain
        result = detect_parent_company(domain="not-a-real-domain-xyz123")
        assert result["parent"] is None


class TestClassifyLeadSource:
    """Test lead source classification for marketing attribution."""

    def test_utm_precedence(self):
        """Test UTM parameters have highest precedence."""
        # PPC with utm_medium
        result = classify_lead_source(
            source="Some Random Source",
            utm={"utm_medium": "ppc", "utm_source": "google"}
        )
        assert result["channel"] == "paid_search"
        assert result["subchannel"] == "google"
        assert result["confidence"] == 0.9

        # Social paid
        result = classify_lead_source(
            utm={"utm_medium": "paid-social", "utm_source": "linkedin"}
        )
        assert result["channel"] == "paid_social"
        assert result["subchannel"] == "linkedin"

    def test_source_pattern_matching(self):
        """Test source string pattern matching."""
        # Google Ads
        result = classify_lead_source(source="Google Ads Campaign")
        assert result["channel"] == "paid_search"
        assert result["confidence"] == 0.7

        # Trade show
        result = classify_lead_source(source="Trade Show - Dreamforce 2024")
        assert result["channel"] == "events"

        # Email campaign
        result = classify_lead_source(source="Q4 Newsletter Campaign")
        assert result["channel"] == "email"

    def test_subchannel_extraction(self):
        """Test comprehensive subchannel extraction."""
        # Google Ads
        result = classify_lead_source(source="Google Ads PPC")
        assert result["subchannel"] == "google"

        # LinkedIn Ads
        result = classify_lead_source(source="LinkedIn Ads Campaign")
        assert result["subchannel"] == "linkedin"

        # Meta/Facebook
        result = classify_lead_source(source="Meta Ads Manager")
        assert result["subchannel"] == "facebook"

        # Instagram
        result = classify_lead_source(source="Instagram Ads")
        assert result["subchannel"] == "instagram"

    def test_referrer_fallback(self):
        """Test referrer as fallback signal."""
        result = classify_lead_source(referrer="https://www.google.com/search")
        assert result["channel"] == "organic_search"
        assert result["subchannel"] == "google"
        assert result["confidence"] == 0.5  # Lower confidence

    def test_social_organic_vs_paid(self):
        """Test distinction between organic and paid social."""
        # Paid social (utm_medium indicates paid)
        result = classify_lead_source(
            utm={"utm_source": "facebook", "utm_medium": "cpc"}
        )
        assert result["channel"] == "paid_social"

        # Organic social (no paid indicator)
        result = classify_lead_source(
            utm={"utm_source": "facebook", "utm_medium": "social"}
        )
        assert result["channel"] == "social_organic"

    def test_direct_traffic(self):
        """Test direct traffic classification."""
        # Empty source defaults to direct
        result = classify_lead_source(source="")
        assert result["channel"] == "direct"

        # Explicit direct
        result = classify_lead_source(source="Direct Traffic")
        assert result["channel"] == "direct"


class TestCompanySizeBucket:
    """Test enhanced company size bucketing."""

    def test_standard_bucketing(self):
        """Test standard numeric bucketing."""
        assert company_size_bucket(5)["value"] == "Startup"
        assert company_size_bucket(15)["value"] == "Small Business"
        assert company_size_bucket(100)["value"] == "SMB"
        assert company_size_bucket(250)["value"] == "Mid-Market"
        assert company_size_bucket(750)["value"] == "Commercial"
        assert company_size_bucket(2500)["value"] == "Enterprise"
        assert company_size_bucket(7500)["value"] == "Large Enterprise"
        assert company_size_bucket(15000)["value"] == "Strategic/Global"

    def test_k_suffix_parsing(self):
        """Test parsing of K/k suffixes."""
        # 10K+ format
        result = company_size_bucket("10K+")
        assert result["numeric"] == 10000
        assert result["segment_code"] == "large_enterprise"

        # 5k employees
        result = company_size_bucket("5k employees")
        assert result["numeric"] == 5000
        assert result["segment_code"] == "enterprise"

        # 15K
        result = company_size_bucket("15K")
        assert result["numeric"] == 15000
        assert result["segment_code"] == "strategic"

    def test_approximate_notation(self):
        """Test ~X approximate notation."""
        # ~5,000 employees
        result = company_size_bucket("~5,000 employees")
        assert result["numeric"] == 5000
        assert result["segment_code"] == "enterprise"

        # approximately 100
        result = company_size_bucket("approximately 100 people")
        assert result["numeric"] == 100
        assert result["segment_code"] == "smb"

    def test_range_parsing(self):
        """Test range parsing."""
        # 10k-15k
        result = company_size_bucket("10k-15k")
        assert result["value"] == "Strategic/Global"
        assert result["numeric"] == 12500  # Midpoint
        assert result["segment_code"] == "strategic"
        assert result["arr_potential"] == "$100M+"

        # 100-250 employees
        result = company_size_bucket("100-250 employees")
        assert result["value"] == "SMB"
        assert result["numeric"] == 175  # Midpoint
        assert result["segment_code"] == "smb"
        assert result["arr_potential"] == "$250K-$1M"

    def test_tier_assignment(self):
        """Test sales tier assignment."""
        assert company_size_bucket(10)["tier"] == "T4"  # Self-serve
        assert company_size_bucket(100)["tier"] == "T3"  # SMB Sales
        assert company_size_bucket(1000)["tier"] == "T2"  # Commercial routing
        assert company_size_bucket(3000)["tier"] == "T2"  # Enterprise Sales
        assert company_size_bucket(15000)["tier"] == "T1"  # Strategic Accounts

    def test_arr_potential(self):
        """Test ARR potential estimates."""
        assert company_size_bucket(5)["arr_potential"] == "$10K-$50K"
        assert company_size_bucket(100)["arr_potential"] == "$250K-$1M"
        assert company_size_bucket(1000)["arr_potential"] == "$5M-$10M"
        assert company_size_bucket(7500)["arr_potential"] == "$50M-$100M"
        assert company_size_bucket(15000)["arr_potential"] == "$100M+"

    def test_edge_cases(self):
        """Test edge cases."""
        # Empty/None
        assert company_size_bucket(None)["value"] is None
        assert company_size_bucket("")["value"] is None

        # Invalid strings
        result = company_size_bucket("no numbers here")
        assert result["value"] is None

        # Zero employees
        result = company_size_bucket(0)
        assert result["value"] is None
        assert result["segment_code"] == "unknown"


class TestNormalizePhoneWithExtensions:
    """Test phone normalization with extension preservation."""

    def test_extension_extraction(self):
        """Test extraction of various extension formats."""
        # x format
        result = normalize_phone_to_e164("(415) 555-0100 x456")
        assert result["extension"] == "456"
        assert result["value"] == "+14155550100"
        assert "x456" in result["formatted"]

        # ext. format
        result = normalize_phone_to_e164("415-555-0100 ext. 789")
        assert result["extension"] == "789"

        # extension format
        result = normalize_phone_to_e164("415-555-0100 extension 321")
        assert result["extension"] == "321"

        # # format
        result = normalize_phone_to_e164("415-555-0100 #123")
        assert result["extension"] == "123"

        # Comma format
        result = normalize_phone_to_e164("415-555-0100,456")
        assert result["extension"] == "456"

    def test_e164_with_extension(self):
        """Test E.164 formatting with extension."""
        result = normalize_phone_to_e164("(415) 555-1234 x789")
        assert result["valid"] is True
        assert result["value"] == "+14155551234"
        assert result["extension"] == "789"
        assert result["format"] == "E.164"

    def test_international_with_extension(self):
        """Test international numbers with extensions."""
        # UK number with extension
        result = normalize_phone_to_e164("020 7946 0958 x123", country="UK")
        assert result["value"] == "+442079460958"
        assert result["extension"] == "123"

    def test_no_extension(self):
        """Test numbers without extensions."""
        result = normalize_phone_to_e164("(415) 555-0100")
        assert result["extension"] is None
        assert result["value"] == "+14155550100"
        assert "x" not in result.get("formatted", "")

    def test_invalid_with_extension(self):
        """Test invalid numbers still preserve extensions."""
        result = normalize_phone_to_e164("invalid x456")
        assert result["extension"] == "456"
        assert result["valid"] is False

    def test_formatted_display(self):
        """Test formatted display with extensions."""
        # US format
        result = normalize_phone_to_e164("4155551234 x456")
        assert result["formatted"] == "+1 415-555-1234 x456"

        # Without extension
        result = normalize_phone_to_e164("4155551234")
        assert "x" not in result["formatted"]


def run_tests():
    """Run all tests and report results."""

    # Run pytest
    exit_code = pytest.main([__file__, "-v", "--tb=short"])

    if exit_code == 0:
        print("\n✅ All tests passed!")
    else:
        print(f"\n❌ Tests failed with exit code: {exit_code}")

    return exit_code


if __name__ == "__main__":
    exit(run_tests())
