"""
Unit tests for contract serializers.
Tests read-only fields, serializer method fields, and validation logic.
"""
from unittest.mock import Mock, MagicMock, patch
from datetime import datetime, timedelta
from decimal import Decimal
import pytest

from smoothschedule.scheduling.contracts.serializers import (
    ContractTemplateSerializer,
    ContractTemplateListSerializer,
    ServiceContractRequirementSerializer,
    ContractSignatureSerializer,
    ContractSerializer,
    ContractListSerializer,
    PublicContractSerializer,
    ContractSignatureInputSerializer,
    CreateContractSerializer,
)
from smoothschedule.scheduling.contracts.models import (
    ContractTemplate,
    Contract,
    ContractSignature,
)


class TestContractTemplateSerializer:
    """Test ContractTemplateSerializer read-only fields and method fields."""

    def test_read_only_fields(self):
        """Verify version, created_by, created_at, updated_at are read-only."""
        serializer = ContractTemplateSerializer()
        read_only = serializer.Meta.read_only_fields

        assert "version" in read_only
        assert "created_by" in read_only
        assert "created_at" in read_only
        assert "updated_at" in read_only

    def test_all_expected_fields_present(self):
        """Verify all expected fields are included."""
        serializer = ContractTemplateSerializer()
        fields = serializer.Meta.fields

        expected_fields = [
            "id", "name", "description", "content", "scope", "status",
            "expires_after_days", "version", "version_notes", "services",
            "created_by", "created_by_name", "created_at", "updated_at"
        ]

        for field in expected_fields:
            assert field in fields

    def test_get_services_returns_service_list(self):
        """Test get_services method returns list of service dicts."""
        # Arrange
        mock_service1 = Mock()
        mock_service1.id = 1
        mock_service1.name = "Service A"

        mock_service2 = Mock()
        mock_service2.id = 2
        mock_service2.name = "Service B"

        mock_requirement1 = Mock()
        mock_requirement1.service = mock_service1

        mock_requirement2 = Mock()
        mock_requirement2.service = mock_service2

        mock_queryset = Mock()
        mock_queryset.select_related.return_value = [mock_requirement1, mock_requirement2]

        mock_template = Mock()
        mock_template.service_requirements = mock_queryset

        serializer = ContractTemplateSerializer()

        # Act
        result = serializer.get_services(mock_template)

        # Assert
        assert len(result) == 2
        assert result[0] == {"id": 1, "name": "Service A"}
        assert result[1] == {"id": 2, "name": "Service B"}
        mock_queryset.select_related.assert_called_once_with("service")

    def test_get_services_returns_empty_list_when_no_requirements(self):
        """Test get_services returns empty list when no service requirements."""
        mock_queryset = Mock()
        mock_queryset.select_related.return_value = []

        mock_template = Mock()
        mock_template.service_requirements = mock_queryset

        serializer = ContractTemplateSerializer()
        result = serializer.get_services(mock_template)

        assert result == []

    def test_get_created_by_name_with_full_name(self):
        """Test get_created_by_name returns full name when available."""
        mock_user = Mock()
        mock_user.get_full_name.return_value = "John Doe"
        mock_user.email = "john@example.com"

        mock_template = Mock()
        mock_template.created_by = mock_user

        serializer = ContractTemplateSerializer()
        result = serializer.get_created_by_name(mock_template)

        assert result == "John Doe"

    def test_get_created_by_name_falls_back_to_email(self):
        """Test get_created_by_name returns email when full name is empty."""
        mock_user = Mock()
        mock_user.get_full_name.return_value = ""
        mock_user.email = "john@example.com"

        mock_template = Mock()
        mock_template.created_by = mock_user

        serializer = ContractTemplateSerializer()
        result = serializer.get_created_by_name(mock_template)

        assert result == "john@example.com"

    def test_get_created_by_name_returns_none_when_no_creator(self):
        """Test get_created_by_name returns None when created_by is None."""
        mock_template = Mock()
        mock_template.created_by = None

        serializer = ContractTemplateSerializer()
        result = serializer.get_created_by_name(mock_template)

        assert result is None


