"""
Unit tests for domain families admin endpoints
"""
import pytest
from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock


class TestAdminDomainFamiliesEndpoints:
    """Test admin domain families API endpoints"""
    
    @pytest.fixture
    def client(self):
        """Create test client"""
        from src.fmatch.saas.main import app
        return TestClient(app)
    
    @pytest.fixture
    def auth_headers(self):
        """Auth headers for testing"""
        return {"Authorization": "Bearer test-token"}
    
    @pytest.fixture
    def mock_registry(self):
        """Mock domain family registry"""
        mock_reg = MagicMock()
        mock_reg.alias_to_family = {
            "google.com": "alphabet",
            "youtube.com": "alphabet",
            "microsoft.com": "microsoft",
            "github.com": "microsoft"
        }
        return mock_reg
    
    def test_get_domain_families_full(self, client, auth_headers, mock_registry):
        """Test GET /api/v2/admin/domain-families (full mode)"""
        with patch('src.fmatch.saas.api.v2.admin_domain_families.get_registry', return_value=mock_registry):
            with patch('src.fmatch.saas.api.v2.admin_domain_families.get_current_account', return_value="test-account"):
                response = client.get(
                    "/api/v2/admin/domain-families",
                    headers=auth_headers
                )
                
                assert response.status_code == 200
                data = response.json()
                
                # Check response structure
                assert "version" in data
                assert "count" in data
                assert "alias_to_family" in data
                
                # Check data values
                assert data["count"] == 4
                assert data["alias_to_family"]["google.com"] == "alphabet"
    
    def test_get_domain_families_summary(self, client, auth_headers, mock_registry):
        """Test GET /api/v2/admin/domain-families?summary=true"""
        with patch('src.fmatch.saas.api.v2.admin_domain_families.get_registry', return_value=mock_registry):
            with patch('src.fmatch.saas.api.v2.admin_domain_families.get_current_account', return_value="test-account"):
                response = client.get(
                    "/api/v2/admin/domain-families?summary=true",
                    headers=auth_headers
                )
                
                assert response.status_code == 200
                data = response.json()
                
                # Check summary structure
                assert "version" in data
                assert "count" in data
                assert "family_count" in data
                assert "top_families" in data
                
                # Should NOT have full alias map in summary mode
                assert "alias_to_family" not in data
                
                # Check family count
                assert data["family_count"] == 2  # alphabet and microsoft
    
    def test_get_domain_families_summary_endpoint(self, client, auth_headers, mock_registry):
        """Test GET /api/v2/admin/domain-families/summary"""
        with patch('src.fmatch.saas.api.v2.admin_domain_families.get_registry', return_value=mock_registry):
            with patch('src.fmatch.saas.api.v2.admin_domain_families.get_current_account', return_value="test-account"):
                response = client.get(
                    "/api/v2/admin/domain-families/summary",
                    headers=auth_headers
                )
                
                assert response.status_code == 200
                data = response.json()
                
                # Check lightweight summary structure
                assert "version" in data
                assert "total_domains" in data
                assert "total_families" in data
                assert "top_families" in data
                
                # Should be lightweight (no full mappings)
                assert "alias_to_family" not in data
                
                assert data["total_domains"] == 4
                assert data["total_families"] == 2
    
    def test_reload_domain_families(self, client, auth_headers, mock_registry):
        """Test POST /api/v2/admin/reload-domain-families"""
        mock_registry.refresh = MagicMock()
        
        with patch('src.fmatch.saas.api.v2.admin_domain_families.get_registry', return_value=mock_registry):
            with patch('src.fmatch.saas.api.v2.admin_domain_families.get_current_account', return_value="test-account"):
                response = client.post(
                    "/api/v2/admin/reload-domain-families",
                    headers=auth_headers
                )
                
                assert response.status_code == 200
                data = response.json()
                
                # Check response
                assert data["status"] == "ok"
                assert "message" in data
                assert "version_before" in data
                assert "version_after" in data
                assert "reloaded_families" in data
                
                # Verify refresh was called
                mock_registry.refresh.assert_called_once_with(force=True)
    
    def test_unauthorized_access(self, client):
        """Test endpoints require authentication"""
        # No auth header should fail
        response = client.get("/api/v2/admin/domain-families")
        assert response.status_code in [401, 403]
        
        response = client.post("/api/v2/admin/reload-domain-families")
        assert response.status_code in [401, 403]
    
    def test_version_hash_stability(self, mock_registry):
        """Test that registry version hash is stable"""
        from src.fmatch.saas.api.v2.admin_domain_families import _registry_digest
        
        # Same registry should produce same hash
        hash1 = _registry_digest(mock_registry)
        hash2 = _registry_digest(mock_registry)
        assert hash1 == hash2
        
        # Hash should be 12 characters
        assert len(hash1) == 12
        
        # Different registry should produce different hash
        mock_reg2 = MagicMock()
        mock_reg2.alias_to_family = {"example.com": "example"}
        hash3 = _registry_digest(mock_reg2)
        assert hash3 != hash1
    
    def test_top_families_calculation(self, mock_registry):
        """Test top families calculation"""
        from src.fmatch.saas.api.v2.admin_domain_families import _get_top_families
        
        # Add more domains to test counting
        mock_registry.alias_to_family = {
            "google.com": "alphabet",
            "youtube.com": "alphabet",
            "android.com": "alphabet",
            "microsoft.com": "microsoft",
            "github.com": "microsoft",
            "example.com": "example"
        }
        
        top = _get_top_families(mock_registry, limit=2)
        
        # Should return top 2 families by count
        assert len(top) == 2
        assert top[0][0] == "alphabet"  # 3 domains
        assert top[0][1] == 3
        assert top[1][0] == "microsoft"  # 2 domains
        assert top[1][1] == 2


class TestAdminEndpointIntegration:
    """Integration tests for admin endpoints with actual registry"""
    
    @pytest.mark.integration
    def test_real_registry_loading(self):
        """Test with real domain family registry"""
        from src.fmatch.saas.services.domain_family import get_registry
        
        reg = get_registry()
        
        # Registry should load
        assert reg is not None
        assert hasattr(reg, 'alias_to_family')
        
        # Should have some domains if seed file exists
        # (may be empty if no seed file)
        assert isinstance(reg.alias_to_family, dict)
    
    @pytest.mark.integration
    def test_registry_refresh_logging(self, caplog):
        """Test that refresh operations are logged"""
        from src.fmatch.saas.api.v2.admin_domain_families import reload_domain_families
        import logging
        
        # Set log level to capture info logs
        caplog.set_level(logging.INFO)
        
        # Mock the dependencies
        with patch('src.fmatch.saas.api.v2.admin_domain_families.get_current_account', return_value="test-account"):
            with patch('src.fmatch.saas.api.v2.admin_domain_families.get_registry') as mock_get_reg:
                mock_reg = MagicMock()
                mock_reg.alias_to_family = {"test.com": "test"}
                mock_reg.refresh = MagicMock()
                mock_get_reg.return_value = mock_reg
                
                # Call reload
                import asyncio
                result = asyncio.run(reload_domain_families(account_id="test-account"))
                
                # Check audit log was written
                assert "Domain families reloaded by account_id=test-account" in caplog.text


if __name__ == "__main__":
    pytest.main([__file__, "-v"])