"""
Contract test for L2A /run endpoint - prevents UnboundLocalError regression
============================================================================
"""
import pytest
import sys
sys.path.insert(0, 'src')

from unittest.mock import Mock, patch, AsyncMock
from fastapi.testclient import TestClient
from sqlalchemy.ext.asyncio import AsyncSession


class TestL2ARunContract:
    """Contract test to ensure /api/v2/l2a/run doesn't crash with UnboundLocalError"""
    
    @pytest.fixture
    def mock_db(self):
        """Mock database session"""
        db = AsyncMock(spec=AsyncSession)
        
        # Mock L2A policy exists
        mock_policy = Mock(
            id="test-policy-id",
            account_id="test-account",
            status="ACTIVE",
            upgrade_enablement="disabled",
            upgrade_min_gain=0.2,
            upgrade_min_score=0.7,
            upgrade_anchor_required=False,
            use_multi_algo=False
        )
        
        db.execute.return_value.scalar_one_or_none.return_value = mock_policy
        db.execute.return_value.scalars.return_value.all.return_value = []
        return db
    
    @pytest.fixture
    def mock_sf_client(self):
        """Mock Salesforce client"""
        sf = Mock()
        
        async def mock_soql(query, **kwargs):
            return {"records": [], "done": True}
        
        sf.soql = AsyncMock(side_effect=mock_soql)
        return sf
    
    @pytest.fixture
    def mock_integration(self):
        """Mock Salesforce integration"""
        from src.fmatch.saas.models import Integration, IntegrationProvider, IntegrationStatus
        
        return Mock(
            spec=Integration,
            id="test-integration",
            account_id="test-account",
            provider=IntegrationProvider.SALESFORCE,
            status=IntegrationStatus.CONNECTED,
            credentials={"access_token": "test-token", "instance_url": "https://test.salesforce.com"}
        )
    
    @pytest.fixture
    def client(self, mock_db, mock_sf_client, mock_integration):
        """Create test client with mocks"""
        from src.fmatch.saas.main import app
        from src.fmatch.saas.db import get_session
        
        async def override_get_session():
            return mock_db
        
        app.dependency_overrides[get_session] = override_get_session
        
        # Mock Salesforce client creation
        with patch('src.fmatch.saas.api.v2.l2a.SalesforceClient') as mock_sf_class:
            mock_sf_class.return_value = mock_sf_client
            
            # Mock integration lookup
            mock_db.execute.return_value.scalar_one_or_none.side_effect = [
                mock_integration,  # First call for integration
                mock_integration,  # Second call if needed
            ]
            
            client = TestClient(app)
            yield client
        
        # Clean up
        app.dependency_overrides.clear()
    
    def test_run_no_unboundlocal(self, client, monkeypatch):
        """Test that /api/v2/l2a/run doesn't raise UnboundLocalError"""
        # Set development mode for auth bypass
        monkeypatch.setenv("ENV", "development")
        monkeypatch.setenv("ALLOW_INSECURE_API_KEY_FALLBACK", "true")
        
        # Make the POST request
        response = client.post(
            "/api/v2/l2a/run",
            json={},  # Empty body or minimal config
            headers={"Authorization": "Bearer dev-token"}
        )
        
        # Should return success (200/202) not 500 with UnboundLocalError
        assert response.status_code in (200, 202, 422), f"Expected success, got {response.status_code}: {response.text}"
        
        # Check response structure
        if response.status_code == 200:
            payload = response.json()
            # Should have some expected fields
            assert "status" in payload or "message" in payload or "policy_id" in payload
    
    def test_run_imports_registry(self, client, monkeypatch):
        """Test that domain registry imports work correctly"""
        monkeypatch.setenv("ENV", "development")
        
        # Mock the domain registry to verify it's called
        with patch('src.fmatch.saas.services.l2a_service_intelligent.get_registry') as mock_get_reg:
            mock_reg = Mock()
            mock_reg.alias_to_family = {"google.com": "alphabet"}
            mock_get_reg.return_value = mock_reg
            
            response = client.post(
                "/api/v2/l2a/run",
                json={},
                headers={"Authorization": "Bearer dev-token"}
            )
            
            # Verify get_registry was called (no UnboundLocalError)
            assert mock_get_reg.called, "get_registry should be called during run"
            
            # Should not crash
            assert response.status_code != 500, f"Got 500 error: {response.text}"
    
    def test_run_handles_missing_policy(self, client, mock_db, monkeypatch):
        """Test graceful handling when no L2A policy exists"""
        monkeypatch.setenv("ENV", "development")
        
        # Mock no policy found
        mock_db.execute.return_value.scalar_one_or_none.return_value = None
        
        response = client.post(
            "/api/v2/l2a/run",
            json={},
            headers={"Authorization": "Bearer dev-token"}
        )
        
        # Should return appropriate error, not crash
        assert response.status_code in (404, 422), f"Expected 404/422 for missing policy, got {response.status_code}"
        
        if response.status_code == 404:
            payload = response.json()
            assert "detail" in payload
            assert "policy" in payload["detail"].lower()


def test_direct_import():
    """Test that domain_family imports work directly"""
    try:
        from src.fmatch.saas.services.l2a_service_intelligent import get_registry, DomainRelation
        
        # Should be callable
        reg = get_registry()
        assert reg is not None
        
        # Should have expected attributes
        assert hasattr(reg, 'alias_to_family')
        
        # DomainRelation should be an enum
        assert hasattr(DomainRelation, 'EXACT')
        assert hasattr(DomainRelation, 'FAMILY')
        assert hasattr(DomainRelation, 'NONE')
        
        print("✓ Direct imports work correctly")
        
    except ImportError as e:
        pytest.fail(f"Import failed: {e}")
    except UnboundLocalError as e:
        pytest.fail(f"UnboundLocalError during import: {e}")


if __name__ == "__main__":
    # Test direct imports
    test_direct_import()
    
    # Run pytest for contract tests
    pytest.main([__file__, "-v"])