class TestContractTemplateListSerializer:
    """Test ContractTemplateListSerializer lightweight fields."""

    def test_contains_only_essential_fields(self):
        """Verify list serializer only includes lightweight fields."""
        serializer = ContractTemplateListSerializer()
        fields = serializer.Meta.fields

        expected_fields = [
            "id", "name", "description", "content", "scope",
            "status", "version", "expires_after_days"
        ]

        assert set(fields) == set(expected_fields)

    def test_does_not_include_heavy_fields(self):
        """Verify list serializer excludes heavy computed fields."""
        serializer = ContractTemplateListSerializer()
        fields = serializer.Meta.fields

        # Should not include these expensive fields
        assert "services" not in fields
        assert "created_by_name" not in fields


class TestServiceContractRequirementSerializer:
    """Test ServiceContractRequirementSerializer read-only nested fields."""

    def test_read_only_nested_fields(self):
        """Verify template_name, template_scope, service_name are read-only."""
        serializer = ServiceContractRequirementSerializer()

        # These should be read-only because they use source with read_only=True
        assert serializer.fields["template_name"].read_only is True
        assert serializer.fields["template_scope"].read_only is True
        assert serializer.fields["service_name"].read_only is True

    def test_all_expected_fields_present(self):
        """Verify all expected fields are included."""
        serializer = ServiceContractRequirementSerializer()
        fields = serializer.Meta.fields

        expected_fields = [
            "id", "service", "service_name", "template", "template_name",
            "template_scope", "display_order", "is_required", "created_at"
        ]

        for field in expected_fields:
            assert field in fields


class TestContractSignatureSerializer:
    """Test ContractSignatureSerializer fields."""

    def test_all_expected_fields_present(self):
        """Verify all signature fields are included."""
        serializer = ContractSignatureSerializer()
        fields = serializer.Meta.fields

        expected_fields = [
            "signed_at", "signer_name", "signer_email", "ip_address",
            "consent_checkbox_checked", "electronic_consent_given"
        ]

        assert set(fields) == set(expected_fields)


class TestContractSerializer:
    """Test ContractSerializer read-only fields and method fields."""

    def test_read_only_fields(self):
        """Verify critical fields are read-only."""
        serializer = ContractSerializer()
        read_only = serializer.Meta.read_only_fields

        assert "template_version" in read_only
        assert "content_html" in read_only
        assert "content_hash" in read_only
        assert "signing_token" in read_only
        assert "sent_at" in read_only
        assert "created_at" in read_only
        assert "updated_at" in read_only

    def test_all_expected_fields_present(self):
        """Verify all expected fields are included."""
        serializer = ContractSerializer()
        fields = serializer.Meta.fields

        expected_fields = [
            "id", "template", "template_name", "template_version", "title",
            "content_html", "customer", "customer_name", "customer_email",
            "event", "status", "expires_at", "is_signed", "signature_details",
            "signing_url", "pdf_path", "sent_at", "created_at", "updated_at"
        ]

        for field in expected_fields:
            assert field in fields

    def test_signature_details_is_nested_serializer(self):
        """Verify signature_details uses ContractSignatureSerializer."""
        serializer = ContractSerializer()
        sig_field = serializer.fields["signature_details"]

        assert sig_field.source == "signature"
        assert sig_field.read_only is True

    def test_get_customer_name_with_full_name(self):
        """Test get_customer_name returns full name when available."""
        mock_customer = Mock()
        mock_customer.get_full_name.return_value = "Jane Smith"
        mock_customer.email = "jane@example.com"

        mock_contract = Mock()
        mock_contract.customer = mock_customer

        serializer = ContractSerializer()
        result = serializer.get_customer_name(mock_contract)

        assert result == "Jane Smith"

    def test_get_customer_name_falls_back_to_email(self):
        """Test get_customer_name returns email when full name is empty."""
        mock_customer = Mock()
        mock_customer.get_full_name.return_value = ""
        mock_customer.email = "jane@example.com"

        mock_contract = Mock()
        mock_contract.customer = mock_customer

        serializer = ContractSerializer()
        result = serializer.get_customer_name(mock_contract)

        assert result == "jane@example.com"

    def test_get_template_name_from_template(self):
        """Test get_template_name returns template name when template exists."""
        mock_template = Mock()
        mock_template.name = "Service Agreement"

        mock_contract = Mock()
        mock_contract.template = mock_template
        mock_contract.title = "Contract Title"

        serializer = ContractSerializer()
        result = serializer.get_template_name(mock_contract)

        assert result == "Service Agreement"

    def test_get_template_name_falls_back_to_title(self):
        """Test get_template_name returns contract title when no template."""
        mock_contract = Mock()
        mock_contract.template = None
        mock_contract.title = "Custom Contract Title"

        serializer = ContractSerializer()
        result = serializer.get_template_name(mock_contract)

        assert result == "Custom Contract Title"

    def test_get_is_signed_returns_true_when_signed(self):
        """Test get_is_signed returns True when status is SIGNED."""
        mock_contract = Mock()
        mock_contract.status = Contract.Status.SIGNED

        serializer = ContractSerializer()
        result = serializer.get_is_signed(mock_contract)

        assert result is True

    def test_get_is_signed_returns_false_when_pending(self):
        """Test get_is_signed returns False when status is PENDING."""
        mock_contract = Mock()
        mock_contract.status = Contract.Status.PENDING

        serializer = ContractSerializer()
        result = serializer.get_is_signed(mock_contract)

        assert result is False

    def test_get_signing_url_calls_contract_method(self):
        """Test get_signing_url passes request to contract method."""
        mock_request = Mock()
        mock_contract = Mock()
        mock_contract.get_signing_url.return_value = "http://example.com/sign/abc123"

        serializer = ContractSerializer(context={"request": mock_request})
        result = serializer.get_signing_url(mock_contract)

        mock_contract.get_signing_url.assert_called_once_with(mock_request)
        assert result == "http://example.com/sign/abc123"

    def test_get_signing_url_without_request_in_context(self):
        """Test get_signing_url works when request is not in context."""
        mock_contract = Mock()
        mock_contract.get_signing_url.return_value = "/sign/abc123"

        serializer = ContractSerializer(context={})
        result = serializer.get_signing_url(mock_contract)

        mock_contract.get_signing_url.assert_called_once_with(None)
        assert result == "/sign/abc123"


class TestContractListSerializer:
    """Test ContractListSerializer lightweight fields."""

    def test_all_expected_fields_present(self):
        """Verify all expected fields are included."""
        serializer = ContractListSerializer()
        fields = serializer.Meta.fields

        expected_fields = [
            "id", "template", "title", "content_html", "customer", "customer_name",
            "customer_email", "status", "is_signed", "template_name",
            "template_version", "expires_at", "sent_at", "signed_at",
            "created_at", "signing_token"
        ]

        for field in expected_fields:
            assert field in fields

    def test_get_signed_at_with_signature(self):
        """Test get_signed_at returns signature date when exists."""
        mock_signed_at = datetime(2024, 1, 15, 10, 30)
        mock_signature = Mock()
        mock_signature.signed_at = mock_signed_at

        mock_contract = Mock()
        mock_contract.signature = mock_signature

        serializer = ContractListSerializer()
        result = serializer.get_signed_at(mock_contract)

        assert result == mock_signed_at

    def test_get_signed_at_without_signature(self):
        """Test get_signed_at returns None when no signature."""
        mock_contract = Mock(spec=[])  # No signature attribute

        serializer = ContractListSerializer()
        result = serializer.get_signed_at(mock_contract)

        assert result is None

    def test_get_signed_at_with_none_signature(self):
        """Test get_signed_at returns None when signature is None."""
        mock_contract = Mock()
        mock_contract.signature = None

        serializer = ContractListSerializer()
        result = serializer.get_signed_at(mock_contract)

        assert result is None


class TestPublicContractSerializer:
    """Test PublicContractSerializer representation logic."""

    def test_to_representation_with_all_fields(self):
        """Test full representation with tenant, customer, and event."""
        # Arrange
        now = datetime(2024, 1, 15, 12, 0)

        with patch('django.db.connection') as mock_connection, \
             patch('django.utils.timezone.now') as mock_timezone_now, \
             patch('smoothschedule.identity.core.models.Tenant') as mock_tenant_model:

            mock_timezone_now.return_value = now
            mock_connection.schema_name = "demo"

            mock_tenant = Mock()
            mock_tenant.name = "ACME Corp"
            mock_tenant.logo = Mock()
            mock_tenant.logo.url = "https://example.com/logo.png"
            mock_tenant_model.objects.get.return_value = mock_tenant

            mock_customer = Mock()
            mock_customer.get_full_name.return_value = "John Doe"
            mock_customer.email = "john@example.com"

            mock_service = Mock()
            mock_service.name = "Consultation"

            mock_event = Mock()
            mock_event.service = mock_service
            mock_event.start_time = datetime(2024, 1, 20, 14, 0)

            mock_template = Mock()
            mock_template.name = "Service Agreement"

            mock_contract = Mock()
            mock_contract.id = "12345"
            mock_contract.title = "Service Agreement"
            mock_contract.content_html = "<p>Contract content</p>"
            mock_contract.status = Contract.Status.PENDING
            mock_contract.expires_at = datetime(2024, 2, 15, 12, 0)
            mock_contract.template = mock_template
            mock_contract.customer = mock_customer
            mock_contract.event = mock_event

            # No signature
            mock_contract.signature = None

            serializer = PublicContractSerializer()

            # Act
            result = serializer.to_representation(mock_contract)

            # Assert
            assert result["contract"]["id"] == "12345"
            assert result["contract"]["title"] == "Service Agreement"
            assert result["contract"]["content"] == "<p>Contract content</p>"
            assert result["contract"]["status"] == Contract.Status.PENDING
            assert result["contract"]["expires_at"] == "2024-02-15T12:00:00"

            assert result["template"]["name"] == "Service Agreement"
            assert result["template"]["content"] == "<p>Contract content</p>"

            assert result["business"]["name"] == "ACME Corp"
            assert result["business"]["logo_url"] == "https://example.com/logo.png"

            assert result["customer"]["name"] == "John Doe"
            assert result["customer"]["email"] == "john@example.com"

            assert result["appointment"]["service_name"] == "Consultation"
            assert result["appointment"]["start_time"] == "2024-01-20T14:00:00"

            assert result["is_expired"] is False
            assert result["can_sign"] is True
            assert result["signature"] is None

    def test_to_representation_with_expired_contract(self):
        """Test representation marks contract as expired and cannot sign."""
        # Arrange
        now = datetime(2024, 2, 20, 12, 0)

        with patch('django.db.connection') as mock_connection, \
             patch('django.utils.timezone.now') as mock_timezone_now, \
             patch('smoothschedule.identity.core.models.Tenant') as mock_tenant_model:

            mock_timezone_now.return_value = now
            mock_connection.schema_name = "demo"
            mock_tenant = Mock()
            mock_tenant.name = "Business"
            mock_tenant.logo = None
            mock_tenant_model.objects.get.return_value = mock_tenant

            mock_customer = Mock()
            mock_customer.get_full_name.return_value = "Jane Smith"
            mock_customer.email = "jane@example.com"

            mock_template = Mock()
            mock_template.name = "Agreement"

            mock_contract = Mock()
            mock_contract.id = "67890"
            mock_contract.title = "Agreement"
            mock_contract.content_html = "<p>Content</p>"
            mock_contract.status = Contract.Status.PENDING
            mock_contract.expires_at = datetime(2024, 2, 15, 12, 0)  # Expired
            mock_contract.template = mock_template
            mock_contract.customer = mock_customer
            mock_contract.event = None
            mock_contract.signature = None

            serializer = PublicContractSerializer()

            # Act
            result = serializer.to_representation(mock_contract)

            # Assert
            assert result["is_expired"] is True
            assert result["can_sign"] is False  # Cannot sign expired contract

    def test_to_representation_with_signed_contract(self):
        """Test representation with signed contract."""
        # Arrange
        now = datetime(2024, 1, 15, 12, 0)

        with patch('django.db.connection') as mock_connection, \
             patch('django.utils.timezone.now') as mock_timezone_now, \
             patch('smoothschedule.identity.core.models.Tenant') as mock_tenant_model:

            mock_timezone_now.return_value = now
            mock_connection.schema_name = "demo"
            mock_tenant = Mock()
            mock_tenant.name = "Business"
            mock_tenant.logo = None
            mock_tenant_model.objects.get.return_value = mock_tenant

            mock_customer = Mock()
            mock_customer.get_full_name.return_value = "Bob Jones"
            mock_customer.email = "bob@example.com"

            mock_template = Mock()
            mock_template.name = "NDA"

            mock_signature = Mock()
            mock_signature.signer_name = "Bob Jones"
            mock_signature.signer_email = "bob@example.com"
            mock_signature.signed_at = datetime(2024, 1, 10, 9, 30)

            mock_contract = Mock()
            mock_contract.id = "11111"
            mock_contract.title = "NDA"
            mock_contract.content_html = "<p>NDA content</p>"
            mock_contract.status = Contract.Status.SIGNED
            mock_contract.expires_at = None
            mock_contract.template = mock_template
            mock_contract.customer = mock_customer
            mock_contract.event = None
            mock_contract.signature = mock_signature

            serializer = PublicContractSerializer()

            # Act
            result = serializer.to_representation(mock_contract)

            # Assert
            assert result["is_expired"] is False
            assert result["can_sign"] is False  # Already signed
            assert result["signature"]["signer_name"] == "Bob Jones"
            assert result["signature"]["signer_email"] == "bob@example.com"
            assert result["signature"]["signed_at"] == "2024-01-10T09:30:00"

    def test_to_representation_with_no_tenant(self):
        """Test representation falls back when tenant not found."""
        # Arrange
        from django.core.exceptions import ObjectDoesNotExist
        now = datetime(2024, 1, 15, 12, 0)

        with patch('django.db.connection') as mock_connection, \
             patch('django.utils.timezone.now') as mock_timezone_now, \
             patch('smoothschedule.identity.core.models.Tenant') as mock_tenant_model:

            mock_timezone_now.return_value = now
            mock_connection.schema_name = "demo"
            # Mock the DoesNotExist exception properly
            mock_tenant_model.DoesNotExist = ObjectDoesNotExist
            mock_tenant_model.objects.get.side_effect = ObjectDoesNotExist("Tenant not found")

            mock_customer = Mock()
            mock_customer.get_full_name.return_value = "Test User"
            mock_customer.email = "test@example.com"

            mock_template = Mock()
            mock_template.name = "Test Contract"

            mock_contract = Mock()
            mock_contract.id = "99999"
            mock_contract.title = "Test"
            mock_contract.content_html = "<p>Test</p>"
            mock_contract.status = Contract.Status.PENDING
            mock_contract.expires_at = None
            mock_contract.template = mock_template
            mock_contract.customer = mock_customer
            mock_contract.event = None
            mock_contract.signature = None

            serializer = PublicContractSerializer()

            # Act
            result = serializer.to_representation(mock_contract)

            # Assert - should use fallback values
            assert result["business"]["name"] == "Business"
            assert result["business"]["logo_url"] is None


class TestContractSignatureInputSerializer:
    """Test ContractSignatureInputSerializer validation."""

    def test_all_required_fields_present(self):
        """Verify all signature input fields are defined."""
        serializer = ContractSignatureInputSerializer()
        fields = serializer.fields

        assert "consent_checkbox_checked" in fields
        assert "electronic_consent_given" in fields
        assert "signer_name" in fields
        assert "latitude" in fields
        assert "longitude" in fields

    def test_valid_data_with_all_fields(self):
        """Test serializer validates with all fields provided."""
        data = {
            "consent_checkbox_checked": True,
            "electronic_consent_given": True,
            "signer_name": "John Doe",
            "latitude": Decimal("40.712776"),
            "longitude": Decimal("-74.005974"),
        }

        serializer = ContractSignatureInputSerializer(data=data)
        assert serializer.is_valid()
        assert serializer.validated_data["signer_name"] == "John Doe"
        assert serializer.validated_data["latitude"] == Decimal("40.712776")

    def test_valid_data_without_optional_location(self):
        """Test serializer validates without optional lat/long fields."""
        data = {
            "consent_checkbox_checked": True,
            "electronic_consent_given": True,
            "signer_name": "Jane Smith",
        }

        serializer = ContractSignatureInputSerializer(data=data)
        assert serializer.is_valid()

    def test_invalid_data_missing_required_field(self):
        """Test serializer fails when required field is missing."""
        data = {
            "consent_checkbox_checked": True,
            "electronic_consent_given": True,
            # Missing signer_name
        }

        serializer = ContractSignatureInputSerializer(data=data)
        assert not serializer.is_valid()
        assert "signer_name" in serializer.errors

    def test_signer_name_max_length_validation(self):
        """Test signer_name enforces max_length."""
        data = {
            "consent_checkbox_checked": True,
            "electronic_consent_given": True,
            "signer_name": "A" * 201,  # Exceeds 200 character limit
        }

        serializer = ContractSignatureInputSerializer(data=data)
        assert not serializer.is_valid()
        assert "signer_name" in serializer.errors


class TestCreateContractSerializer:
    """Test CreateContractSerializer validation logic."""

    def test_all_expected_fields_present(self):
        """Verify all contract creation fields are defined."""
        serializer = CreateContractSerializer()
        fields = serializer.fields

        assert "template" in fields
        assert "customer_id" in fields
        assert "event_id" in fields
        assert "send_email" in fields

    def test_template_queryset_filters_active_only(self):
        """Test template field only allows ACTIVE templates."""
        serializer = CreateContractSerializer()
        template_field = serializer.fields["template"]

        # The queryset should be filtered to active templates
        assert hasattr(template_field, "queryset")

    def test_validate_customer_id_with_valid_customer(self):
        """Test validate_customer_id returns customer object for valid ID."""
        from rest_framework.exceptions import ValidationError

        with patch('smoothschedule.identity.users.models.User') as mock_user_model:
            mock_customer = Mock()
            mock_customer.id = 123
            mock_user_model.objects.get.return_value = mock_customer

            serializer = CreateContractSerializer()
            result = serializer.validate_customer_id(123)

            assert result == mock_customer
            # Verify it filters by customer role
            mock_user_model.objects.get.assert_called_once()

    def test_validate_customer_id_with_invalid_customer(self):
        """Test validate_customer_id raises validation error for invalid ID."""
        from rest_framework.exceptions import ValidationError
        from django.core.exceptions import ObjectDoesNotExist

        with patch('smoothschedule.identity.users.models.User') as mock_user_model:
            # Mock the DoesNotExist exception properly
            mock_user_model.DoesNotExist = ObjectDoesNotExist
            mock_user_model.objects.get.side_effect = ObjectDoesNotExist("User not found")

            serializer = CreateContractSerializer()

            with pytest.raises(ValidationError) as exc_info:
                serializer.validate_customer_id(999)

            assert "Customer not found" in str(exc_info.value)

    def test_validate_event_id_with_valid_event(self):
        """Test validate_event_id returns event object for valid ID."""
        with patch('smoothschedule.scheduling.schedule.models.Event') as mock_event_model:
            mock_event = Mock()
            mock_event.id = 456
            mock_event_model.objects.get.return_value = mock_event

            serializer = CreateContractSerializer()
            result = serializer.validate_event_id(456)

            assert result == mock_event
            mock_event_model.objects.get.assert_called_once_with(id=456)

    def test_validate_event_id_with_none(self):
        """Test validate_event_id returns None when passed None."""
        with patch('smoothschedule.scheduling.schedule.models.Event') as mock_event_model:
            serializer = CreateContractSerializer()
            result = serializer.validate_event_id(None)

            assert result is None
            mock_event_model.objects.get.assert_not_called()

    def test_validate_event_id_with_invalid_event(self):
        """Test validate_event_id raises validation error for invalid ID."""
        from rest_framework.exceptions import ValidationError
        from django.core.exceptions import ObjectDoesNotExist

        with patch('smoothschedule.scheduling.schedule.models.Event') as mock_event_model:
            # Mock the DoesNotExist exception properly
            mock_event_model.DoesNotExist = ObjectDoesNotExist
            mock_event_model.objects.get.side_effect = ObjectDoesNotExist("Event not found")

            serializer = CreateContractSerializer()

            with pytest.raises(ValidationError) as exc_info:
                serializer.validate_event_id(789)

            assert "Event not found" in str(exc_info.value)

    def test_validate_transforms_customer_id_to_customer(self):
        """Test validate method transforms customer_id to customer object."""
        mock_customer = Mock()
        attrs = {
            "customer_id": mock_customer,
            "template": Mock(),
            "send_email": True,
        }

        serializer = CreateContractSerializer()
        result = serializer.validate(attrs)

        assert "customer" in result
        assert result["customer"] == mock_customer
        assert "customer_id" not in result

    def test_validate_transforms_event_id_to_event(self):
        """Test validate method transforms event_id to event object."""
        mock_event = Mock()
        attrs = {
            "customer_id": Mock(),
            "event_id": mock_event,
            "template": Mock(),
            "send_email": False,
        }

        serializer = CreateContractSerializer()
        result = serializer.validate(attrs)

        assert "event" in result
        assert result["event"] == mock_event
        assert "event_id" not in result

    def test_validate_handles_none_event_id(self):
        """Test validate method handles None event_id properly."""
        attrs = {
            "customer_id": Mock(),
            "template": Mock(),
            "send_email": True,
        }

        serializer = CreateContractSerializer()
        result = serializer.validate(attrs)

        assert "event" in result
        assert result["event"] is None

    def test_send_email_defaults_to_true(self):
        """Test send_email field has default value of True."""
        serializer = CreateContractSerializer()
        send_email_field = serializer.fields["send_email"]

        assert send_email_field.default is True

    def test_event_id_is_optional(self):
        """Test event_id field is not required and allows null."""
        serializer = CreateContractSerializer()
        event_id_field = serializer.fields["event_id"]

        assert event_id_field.required is False
        assert event_id_field.allow_null is True
