
from rest_framework import serializers
from django.contrib.auth import get_user_model
from users.models import (
    User, Company, Client, ClientRelation, ClientDocument, ClientFrequentFlyer,
    Cities, Countries, State, ClientVisa, ClientPassport, ClientLog, Airlines, 
    AssocClientCompany, Menu, LoginOTP, UserPermissions, ClientTravelInsurance, EmailSetup, CompanyDataView, ClientDataView)
from django.db import transaction
import json
from datetime import datetime
from django.utils import timezone
from django.utils.dateparse import parse_date
from django.contrib.auth import get_user_model
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
import base64
import mimetypes
from django.db.models import Q
from django.core.serializers.json import DjangoJSONEncoder
from .signals import build_changes
from users.utils import serialize_client_with_related

# from .serializers import (
#     CompanySerializer,
#     CompanydataSerializer,
#     UserPermissionsSerializer,
#     UserSerializer,
#     ClientCreateSerializer,
#     FullClientSerializer,
# )
# from users.fields import FileUrlField

# Use the active auth user model
User = get_user_model()

def get_file_name(file_field):
    return file_field.name if file_field else None

def safe_get_file(value):
    """
    Return the provided file object if it exists,
    otherwise return None to prevent invalid assignments.
    """
    return value if value else None

class FileUrlField(serializers.FileField):
    def to_representation(self, value):
        if not value:
            return None
        try:
            url = value.url
        except Exception:
            return str(value)
        request = self.context.get("request")
        if request:
            return request.build_absolute_uri(url)
        return url

class OptionalFileField(serializers.FileField):
    """Accepts either an uploaded file or a string (existing path)."""
    def to_internal_value(self, data):
        # If it's a string (path or URL), just return it as-is
        if isinstance(data, str):
            return data
        # Otherwise fallback to normal FileField behavior
        return super().to_internal_value(data)


# ---------- Helpers ----------
class FileUrlField(serializers.FileField):
    """
    Ensures file fields serialize to URL (or string) instead of a FieldFile object,
    preventing "Object of type FieldFile is not JSON serializable".
    """
    def to_representation(self, value):
        if not value:
            return None
        try:
            return value.url
        except Exception:
            return str(value)


class FlexibleDateField(serializers.DateField):
    def __init__(self, *args, **kwargs):
        # Default to strict format unless user overrides
        kwargs.setdefault("input_formats", ["%Y-%m-%d"])
        super().__init__(*args, **kwargs)

    def to_internal_value(self, value):
        # Normalize empty values
        if value in ("", None):
            return None
        return super().to_internal_value(value)

    def to_representation(self, value):
        if not value:
            return None
        return super().to_representation(value)


# ---------- Basic Serializers ----------
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = "__all__"


class CountrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Countries
        fields = "__all__"

    def to_internal_value(self, data):
        """
        Normalize incoming value into a dict with 'id'.
        """

        # Case 1: null or empty string
        if data in (None, "", "null"):
            return {"id": None}

        # Case 2: dict (DRF validates normally)
        if isinstance(data, dict):
            return super().to_internal_value(data)

        # Case 3: number or numeric string
        if isinstance(data, (int, str)) and str(data).isdigit():
            num_value = int(data)

            # Try country_code
            country = Countries.objects.filter(country_code=num_value).first()
            if country:
                return {"id": country.id}

            # Try primary key
            country = Countries.objects.filter(id=num_value).first()
            if country:
                return {"id": country.id}

            raise serializers.ValidationError(
                {"country": f"Invalid country id or code: {data}"}
            )

        raise serializers.ValidationError(
            {"country": f"Invalid input for country: {data}"}
        )


    def to_representation(self, instance):
        if instance is None:
            return None
        return {
            "id": instance.id,
            "name": instance.name,
            "shortname": instance.shortname,
            "country_code": instance.country_code,
            "min_length": instance.min_length,
            "max_length": instance.max_length,
        }



class StateSerializer(serializers.ModelSerializer):
    class Meta:
        model = State
        fields = ["id", "name"]


class CitySerializer(serializers.ModelSerializer):
    class Meta:
        model = Cities
        fields = ["id", "name"]


class CompanydataSerializer(serializers.ModelSerializer):
    # company_country = serializers.CharField(
    #     source="company_country.country_name", read_only=True
    # )
    # company_state = serializers.CharField(
    #     source="company_state.state_name", read_only=True
    # )
    # company_city = serializers.CharField(
    #     source="company_city.city_name", read_only=True
    # )
    class Meta:
        model = Company
        fields = "__all__"

class CompanyDataSerializer(serializers.ModelSerializer):
    created_by_name = serializers.SerializerMethodField()
    updated_by_name = serializers.SerializerMethodField()

    company_country = serializers.SerializerMethodField()
    company_state = serializers.SerializerMethodField()
    company_city = serializers.SerializerMethodField()

    class Meta:
        model = Company
        fields = "__all__"

    # def get_created_by_name(self, obj):
    #     if obj.created_by:
    #         return str(obj.created_by)
    #     return None

    # def get_updated_by_name(self, obj):
    #     if obj.updated_by:
    #         return str(obj.updated_by)
    #     return None
    
    def get_created_by_name(self, obj):
        return str(obj.created_by) if obj.created_by else None

    def get_updated_by_name(self, obj):
        return str(obj.updated_by) if obj.updated_by else None

    def get_company_country(self, obj):
        return obj.company_country.name, obj.company_country.country_code  if obj.company_country else None

    def get_company_state(self, obj):
        return obj.company_state.name if obj.company_state else None

    def get_company_city(self, obj):
        return obj.company_city.name if obj.company_city else None
    
    def get_gst_document_file(self, obj):
        # return relative path instead of full absolute URL
        if obj.gst_document_file:
            return obj.gst_document_file.url 
        return None
    

# class CompanySerializer(serializers.ModelSerializer):
#     # Write-side for FK relations
#     # company_country = CountrySerializer(required=False)  # accepts country_code or full object
#     company_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     company_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False
#     )
#     company_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False
#     )
#     account_concerned_person_country_code = CountrySerializer(required=False)
#     travel_concerned_person_country_code = CountrySerializer(required=False)

#     gst_document_file = OptionalFileField(
#         required=False,
#         allow_null=True,
#         use_url=True
#     )

#     class Meta:
#         model = Company
#         fields = "__all__"

#     def to_representation(self, instance):
#         """Customize output: return id + name for country/state/city"""
#         data = super().to_representation(instance)

#         if instance.company_country:
#             data["company_country"] = {
#                 "id": instance.company_country.id,
#                 "name": instance.company_country.name,
#                 "country_code": instance.company_country.country_code,
#             }

#         if instance.company_state:
#             data["company_state"] = {
#                 "id": instance.company_state.id,
#                 "name": instance.company_state.name,
#             }

#         if instance.company_city:
#             data["company_city"] = {
#                 "id": instance.company_city.id,
#                 "name": instance.company_city.name,
#             }

#         if instance.account_concerned_person_country_code:
#             data["account_concerned_person_country_code"] = {
#                 "id": instance.account_concerned_person_country_code.id,
#                 "name": instance.account_concerned_person_country_code.name,
#                 "code": instance.company_country.country_code,
#             }

#         if instance.travel_concerned_person_country_code:
#             data["travel_concerned_person_country_code"] = {
#                 "id": instance.travel_concerned_person_country_code.id,
#                 "name": instance.travel_concerned_person_country_code.name,
#                 "code": instance.company_country.country_code,
#             }

#         return data

#     # ---------- Create / Update ----------
#     def create(self, validated_data):
#         # Handle nested countries
#         company_country_data = validated_data.pop("company_country", None)
#         account_country_data = validated_data.pop("account_concerned_person_country_code", None)
#         travel_country_data = validated_data.pop("travel_concerned_person_country_code", None)
#         validated_data['created_by'] = self.context['request'].user
#         validated_data['created_at'] = timezone.now()

#         if company_country_data:
#             if isinstance(company_country_data, dict):
#                 validated_data["company_country"] = Countries.objects.get(id=company_country_data["id"])
#             elif isinstance(company_country_data, Countries):
#                 validated_data["company_country"] = company_country_data

#         if account_country_data:
#             if isinstance(account_country_data, dict):
#                 validated_data["account_concerned_person_country_code"] = Countries.objects.get(id=account_country_data["id"])
#             elif isinstance(account_country_data, Countries):
#                 validated_data["account_concerned_person_country_code"] = account_country_data

#         if travel_country_data:
#             if isinstance(travel_country_data, dict):
#                 validated_data["travel_concerned_person_country_code"] = Countries.objects.get(id=travel_country_data["id"])
#             elif isinstance(travel_country_data, Countries):
#                 validated_data["travel_concerned_person_country_code"] = travel_country_data

#         return super().create(validated_data)

#     def update(self, instance, validated_data):
#         # --- Handle GST Document File ---
#         gst_file = validated_data.pop("gst_document_file", None)
#         if gst_file:
#             if hasattr(gst_file, "read"):  # actual uploaded file
#                 instance.gst_document_file = gst_file
#             elif isinstance(gst_file, str):  # string path (keep existing)
#                 pass  # Do nothing

#         # Handle nested countries
#         company_country_data = validated_data.pop("company_country", None)
#         account_country_data = validated_data.pop("account_concerned_person_country_code", None)
#         travel_country_data = validated_data.pop("travel_concerned_person_country_code", None)
#         validated_data['updated_by'] = self.context['request'].user
#         validated_data['updated_at'] = timezone.now()

#         if company_country_data:
#             if isinstance(company_country_data, dict):
#                 instance.company_country = Countries.objects.get(id=company_country_data["id"])
#             elif isinstance(company_country_data, Countries):
#                 instance.company_country = company_country_data

#         if account_country_data:
#             if isinstance(account_country_data, dict):
#                 instance.account_concerned_person_country_code = Countries.objects.get(id=account_country_data["id"])
#             elif isinstance(account_country_data, Countries):
#                 instance.account_concerned_person_country_code = account_country_data

#         if travel_country_data:
#             if isinstance(travel_country_data, dict):
#                 instance.travel_concerned_person_country_code = Countries.objects.get(id=travel_country_data["id"])
#             elif isinstance(travel_country_data, Countries):
#                 instance.travel_concerned_person_country_code = travel_country_data

#         # Update remaining fields
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)

#         instance.save()
#         return instance

# class CompanySerializer(serializers.ModelSerializer):
#     company_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     company_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     company_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     account_concerned_person_country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     travel_concerned_person_country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     gst_document_file = OptionalFileField(required=False, allow_null=True, use_url=True)

#     class Meta:
#         model = Company
#         fields = "__all__"

#     def to_representation(self, instance):
#         data = super().to_representation(instance)
#         if instance.company_country:
#             data["company_country"] = {
#                 "id": instance.company_country.id,
#                 "name": instance.company_country.name,
#                 "country_code": instance.company_country.country_code,
#             }
#         if instance.company_state:
#             data["company_state"] = {
#                 "id": instance.company_state.id,
#                 "name": instance.company_state.name,
#             }
#         if instance.company_city:
#             data["company_city"] = {
#                 "id": instance.company_city.id,
#                 "name": instance.company_city.name,
#             }
#         if instance.account_concerned_person_country_code:
#             data["account_concerned_person_country_code"] = {
#                 "id": instance.account_concerned_person_country_code.id,
#                 "name": instance.account_concerned_person_country_code.name,
#                 "country_code": instance.account_concerned_person_country_code.country_code,
#             }
#         if instance.travel_concerned_person_country_code:
#             data["travel_concerned_person_country_code"] = {
#                 "id": instance.travel_concerned_person_country_code.id,
#                 "name": instance.travel_concerned_person_country_code.name,
#                 "country_code": instance.travel_concerned_person_country_code.country_code,
#             }
#         return data

class CompanySerializer(serializers.ModelSerializer):
    company_country = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), required=False, allow_null=True
    )
    company_state = serializers.PrimaryKeyRelatedField(
        queryset=State.objects.all(), required=False, allow_null=True
    )
    company_city = serializers.PrimaryKeyRelatedField(
        queryset=Cities.objects.all(), required=False, allow_null=True
    )
    account_concerned_person_country_code = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), required=False, allow_null=True
    )
    travel_concerned_person_country_code = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), required=False, allow_null=True
    )
    gst_document_file = OptionalFileField(required=False, allow_null=True, use_url=True)

    class Meta:
        model = Company
        fields = "__all__"

    def to_representation(self, instance):
        data = super().to_representation(instance)
        if instance.company_country:
            data["company_country"] = {
                "id": instance.company_country.id,
                "name": instance.company_country.name,
                "country_code": instance.company_country.country_code,
            }
        if instance.company_state:
            data["company_state"] = {
                "id": instance.company_state.id,
                "name": instance.company_state.name,
            }
        if instance.company_city:
            data["company_city"] = {
                "id": instance.company_city.id,
                "name": instance.company_city.name,
            }
        if instance.account_concerned_person_country_code:
            data["account_concerned_person_country_code"] = {
                "id": instance.account_concerned_person_country_code.id,
                "name": instance.account_concerned_person_country_code.name,
                "country_code": instance.account_concerned_person_country_code.country_code,
            }
        if instance.travel_concerned_person_country_code:
            data["travel_concerned_person_country_code"] = {
                "id": instance.travel_concerned_person_country_code.id,
                "name": instance.travel_concerned_person_country_code.name,
                "country_code": instance.travel_concerned_person_country_code.country_code,
            }
        return data
    
# ---------- Activity / Logs ----------
class UserPermissionsSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserPermissions
        fields = "__all__"


class ClientLogSerializer(serializers.ModelSerializer):
    ref_client_id = serializers.PrimaryKeyRelatedField(queryset=Client.objects.all(), required=False, allow_null=True)
    performed_by = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), required=False, allow_null=True)
    id = serializers.IntegerField(required=False, allow_null=True)
    
    class Meta:
        model = ClientLog
        fields = [
            "id",
            "ref_client_id",
            "ref_table_name",
            "ref_id",
            "action_type",
            "changed_data",
            "performed_by",
            "performed_at",
        ]


class FlexibleFileField(serializers.FileField):
    def to_internal_value(self, data):
        # Accept string path/URL
        if isinstance(data, str):
            return data
        return super().to_internal_value(data)
# ---------- Nested Entities ----------

# class ClientPassportSerializer(serializers.ModelSerializer):
#     passport_no = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     passport_file = FlexibleFileField(required=False, allow_null=True)
#     passport_expiry_date = FlexibleDateField(required=False, allow_null=True)
#     id = serializers.IntegerField(required=False, allow_null=True)

#     class Meta:
#         model = ClientPassport
#         fields = ["id", "passport_no", "passport_expiry_date", "passport_file", "ref_client"]
#         extra_kwargs = {"ref_client": {"write_only": True},"id": {"read_only": True},}
        

#     def to_internal_value(self, data):
#         # Accept single-item lists and nested values provided by front-end
#         if isinstance(data, list) and data:
#             data = data[0]
#         if isinstance(data, dict):
#             # unwrap list values that sometimes come from multipart forms
#             for k in ("passport_no", "passport_expiry_date", "passport_file"):
#                 v = data.get(k)
#                 if isinstance(v, list):
#                     data[k] = v[0] if v else None
#         return super().to_internal_value(data)

#     def validate_passport_no(self, value):
#         if value in (None, ""):
#             return None
#         return str(value).strip()

class ClientPassportSerializer(serializers.ModelSerializer):
    passport_no = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    passport_file = serializers.FileField(required=False, allow_null=True, use_url=True)  # Use standard FileField
    passport_expiry_date = serializers.DateField(required=False, allow_null=True)  # Use standard DateField
    id = serializers.IntegerField(required=False, allow_null=True)

    class Meta:
        model = ClientPassport
        fields = ["id", "passport_no", "passport_expiry_date", "passport_file", "ref_client"]
        extra_kwargs = {
            "ref_client": {"write_only": True},
            "id": {"read_only": True},
        }

    def to_internal_value(self, data):
        # Handle single-item lists and nested values from multipart forms
        if isinstance(data, list) and data:
            data = data[0]
        if isinstance(data, dict):
            for k in ("passport_no", "passport_expiry_date", "passport_file"):
                v = data.get(k)
                if isinstance(v, list):
                    data[k] = v[0] if v else None
                # Ensure file is a valid uploaded file object
                if k == "passport_file" and v and not isinstance(v, (InMemoryUploadedFile, TemporaryUploadedFile)):
                    data[k] = None  # Discard invalid file data
        return super().to_internal_value(data)

    def validate_passport_no(self, value):
        if value in (None, ""):
            return None
        return str(value).strip()

    def validate_passport_file(self, value):
        if value is None:
            return None
        if not isinstance(value, (InMemoryUploadedFile, TemporaryUploadedFile)):
            raise serializers.ValidationError("Invalid file format for passport_file.")
        return value

'''
class ClientPassportSerializer(serializers.ModelSerializer):
    # Accept file on write; return URL on read
    passport_no = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    passport_file = serializers.FileField(required=False, allow_null=True, use_url=True)
    passport_expiry_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    class Meta:
        model = ClientPassport
        # fields = "__all__"
        fields = ["id", "passport_file", "passport_no", "passport_expiry_date", "ref_client"]
        extra_kwargs = {
            "ref_client": {"write_only": True},
        }

    # def validate_passport_no(self, value):
    #     if not value:
    #         raise serializers.ValidationError("Passport number is required.")
    #     if len(value) > 10:
    #         raise serializers.ValidationError("Passport number cannot exceed 10 characters.")
    #     if not value.isalnum():
    #         raise serializers.ValidationError("Passport number must be alphanumeric.")
    #     return value.upper()

    def get_passport_file(self, obj):
        if obj.passport_file:
            return obj.passport_file.url  # full media URL
        return None

    def validate(self, data):
        def clean_date(value):
            if not value or str(value).strip() == "":
                return None
            try:
                return datetime.strptime(str(value), "%Y-%m-%d").date()
            except ValueError:
                return None
        data["passport_expiry_date"] = clean_date(data.get("passport_expiry_date"))
        return data

    def validate_passport_expiry_date(self, value):
        """Convert string to date and validate"""
        if not value or str(value).strip() == "":
            return None
        try:
            # convert string (e.g., "2029-05-10") into a date object
            date_value = datetime.strptime(value.strip(), "%Y-%m-%d").date()
        except ValueError:
            raise serializers.ValidationError("Invalid date format. Use YYYY-MM-DD.")

        # now safe to compare
        if date_value < timezone.now().date():
            raise serializers.ValidationError("Passport expiry date cannot be in the past.")
        return value
'''


# class OtherDocumentSerializer(serializers.ModelSerializer):
#     other_document = serializers.FileField(required=False, allow_null=True, use_url=True)
#     id = serializers.IntegerField(required=False, allow_null=True)

#     class Meta:
#         model = ClientDocument
#         # fields = "__all__"
#         fields = ["id", "other_document", "other_document_name", "ref_client"]
#         extra_kwargs = {
#             "ref_client": {"write_only": True},
#             "other_document_name": {"required": False, "allow_null": True},
#             "other_document": {"required": False, "allow_null": True},
#         }

#     def get_other_document(self, obj):
#         return obj.other_document.url if obj.other_document else None
    
#     def validate(self, data):
#         other_document = data.get("other_document")
#         other_document_name = data.get("other_document_name")

#         # Return None to signal that this entry can be skipped
#         if not other_document and not other_document_name:
#             return {}

#         return data
    
#     def to_internal_value(self, data):
#         data = super().to_internal_value(data)

#         # normalize client_documents (single dict -> list)
#         if isinstance(data.get("client_documents"), dict):
#             data.get["client_documents"] = [data.get["client_documents"]]

#         return data

#     # def validate_other_document_name(self, value):
#     #     if not value:
#     #         raise serializers.ValidationError("Document name is required.")
#     #     if len(value) > 255:
#     #         raise serializers.ValidationError("Document name cannot exceed 255 characters.")
#     #     return value


class OtherDocumentSerializer(serializers.ModelSerializer):
    other_document = serializers.FileField(required=False, allow_null=True, use_url=True)
    id = serializers.IntegerField(required=False, allow_null=True)
    other_document_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    class Meta:
        model = ClientDocument
        fields = ["id", "other_document", "other_document_name", "ref_client"]
        extra_kwargs = {
            "ref_client": {"write_only": True},
            "other_document_name": {"required": False, "allow_null": True, "allow_blank": True},
            "other_document": {"required": False, "allow_null": True},
        }

    def validate(self, data):
        data = data.copy()  # Create a mutable copy
        other_document = data.get("other_document")
        other_document_name = data.get("other_document_name")

        # Validate id
        if "id" in data and data["id"]:
            try:
                data["id"] = int(data["id"])
                if not ClientDocument.objects.filter(id=data["id"]).exists():
                    data["id"] = None  # Treat as new record if ID is invalid
            except (ValueError, TypeError):
                data["id"] = None

        # Handle file uploads
        index = self.context.get("index", 0)
        file_key = f"client_documents[{index}][other_document]"
        if self.context.get("request") and file_key in self.context["request"].FILES:
            data["other_document"] = self.context["request"].FILES[file_key]
        elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
            data["other_document"] = None

        # Clean other_document_name
        if "other_document_name" in data:
            data["other_document_name"] = data["other_document_name"].strip() if data["other_document_name"] else None
           

        return data

    def get_other_document(self, obj):
        return obj.other_document.url if obj.other_document else None

class ClientVisaSerializer(serializers.ModelSerializer):
    # Accept raw integer instead of strict PK validation
    # ref_visa_country = serializers.IntegerField(required=False, allow_null=True)
    ref_visa_country = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), required=False, allow_null=True
    )
    passport_size_photograph = serializers.FileField(required=False, allow_null=True, use_url=True)
    visa_from_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    visa_to_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    # Read-only helper fields
    passport_size_photograph_url = serializers.SerializerMethodField()
    # ref_client = serializers.PrimaryKeyRelatedField(
    #     queryset=Client.objects.all(), required=False, allow_null=False
    # )
    id = serializers.IntegerField(required=False, allow_null=True)
    
    
    class Meta:
        model = ClientVisa
        fields = [
            "id",
            "ref_visa_country",
            "visa_type",
            "passport_size_photograph",
            "visa_from_date",
            "visa_to_date",
            "passport_size_photograph_url",
        ]
        extra_kwargs = {
            "ref_client": {"write_only": True},
        }
        
        print(">>>>>fields<<<<<<<<<<", fields)

    def validate(self, data):
        """Clean date fields and resolve country safely"""
        # Resolve country ID manually
        country_id = data.get("ref_visa_country") or data.get("ref_visa_country_id")

        if isinstance(country_id, Countries):
            # already resolved earlier in create()
            data["ref_visa_country"] = country_id
        elif country_id:
            try:
                data["ref_visa_country"] = Countries.objects.get(pk=country_id)
            except Countries.DoesNotExist:
                raise serializers.ValidationError({"ref_visa_country": "Invalid country ID."})
        else:
            data["ref_visa_country"] = None

        # Convert date strings
        def clean_date(value):
            if not value or str(value).strip() == "":
                return None
            try:
                return datetime.strptime(str(value), "%Y-%m-%d").date()
            except ValueError:
                return None
        data["visa_from_date"] = clean_date(data.get("visa_from_date"))
        data["visa_to_date"] = clean_date(data.get("visa_to_date"))
        return data

    # def get_client_name(self, obj):
    #     if hasattr(obj, "ref_client") and obj.ref_client:
    #         return f"{obj.ref_client.client_first_name} {obj.ref_client.client_last_name}"
    #     return None

    def get_passport_size_photograph_url(self, obj):
        if obj.passport_size_photograph:
            try:
                return obj.passport_size_photograph.url
            except ValueError:
                return None
        return None
    
    # def get_passport_size_photograph(self, obj):
    #     return get_file_name(obj.passport_size_photograph)


# class ClientTravelInsuranceSerializer(serializers.ModelSerializer):
#     insurance_document = serializers.FileField(required=False, allow_null=True, use_url=True)
#     insurance_from_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     insurance_to_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     id = serializers.IntegerField(required=False, allow_null=True)

#     class Meta:
#         model = ClientTravelInsurance
#         # fields = "__all__"
#         fields = ["id", "insurance_document", "insurance_from_date", "insurance_to_date", "ref_client"]
#         # extra_kwargs = {
#         #     "ref_client": {"write_only": True},
#         # }

#     def validate(self, data):
#         def clean_date(value):
#             if not value or str(value).strip() == "":
#                 return None
#             try:
#                 return datetime.strptime(str(value), "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         data["insurance_from_date"] = clean_date(data.get("insurance_from_date"))
#         data["insurance_to_date"] = clean_date(data.get("insurance_to_date"))
#         return data

#     def get_insurance_document(self, obj):
#         return obj.insurance_document.url if obj.insurance_document else None

#     # def validate_insurance_document(self, value):
#     #     if value:
#     #         valid_mime_types = ["image/jpeg", "image/png", "application/pdf"]
#     #         if hasattr(value, "content_type") and value.content_type not in valid_mime_types:
#     #             raise serializers.ValidationError("Only JPG, PNG, and PDF files are allowed.")
#     #         if hasattr(value, "size") and value.size > 5 * 1024 * 1024:
#     #             raise serializers.ValidationError("File size must be under 5MB.")
#     #     return value

class ClientTravelInsuranceSerializer(serializers.ModelSerializer):
    insurance_document = serializers.FileField(required=False, allow_null=True, use_url=True)
    insurance_from_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    insurance_to_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    id = serializers.IntegerField(required=False, allow_null=True)

    class Meta:
        model = ClientTravelInsurance
        fields = ["id", "insurance_document", "insurance_from_date", "insurance_to_date", "ref_client"]
        extra_kwargs = {
            "ref_client": {"write_only": True},
        }

    def validate(self, data):
        data = data.copy()  # Create a mutable copy
        def clean_date(value):
            if not value or str(value).strip() == "":
                return None
            try:
                return datetime.strptime(str(value), "%Y-%m-%d").date()
            except ValueError:
                return None

        data["insurance_from_date"] = clean_date(data.get("insurance_from_date"))
        data["insurance_to_date"] = clean_date(data.get("insurance_to_date"))

        # Validate id
        if "id" in data and data["id"]:
            try:
                data["id"] = int(data["id"])
                if not ClientTravelInsurance.objects.filter(id=data["id"]).exists():
                    data["id"] = None  # Treat as new record if ID is invalid
            except (ValueError, TypeError):
                data["id"] = None

        # Handle file uploads
        index = self.context.get("index", 0)
        file_key = f"travel_insurance[{index}][insurance_document]"
        if self.context.get("request") and file_key in self.context["request"].FILES:
            data["insurance_document"] = self.context["request"].FILES[file_key]
        elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
            data["insurance_document"] = None

        return data

    def get_insurance_document(self, obj):
        return obj.insurance_document.url if obj.insurance_document else None

class AirlinesSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(required=False, allow_null=True)
    class Meta:
        model = Airlines
        # fields = "__all__"
        fields = ["id", "iata", "icao", "airline", "callsign", "country"]


class FrequentflyerSerializer(serializers.ModelSerializer):
    ref_airline = serializers.PrimaryKeyRelatedField(queryset=Airlines.objects.all(), required=False, allow_null = True)
    id = serializers.IntegerField(required=False, allow_null=True)
    
    class Meta:
        model = ClientFrequentFlyer
        fields = ["id", "ref_airline", "ref_client", "ff_no"]

    def to_internal_value(self, data):
        if isinstance(data, dict) and "ref_airline" in data:
            airline_value = data["ref_airline"]

            if str(airline_value).isdigit():
                try:
                    airline = Airlines.objects.get(id=int(airline_value))
                    data["ref_airline"] = airline.id
                except Airlines.DoesNotExist:
                    raise serializers.ValidationError({
                        "ref_airline": f"Airline id '{airline_value}' not found."
                    })
            elif isinstance(airline_value, str):
                airline = (
                    Airlines.objects.filter(airline__iexact=airline_value).first()
                    or Airlines.objects.filter(iata__iexact=airline_value).first()
                    or Airlines.objects.filter(icao__iexact=airline_value).first()
                )
                if not airline:
                    raise serializers.ValidationError({
                        "ref_airline": f"Airline '{airline_value}' not found."
                    })
                data["ref_airline"] = airline.id   # enforce pk only

        return super().to_internal_value(data)

    def to_representation(self, instance):
        """Return airline details too"""
        return {
            "id": instance.id,
            "ref_client": instance.ref_client.client_id,
            "ff_no": instance.ff_no,
            "ref_airline": {
                "id": instance.ref_airline.id,
                "airline": instance.ref_airline.airline,
                "iata": instance.ref_airline.iata,
                "icao": instance.ref_airline.icao,
                "country": instance.ref_airline.country,
            } if instance.ref_airline else "",
        }


class AssocClientCompanySerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(required=False, allow_null=True)
    class Meta:
        model = AssocClientCompany
        fields = "__all__"
        # fields = ["id", "ref_company", "designation", "primary_company", "ref_client"]
        extra_kwargs = {
            "ref_client": {"write_only": True},
        }

# If you need family members separately on some endpoints
class ClientRelationSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(required=False, allow_null=True)
    class Meta:
        model = ClientRelation
        fields = "__all__"
        # fields = ["relation", "cross_relation", "to_client"]

'''
class FamilyMemberSerializer(serializers.ModelSerializer):
    aadhaar_card_file = FileUrlField(required=False, allow_null=True)
    pan_card_file = FileUrlField(required=False, allow_null=True)

    passports = ClientPassportSerializer(many=True, required=False)
    relationsWithOthers = ClientRelationSerializer(many=True, required=False)

    visas = ClientVisaSerializer(many=True, required=False)
    travelInsurances = ClientTravelInsuranceSerializer(many=True, required=False)
    documents = OtherDocumentSerializer(many=True, required=False)
    companies = AssocClientCompanySerializer(many=True, required=False)
    familyMembers = ClientRelationSerializer(many=True, required=False)

    class Meta:
        model = Client
        fields = [
            "client_code", "client_salutation", "client_first_name", "client_middle_name", "client_last_name",
            "relation", "crossrelation",
            "country_code", "contact_no", "email", "dob", "gender", "occupation",
            "aadhaar_card_file", "aadhaar_no", "pan_card_file", "pan_no",
            "passports", "relationsWithOthers",
        ]

    def get_aadhaar_card_file(self, obj):
        return get_file_name(obj.aadhaar_card_file)

    def get_pan_card_file(self, obj):
        return get_file_name(obj.pan_card_file)
'''

# class FamilyMemberSerializer(serializers.ModelSerializer):
#     # aadhaar_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
#     # pan_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
#     passports = ClientPassportSerializer(many=True, required=False)
#     client_first_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_middle_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_last_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_code = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_salutation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     relation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     crossrelation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     country_code = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     contact_no = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     email = serializers.EmailField(required=False, allow_blank=True, allow_null=True)
#     dob = serializers.DateField(required=False, allow_null=True)
#     gender = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     occupation = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     # Apply same for nested passports, or mark passports as not required:
#     # passports = ClientPassportSerializer(many=True, required=False)

#     # If family members have relations among themselves
#     relationsWithOthers = ClientRelationSerializer(many=True, required=False)

#     class Meta:
#         model = Client
#         fields = [
#             "client_code", "client_salutation", "client_first_name", "client_middle_name", "client_last_name",
#             "relation", "crossrelation", "is_prepayment",
#             "country_code", "contact_no", "email", "dob", "gender", "occupation",
#             "aadhaar_no", "aadhaar_card_file",
#             "pan_no", "pan_card_file",
#             "passports", "relationsWithOthers",
#         ]

# class FamilyMemberSerializer(serializers.ModelSerializer):
#     id = serializers.IntegerField(source='client_id', read_only=True)
#     type = serializers.CharField(source='client_type', read_only=True)
#     full_name = serializers.SerializerMethodField()
#     residential_city = serializers.CharField(source='residential_city.__str__', read_only=True, allow_null=True)
#     companies = serializers.SerializerMethodField()
#     status_label = serializers.CharField(source='get_client_status_display', read_only=True, allow_null=True)
#     created_at = serializers.DateTimeField(format='%d-%m-%Y', read_only=True, allow_null=True)
#     client_first_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_middle_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_last_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_code = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     client_salutation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     relation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     crossrelation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     country_code = serializers.SerializerMethodField()
#     contact_no = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     email = serializers.EmailField(required=False, allow_blank=True, allow_null=True)
#     dob = FlexibleDateField(required=False, allow_null=True)
#     gender = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     occupation = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             'id', 'client_code', 'client_salutation', 'full_name', 'client_first_name', 'client_middle_name',
#             'client_last_name', 'contact_no', 'email', 'residential_city', 'companies', 'relation',
#             'crossrelation', 'type', 'created_at', 'client_status', 'status_label', 'is_active',
#             'dob', 'country_code', 'gender', 'occupation', 'aadhaar_no', 'aadhaar_card_file', 'pan_no', 'pan_card_file'
#         ]

#     def get_full_name(self, obj):
#         parts = [obj.client_first_name or '', obj.client_middle_name or '', obj.client_last_name or '']
#         return ' '.join(part for part in parts if part).strip()

#     def get_companies(self, obj):
#         return [
#             {
#                 "company_id": assoc.ref_company.id if assoc.ref_company else None,
#                 "company_name": assoc.ref_company.company_name if assoc.ref_company else None,
#                 "designation": assoc.designation,
#                 "primary_company": assoc.primary_company,
#             }
#             for assoc in obj.client_companies.all()
#         ]

#     def get_country_code(self, obj):
#         return self.context['parent_serializer'].get_country_code_detail(obj)

class FamilyMemberSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(source='client_id', read_only=True)
    type = serializers.CharField(source='client_type', read_only=True)
    full_name = serializers.SerializerMethodField()
    residential_city = serializers.SerializerMethodField()  # Changed to SerializerMethodField
    companies = serializers.SerializerMethodField()
    status_label = serializers.CharField(source='get_client_status_display', read_only=True, allow_null=True)
    created_at = serializers.DateTimeField(format='%d-%m-%Y', read_only=True, allow_null=True)
    client_first_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    client_middle_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    client_last_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    client_code = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    client_salutation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    relation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    crossrelation = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    country_code = serializers.SerializerMethodField()
    contact_no = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    email = serializers.EmailField(required=False, allow_blank=True, allow_null=True)
    dob = FlexibleDateField(required=False, allow_null=True)
    gender = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    occupation = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    class Meta:
        model = Client
        fields = [
            'id', 'client_code', 'client_salutation', 'full_name', 'client_first_name', 'client_middle_name',
            'client_last_name', 'contact_no', 'email', 'residential_city', 'companies', 'relation',
            'crossrelation', 'type', 'created_at', 'client_status', 'status_label', 'is_active',
            'dob', 'country_code', 'gender', 'occupation', 'aadhaar_no', 'aadhaar_card_file', 'pan_no', 'pan_card_file'
        ]

    def get_full_name(self, obj):
        parts = [obj.client_first_name or '', obj.client_middle_name or '', obj.client_last_name or '']
        return ' '.join(part for part in parts if part).strip()

    def get_companies(self, obj):
        return [
            {
                "company_id": assoc.ref_company.id if assoc.ref_company else None,
                "company_name": assoc.ref_company.company_name if assoc.ref_company else None,
                "designation": assoc.designation,
                "primary_company": assoc.primary_company,
            }
            for assoc in obj.client_companies.all()
        ]

    def get_country_code(self, obj):
        try:
            parent_serializer = self.context.get('parent_serializer')
            if parent_serializer:
                return parent_serializer.get_country_code_detail(obj)
            # Fallback if parent_serializer is not available
            con_cc = obj.country_code
            if con_cc:
                return {
                    "id": con_cc.id,
                    "shortname": con_cc.shortname,
                    "name": con_cc.name,
                    "country_code": con_cc.country_code
                }
            return None
        except AttributeError:
            return None

    def get_residential_city(self, obj):
        try:
            city = obj.residential_city
            return str(city) if city else None
        except AttributeError:
            return None
    
# class ClientSerializer(serializers.ModelSerializer):
#     dob = FlexibleDateField(required=False, allow_null=True, default=None)
#     country_code = serializers.SerializerMethodField()
#     anniversary_date = FlexibleDateField(required=False, allow_null=True, default=None)
#     # aadhaar_card_file_url = serializers.SerializerMethodField()

#     class Meta:
#         model = Client
#         fields = "__all__"

#     def get_country_code_detail(self, obj):
#         con_cc = obj.country_code
#         if con_cc:
#             return {"id": con_cc.id, "shortname": con_cc.shortname, "name": con_cc.name, "country_code": con_cc.country_code}
#         return None
    
#     # def get_aadhaar_card_file_url(self, obj):
#     #     if obj.aadhaar_card_file and hasattr(obj.aadhaar_card_file, "url"):
#     #         return obj.aadhaar_card_file.url
#     #     return None

#     # def get_aadhar_card_file(self, obj):
#     #     return obj.aadhar_card_file.url if obj.aadhar_card_file else None
    
#     # def get_pan_card_file(self, obj):
#     #     return obj.pan_card_file.url if obj.pan_card_file else None

# class ClientSerializer(serializers.ModelSerializer):
#     id = serializers.IntegerField(source='client_id', read_only=True)
#     type = serializers.CharField(source='client_type', read_only=True)
#     full_name = serializers.SerializerMethodField()
#     residential_city = serializers.CharField(source='residential_city.__str__', read_only=True, allow_null=True)
#     companies = serializers.SerializerMethodField()
#     family_members = serializers.SerializerMethodField()  # Changed to SerializerMethodField
#     status_label = serializers.CharField(source='get_client_status_display', read_only=True, allow_null=True)
#     created_at = serializers.DateTimeField(format='%d-%m-%Y', read_only=True, allow_null=True)
#     dob = FlexibleDateField(required=False, allow_null=True, default=None)
#     country_code = serializers.SerializerMethodField()
#     anniversary_date = FlexibleDateField(required=False, allow_null=True, default=None)

#     class Meta:
#         model = Client
#         fields = [
#             'id', 'client_code', 'full_name', 'contact_no', 'is_prepayment', 'email', 'residential_city',
#             'companies', 'type', 'created_at', 'client_status', 'status_label', 'is_active', 'family_members',
#             'dob', 'country_code', 'anniversary_date', 'client_salutation', 'client_first_name',
#             'client_middle_name', 'client_last_name', 'gender', 'occupation', 'aadhaar_no',
#             'aadhaar_card_file', 'pan_no', 'pan_card_file'
#         ]

#     def get_full_name(self, obj):
#         parts = [obj.client_first_name or '', obj.client_middle_name or '', obj.client_last_name or '']
#         return ' '.join(part for part in parts if part).strip()

#     def get_companies(self, obj):
#         return [
#             {
#                 "company_id": assoc.ref_company.id if assoc.ref_company else None,
#                 "company_name": assoc.ref_company.company_name if assoc.ref_company else None,
#                 "designation": assoc.designation,
#                 "primary_company": assoc.primary_company,
#             }
#             for assoc in obj.client_companies.all()
#         ]

#     def get_country_code_detail(self, obj):
#         con_cc = obj.country_code
#         if con_cc:
#             return {
#                 "id": con_cc.id,
#                 "shortname": con_cc.shortname,
#                 "name": con_cc.name,
#                 "country_code": con_cc.country_code
#             }
#         return None

#     def get_country_code(self, obj):
#         return self.get_country_code_detail(obj)

#     def get_family_members(self, obj):
#         # Fetch related clients (family members) and pass parent_serializer in context
#         family_members = obj.related_clients.all()
#         serializer = FamilyMemberSerializer(
#             family_members,
#             many=True,
#             context={'request': self.context.get('request'), 'parent_serializer': self}
#         )
#         return serializer.data

# class ClientSerializer(serializers.ModelSerializer):
#     id = serializers.IntegerField(source='client_id', read_only=True)
#     type = serializers.CharField(source='client_type', read_only=True)
#     full_name = serializers.SerializerMethodField()
#     residential_city = serializers.SerializerMethodField()  # Changed to SerializerMethodField
#     companies = serializers.SerializerMethodField()
#     family_members = serializers.SerializerMethodField()
#     status_label = serializers.CharField(source='get_client_status_display', read_only=True, allow_null=True)
#     created_at = serializers.DateTimeField(format='%d-%m-%Y', read_only=True, allow_null=True)
#     dob = FlexibleDateField(required=False, allow_null=True, default=None)
#     country_code = serializers.SerializerMethodField()
#     anniversary_date = FlexibleDateField(required=False, allow_null=True, default=None)

#     class Meta:
#         model = Client
#         fields = [
#             'id', 'client_code', 'full_name', 'contact_no', 'is_prepayment', 'email', 'residential_city',
#             'companies', 'type', 'created_at', 'client_status', 'status_label', 'is_active', 'family_members',
#             'dob', 'country_code', 'anniversary_date', 'client_salutation', 'client_first_name',
#             'client_middle_name', 'client_last_name', 'gender', 'occupation', 'aadhaar_no',
#             'aadhaar_card_file', 'pan_no', 'pan_card_file'
#         ]

#     def get_full_name(self, obj):
#         parts = [obj.client_first_name or '', obj.client_middle_name or '', obj.client_last_name or '']
#         return ' '.join(part for part in parts if part).strip()

#     def get_companies(self, obj):
#         return [
#             {
#                 "company_id": assoc.ref_company.id if assoc.ref_company else None,
#                 "company_name": assoc.ref_company.company_name if assoc.ref_company else None,
#                 "designation": assoc.designation,
#                 "primary_company": assoc.primary_company,
#             }
#             for assoc in obj.client_companies.all()
#         ]

#     def get_country_code_detail(self, obj):
#         try:
#             con_cc = obj.country_code
#             if con_cc:
#                 return {
#                     "id": con_cc.id,
#                     "shortname": con_cc.shortname,
#                     "name": con_cc.name,
#                     "country_code": con_cc.country_code
#                 }
#             return None
#         except AttributeError:
#             return None

#     def get_country_code(self, obj):
#         return self.get_country_code_detail(obj)

#     def get_family_members(self, obj):
#         # Fetch related clients (family members) and pass parent_serializer in context
#         family_members = obj.related_clients.all()
#         serializer = FamilyMemberSerializer(
#             family_members,
#             many=True,
#             context={'request': self.context.get('request'), 'parent_serializer': self}
#         )
#         return serializer.data

#     def get_residential_city(self, obj):
#         try:
#             city = obj.residential_city
#             return str(city) if city else None
#         except AttributeError:
#             return None

class ClientExportSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(source='client_id', read_only=True)
    type = serializers.CharField(source='client_type', read_only=True)
    full_name = serializers.SerializerMethodField()
    residential_city = serializers.SerializerMethodField()
    dob = FlexibleDateField(required=False, allow_null=True, default=None)

    class Meta:
        model = Client
        fields = [
            'id','client_code', 'full_name', 'contact_no', 'is_prepayment', 'email', 'residential_city','type', 'client_status',
            'dob', 'client_salutation', 'client_first_name',
            'client_middle_name', 'client_last_name', 'gender',
        ]

    def get_full_name(self, obj):
        # Simplified full_name concatenation
        return ' '.join(filter(None, [
            obj.client_first_name or '',
            obj.client_middle_name or '',
            obj.client_last_name or ''
        ])).strip()

   
    def get_residential_city(self, obj):
        # Simplified city string conversion
        return str(obj.residential_city) if obj.residential_city else None
   

class ClientSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(source='client_id', read_only=True)
    type = serializers.CharField(source='client_type', read_only=True)
    full_name = serializers.SerializerMethodField()
    residential_city = serializers.SerializerMethodField()
    companies = serializers.SerializerMethodField()
    family_members = serializers.SerializerMethodField()
    status_label = serializers.CharField(source='get_client_status_display', read_only=True, allow_null=True)
    created_at = serializers.DateTimeField(format='%d-%m-%Y', read_only=True, allow_null=True)
    dob = FlexibleDateField(required=False, allow_null=True, default=None)
    country_code = serializers.SerializerMethodField()
    anniversary_date = FlexibleDateField(required=False, allow_null=True, default=None)

    class Meta:
        model = Client
        fields = [
            'id', 'client_code', 'full_name', 'contact_no', 'is_prepayment', 'email', 'residential_city',
            'companies', 'type', 'created_at', 'client_status', 'status_label', 'is_active', 'family_members',
            'dob', 'country_code', 'anniversary_date', 'client_salutation', 'client_first_name',
            'client_middle_name', 'client_last_name', 'gender', 'occupation', 'aadhaar_no',
            'aadhaar_card_file', 'pan_no', 'pan_card_file'
        ]

    def get_full_name(self, obj):
        # Simplified full_name concatenation
        return ' '.join(filter(None, [
            obj.client_first_name or '',
            obj.client_middle_name or '',
            obj.client_last_name or ''
        ])).strip()

    def get_companies(self, obj):
        # Optimize by assuming client_companies is prefetched
        return [
            {
                "company_id": assoc.ref_company_id,  # Use direct ID to avoid additional queries
                "company_name": assoc.ref_company.company_name if assoc.ref_company else None,
                "designation": assoc.designation,
                "primary_company": assoc.primary_company,
            }
            for assoc in obj.client_companies.all()
        ]

    def get_country_code(self, obj):
        # Simplified country_code serialization
        if obj.country_code:
            return {
                "id": obj.country_code.id,
                "shortname": obj.country_code.shortname,
                "name": obj.country_code.name,
                "country_code": obj.country_code.country_code
            }
        return None

    def get_family_members(self, obj):
        # Optimize family members serialization by leveraging prefetched data
        serializer = FamilyMemberSerializer(
            obj.related_clients.all(),
            many=True,
            context={'request': self.context.get('request'), 'parent_serializer': self}
        )
        return serializer.data

    def get_residential_city(self, obj):
        # Simplified city string conversion
        return str(obj.residential_city) if obj.residential_city else None
    
class ClientDeleteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = "__all__"
        # fields = ["client_id", "client_first_name", "client_last_name"]


class FlexibleFileField(serializers.FileField):
    def to_internal_value(self, data):
        # Accept string path/URL
        if isinstance(data, str):
            return data
        return super().to_internal_value(data)

class PassportInSerializer(serializers.Serializer):
    passport_no = serializers.CharField(required=False, allow_blank=True)
    passport_expiry_date = FlexibleDateField(required=False, allow_null=True, default=None)
    passport_file = FlexibleFileField(required=False, allow_null=True)

class RelationsWithOthersInSerializer(serializers.Serializer):
    from_client = serializers.IntegerField(required=False, allow_null=True)
    to_client = serializers.IntegerField(required=False, allow_null=True)
    relation = serializers.CharField(required=False, allow_blank=True)
    cross_relation = serializers.CharField(required=False, allow_blank=True)

class FamilyMemberInSerializer(serializers.Serializer):
    
    # def to_internal_value(self, data):
    #     if data("countryCode") == "":
    #         data.get["countryCode"] = None
    #     return data
    id = serializers.IntegerField(required=False, allow_null=True)
    clientCode = serializers.CharField(required=False, allow_blank=True)
    salutation = serializers.CharField(required=False, allow_blank=True)
    firstName = serializers.CharField(required=False, allow_blank=True)
    middleName = serializers.CharField(required=False, allow_blank=True)
    lastName = serializers.CharField(required=False, allow_blank=True)

    relation = serializers.CharField(required=False, allow_blank=True)
    crossrelation = serializers.CharField(required=False, allow_blank=True)

    fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
    relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False)

    # countryCode = serializers.IntegerField(required=False, allow_null=True)
    # countryCode = serializers.PrimaryKeyRelatedField(
    #     queryset=Countries.objects.all(),
    #     required=False,
    #     allow_null=True
    # )

    countryCode = CountrySerializer(required=False, allow_null=True)

    contactNo = serializers.CharField(required=False, allow_blank=True)
    email = serializers.EmailField(required=False, allow_blank=True, allow_null=True)
    # dob = serializers.DateField(input_formats=["%Y-%m-%d", None], required=False, allow_null=True)
    dob = FlexibleDateField(required=False, allow_null=True)
    # dob = serializers.DateField(required=False, allow_null=True)
    gender = serializers.CharField(required=False, allow_blank=True)
    occupation = serializers.CharField(required=False, allow_blank=True)

    aadhaarNo = serializers.CharField(required=False, allow_blank=True)
    aadhaarCard = serializers.FileField(required=False, allow_null=True)
    panNo = serializers.CharField(required=False, allow_blank=True)
    panCard = serializers.FileField(required=False, allow_null=True)

    # passports = PassportInSerializer(many=True, required=False)
    client_passport = PassportInSerializer(many=True, required=False)

    residential_address = serializers.CharField(required=False, allow_blank=True)
    residential_city = serializers.PrimaryKeyRelatedField(
        queryset=Cities.objects.all(), required=False, allow_null=True
    )
    residential_state = serializers.PrimaryKeyRelatedField(
        queryset=State.objects.all(), required=False, allow_null=True
    )
    residential_country = CountrySerializer(required=False, allow_null=True)
    residential_pincode = serializers.CharField(required=False, allow_blank=True)

class FamilyMemberOutSerializer(serializers.ModelSerializer):
    # client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
    # client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
    # travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
    # client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
    # client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
    # frequent_flyer = FrequentflyerSerializer(many=True, required=False, allow_null=True)
    # fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)

    class Meta:
        model = Client
        fields = [
            "client_code", "client_type", "client_salutation", "client_first_name", "client_middle_name", "client_last_name",
            "dob", "country_code", "is_prepayment",
            "contacst_no", "email", "gender",
            "residential_address", "residential_city", "residential_state", "residential_country", "residential_pincode",
            "marital_status", "anniversary_date", "reference_from", "reference_remark",
            "occupation", "preferred_contact_method",
            "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
            "ref_preferred_airline", "star_rating", "stay_preference", "room_preference", 
            "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
            "created_at", "created_by", "updated_at", "updated_by", 
            "fam_passports", "client_passport", "relationsWithOthers",
        ]


def unwrap_scalars(data, skip_keys=None):
    """
    Convert single-item lists into scalars for all fields except skip_keys.
    Example: {"client_code": ["ABC123"]} -> {"client_code": "ABC123"}
    """
    skip_keys = skip_keys or []
    cleaned = {}
    for k, v in data.items():
        if isinstance(v, list) and k not in skip_keys:
            if len(v) == 1:
                cleaned[k] = v[0]
            elif len(v) == 0:
                cleaned[k] = None
            else:
                cleaned[k] = v  # keep multi-item lists as-is
        else:
            cleaned[k] = v
    return cleaned

import ast

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = CountrySerializer(required=False)

#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), allow_null=True, required=False
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     # ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#     #     queryset=Airlines.objects.all(), required=False, allow_null=True
#     # )
#     ref_visa_country = CountrySerializer(required=False)

#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(queryset=Airlines.objects.all(), required=False, allow_null=True, write_only=True)
    
#     preferred_airline = AirlinesSerializer(read_only=True)

#     # --- Nested serializers (all many=True) ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
#             "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value
    
#     def clean_row(self, row, file_map=None):
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         # remove blank 'id'
#         if "id" in cleaned and (cleaned["id"] is None or str(cleaned["id"]).strip() == ""):
#             cleaned.pop("id")

#         # handle file uploads
#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def clean_str(self, value):
#         """
#         Normalize string/choice/char fields:
#         - Handle None, "", [], [""] → None
#         - Unwrap single-item lists
#         - If it's a stringified list like "['Male']", eval to "Male"
#         """
#         if value in ["", None, [], [""]]:
#             return None

#         # unwrap Python lists
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))  # join multi-values

#         # unwrap stringified lists (e.g. "['Male']" → "Male")
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass

#         return str(value).strip() or None
    
#     def safe_fk(self, model_class, value):
#         """
#         Return the ID of the foreign key, or None.
#         """
#         if not value:
#             return None
#         try:
#             # ensure value is integer ID
#             if isinstance(value, int):
#                 return value
#             # if value is string, convert to int
#             value_int = int(value)
#             # check that object exists
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     # def normalize_preferred_contact_method(self, value):
#     #     normalized = []
#     #     if not value:
#     #         return []
#     #     for v in value:
#     #         key = None
#     #         if isinstance(v, dict):
#     #             key = v.get("id") or v.get("value") or v.get("label") or v.get("")
#     #         else:
#     #             key = str(v)
#     #         if key:
#     #             normalized.append(str(key).lower().strip())
#     #     return normalized

#     def normalize_preferred_contact_method(self, value):
#         normalized = []
#         if not value:
#             return []

#         # Ensure we always work with a list
#         if isinstance(value, str):
#             value = [value]

#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())

#         return normalized
    
#     def extract_family_passports(self, fam):
#         """
#         Returns a list of passport dicts for a family member by trying all standard keys.
#         """
#         # Try all likely key variants, return the first found (list or single element as list)
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):

#         # unwrap single-item lists for scalar fields
#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]       
#                     elif len(v) == 0:
#                         d[k] = None
#             return d

#         # Step 1: normalize nested fields
#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport", "relationsWithOthers"
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     normalized_list.append(normalize_nested_dict(item))
#             data[field] = normalized_list

#         # --- Uniqueness checks ---
#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:  # only at create
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         # --- Clean top-level dates ---
#         data["dob"] = self.clean_date(data.get("dob"))
#         data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         # --- Helper: expand passports with multiple values ---
#         def expand_passports(passport_dict):
#             """
#             Expand a passport dict with lists into multiple passport dicts.
#             """
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         if i < len(value):
#                             record[key] = value[i]
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # --- Nested: Passport (Primary client) ---
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue
        
#         for i, p in enumerate(expanded_passports):
#             # unwrap lists → single values
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

#             # pull actual file from request.FILES
#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]

#             # normalize
#             p["passport_no"] = self.clean_str(p.get("passport_no"))
#             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports
#         # --- Nested: Familiar Passports ---   
#         for i, p in enumerate(data.get("fam_passport", [])):
#             p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
#             p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))
#             p["fam_passport_passport_file"] = self.context["request"].FILES.get(f"fam_passport[{i}][fam_passport_file]")

#         # --- Nested: Relations with Others ---
#         for r in data.get("relationsWithOthers", []):
#             r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

#         # --- Nested: Companies ---
#         for c in data.get("client_companies", []):
#             c["designation"] = self.clean_str(c.get("designation"))
#             c["primary_company"] = c.get("primary_company")

#         # --- Nested: Documents ---
#         for i, d in enumerate(data.get("client_documents", [])):
#             file_key = f"client_documents[{i}][other_document]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 d["other_document"] = self.context["request"].FILES[file_key]

#             d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         # --- Nested: Frequent Flyers ---
#         for f in data.get("client_frequent_flyers", []):
#             # f["ref_airline"] = self.clean_date(f.get("ref_airline"))
#             f["ff_no"] = self.clean_str(f.get("ff_no"))

#         # --- Nested: Visa ---
#         for v in data.get("client_visa", []):
#             v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#             v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))

#         # --- Nested: Travel Insurance ---
#         for t in data.get("travel_insurance", []):
#             t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#             t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))

#         # --- Nested: Family Members ---
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             fam["dob"] = self.clean_date(fam.get("dob"))
#             fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))

#             if "fam_passport" in fam:
#                 expanded_fam_passports = []
#                 for p in fam["fam_passport"]:
#                     if isinstance(p, dict):
#                         if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                             expanded_fam_passports.extend(expand_passports(p))
#                         else:
#                             expanded_fam_passports.append(p)
#                     else:
#                         continue

#                 for pi, p in enumerate(expanded_fam_passports):
#                     # unwrap lists → single values
#                     if isinstance(p.get("passport_no"), list):
#                         p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                     if isinstance(p.get("passport_expiry_date"), list):
#                         p["passport_expiry_date"] = (
#                             p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         )
#                     if isinstance(p.get("passport_file"), list):
#                         p["passport_file"] = (
#                             p["passport_file"][0] if p["passport_file"] else None
#                         )

#                     # pull uploaded file from request.FILES
#                     file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                     if self.context.get("request") and file_key in self.context["request"].FILES:
#                         p["passport_file"] = self.context["request"].FILES[file_key]

#                     # normalize values
#                     p["passport_no"] = self.clean_str(p.get("passport_no"))
#                     p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))
#                 fam["fam_passport"] = expanded_fam_passports

#         return data


#     # ---------------- Serializer Methods ----------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

#     '''
#     @transaction.atomic
#     def create(self, instance, validated_data):
#         # --- Helper: expand passport dicts with multiple values ---
#         def expand_passports(passport_dict):
#             max_len = max(
#                 len(v) if isinstance(v, list) else 1
#                 for v in passport_dict.values()
#                 if v is not None
#             )
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         if i < len(value):
#                             record[key] = value[i]
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results
        
#         def unwrap(value):
#             # Single-item list to scalar, blank string to None
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # --- Pop related data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relations_data = validated_data.pop("relationsWithOthers", [])
#         fam_passports=validated_data.pop("fam_passport", [])

#         # --- Pop FKs first ---
#         c_code = validated_data.pop("country_code", None)
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)

#         # --- Normalize top-level ---
#         # country_value = validated_data.get("country_code", None)
#         # country_id = validated_data.get("country_id", None)
#         # if country_value :
#         #     if isinstance(country_value, (str, int)):
#         #         validated_data["country_code"] = Countries.objects.get(country_code=country_value)
#         #     elif isinstance(country_value, dict):
#         #         validated_data["country_code"] = Countries.objects.get(Countries.country_id)
#         #     elif isinstance(country_value, Countries):
#         #         validated_data["country_code"] = country_value
#         #     else:
#         #         validated_data["country_code"] = None
#         # validated_data["country_code"] = country_value


#         # country_code = validated_data.get("country_code", Countries)

#         if c_code:
#             if isinstance(c_code, dict):
#                 instance.c_code = Countries.objects.get(id=c_code["id"])
#             elif isinstance(c_code, Countries):
#                 instance.c_code = c_code
        

#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = "Active"

#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         # --- Create main client ---
#         client = Client.objects.create(**validated_data)

#         # --- Assign FK fields after creation ---
#         if airline:
#             client.ref_preferred_airline = airline
#         if country:
#             client.residential_country = country
#         if state:
#             client.residential_state = state
#         if city:
#             client.residential_city = city
#         client.save()  

#         # --- Related: Passports ---
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if not pd["passport_no"] or not pd["passport_expiry_date"]:
#                 continue
#             ClientPassport.objects.create(ref_client=client, **pd)

#         # --- Related: Visas ---
        
#             for vd in visas_data:
#                 vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#                 vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date") or "")
#                 vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date") or "")

#                 # Normalize ref_visa_country
#                 country_value = vd.pop("ref_visa_country", None)
#                 if country_value:
#                     if isinstance(country_value, (str, int)):
#                         vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                     elif isinstance(country_value, dict):
#                         vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                     elif isinstance(country_value, Countries):
#                         vd["ref_visa_country"] = country_value
#                     else:
#                         vd["ref_visa_country"] = None
#                 else:
#                     vd["ref_visa_country"] = None

#                 if (vd["visa_from_date"]==None and vd["visa_to_date"]==None and vd["ref_visa_country"]==None and vd["passport_size_photograph"]==None):
#                     return 
#                 else:
#                     ClientVisa.objects.create(ref_client=client, **vd)

#         # --- Related: Travel Insurance ---
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # --- Other Documents ---
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if not any(doc.values()):
#                 continue
#             ClientDocument.objects.create(ref_client=client, **doc)

#         # --- Companies ---
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         # --- Frequent Flyers ---
#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # --- Family Members ---
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             # Pop passports before building fam_data
#             # fam_passports = fam.pop("fam_passport", [])

#             # if fam_passports==None:
#             #     print("Its empty")
#             # print(fam_passports)

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": "Active",
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             # Attach files if multipart provided
#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(**fam_data)
#             print("family mmeber:", family_client.client_id)

#             # Family passports
#             # fam_passports = self.extract_family_passports(fam)
#             for pd in fam_passports:
#                 if not isinstance(pd, dict):
#                     continue
#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 print("\n",f_passport_no)
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))
#                 print("\n",f_passport_expiry_date)
#                 f_passport_file = pd.get("passport_file") or pd.get("passportFile")
#                 # print(f_passport_file.uri)
#                 # print("family_passport_data:", pd.passport_no, pd.passport_expiry_date, family_client)
#                 # print("family_passports:", fam_passports)
#                 ClientPassport.objects.create(ref_client=family_client, passport_no=f_passport_no, passport_expiry_date=f_passport_expiry_date, passport_file=f_passport_file)

#             # Relations
#             if fam.get("relation"):
#                 ClientRelation.objects.create(from_client=client, to_client=family_client, relation=fam["relation"])
#             if fam.get("crossrelation"):
#                 ClientRelation.objects.create(from_client=family_client, to_client=client, relation=fam["crossrelation"])

#             for rel in relations_data:
#                 if isinstance(rel, str):
#                     try:
#                         rel = ast.literal_eval(rel)
#                     except Exception:
#                         continue
#                 if not isinstance(rel, dict):
#                     continue
#                 to_index = rel.get("toIndex")
#                 relation = rel.get("relation")
#                 cross_relation = rel.get("crossRelation")
#                 if not to_index:
#                     continue
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue
#                 ClientRelation.objects.create(
#                     from_client=family_client,
#                     to_client=target_client,
#                     relation=relation,
#                     cross_relation=cross_relation,
#                 )

#         return client
#     '''
#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
        
#         def unwrap(value):
#             # Single-item list to scalar, blank string to None
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # --- Pop related data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # --- Pop FKs first ---
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         # client_ref = validated_data.pop('clientRef_id', None)
    
#         # if client_ref:
#         #     validated_data['reference_from'] = 'client'
#         #     validated_data['reference_id'] = client_ref.id

#         # # client_ref = validated_data.pop("clientRef_id", None)
#         # if client_ref:
#         #     validated_data["reference_id"] = client_ref.client_id
#         # instance = super().create(validated_data)
#         # if client_ref:
#         #     instance.clientRef_id = client_ref

#         # Normalize country_code
#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         # finally assign back to validated_data so it saves properly
#         validated_data["country_code"] = country_code_instance

#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

                
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # --- Create main client ---

#         # --- Assign FK fields after creation ---
#         # Use normalized instances, not raw values
#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = (
#                 airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#             )
#         if country:
#             client.residential_country = (
#                 country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#             )
#         if state:
#             client.residential_state = (
#                 state if isinstance(state, State) else self.safe_fk(state, State)
#             )
#         if city:
#             client.residential_city = (
#                 city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#             )
#         client.save()

#         # --- Related: Passports ---
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"]:
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # --- Related: Visas ---
#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             # Normalize ref_visa_country
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value

#             # Only save if at least one meaningful field is present
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # --- Related: Travel Insurance ---
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"]:
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # --- Other Documents ---
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         # --- Companies ---
#         '''
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue

#             company_instance = None

#             # Case 1: If frontend sends company_id
#             company_id = cd.get("ref_company_id")
#             if company_id:
#                 try:
#                     company_instance = Company.objects.get(pk=company_id)
#                 except Company.DoesNotExist:
#                     continue

#             # Case 2: If frontend sends company name
#             elif cd.get("ref_company"):
#                 try:
#                     company_instance = Company.objects.get(company_name=cd["ref_company"])
#                 except Company.DoesNotExist:
#                     continue

#             if not company_instance:
#                 continue

#             # Replace with actual FK instance
#             cd["ref_company"] = company_instance
#             cd.pop("ref_company_id", None)  # cleanup if present

#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         '''
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)     


#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             # flyer_data["ref_airline_id"] = airline_instance.id
#             # flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
            
#             # print("RAW ff_no:", flyer_data.get("ff_no"))
#             # flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             # print("CLEANED ff_no:", flyer_data["ff_no"])


#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # --- Family Members ---
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)
        
#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())
#             # print("family member:", family_client.client_id)

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])  # only passports for this family member
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))

#                 # Look inside request.FILES
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no and f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             '''
#             fam_passports = fam.pop("fam_passport", [])  # only passports for this family member
#             for pd in fam_passports:
#                 if not isinstance(pd, dict):
#                     continue
#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(
#                     pd.get("passport_expiry_date") or pd.get("passportExpiryDate")
#                 )
#                 f_passport_file = pd.get("passport_file") or pd.get("passportFile")
#                 if f_passport_no and f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )
#             '''

#             # Relations
#             # if fam.get("relation"):
#             #     ClientRelation.objects.create(from_client=client, to_client=family_client, relation=fam["relation"])
#             # if fam.get("crossrelation"):
#             #     ClientRelation.objects.create(from_client=family_client, to_client=client, relation=fam["crossrelation"])
#             '''
#             if fam.get("relation"):
#                 ClientRelation.objects.create(from_client=family_client, to_client=family_client, relation=fam.get("relation"))
#             if fam.get("crossrelation") or fam.get("crossRelation"):
#                 cross_rel = fam.get("crossrelation")
#                 ClientRelation.objects.create(from_client=family_client, to_client=family_client, cross_relation=cross_rel,)

#              # --- Relation with primary client ---
#             if fam.get("relation"):
#                 ClientRelation.objects.create(
#                     from_client=client,
#                     to_client=family_client,
#                     relation=fam.get("relation"),
#                 )
#             if fam.get("crossrelation") or fam.get("crossRelation"):
#                 cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                 ClientRelation.objects.create(
#                     from_client=family_client, to_client=client, relation=cross_rel)
 
#             # --- Extra Relations (relationsWithOthers) ---
#             for rel in relations_data:
#                 if isinstance(rel, str):
#                     try:
#                         rel = ast.literal_eval(rel)
#                     except Exception:
#                         continue
#                 if not isinstance(rel, dict):
#                     continue

#                 to_index = rel.get("toIndex")
#                 relation = rel.get("relation")
#                 cross_relation = rel.get("crossrelation") or rel.get("crossRelation")

#                 if not to_index:
#                     continue
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#                 ClientRelation.objects.create(
#                     from_client=family_client,
#                     to_client=target_client,
#                     relation=relation,
#                     cross_relation=cross_relation,
#                 )
#             '''
            
#             # --- Relation with previous family member ---
#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         # --- Extra Relations (relationsWithOthers) processed once ---
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#         return client
                    
#             # --- Relation With Others (NEW) ---
#             # for rel in relation_with_other_data:
#             #     to_index = rel.get("toIndex")
#             #     relation = rel.get("relation")
#             #     cross_relation = rel.get("crossRelation")

#             #     if to_index:
#             #         try:
#             #             to_client = Client.objects.get(pk=to_index)
#             #             ClientRelation.objects.create(
#             #                 from_client=client,
#             #                 to_client=to_client,
#             #                 relation=relation,
#             #                 cross_relation=cross_relation
#             #             )
#             #         except Client.DoesNotExist:
#             #             continue
            



#     @transaction.atomic
#     def update(self, instance, validated_data):

#         # --- Skip file updates if instance is new (no pk) ---
#         # if not instance.pk:
#         #     for field in ["aadhaar_card_file", "pan_card_file"]:
#         #         if field in validated_data:
#         #             validated_data.pop(field)

#         # --- Normalize FK fields ---
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }
        
#         # --- Pop FKs first ---
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         for fk_field in fk_fields:
#             fk_value = validated_data.get(fk_field)
#             if fk_value:
#                 if isinstance(fk_value, dict):  # from frontend {"id": 3, ...}
#                     fk_value = fk_value.get("id")
#                 model_class = fk_models.get(fk_field)
#                 if isinstance(fk_value, int):
#                     validated_data[f"{fk_field}_id"] = fk_value
#                 elif isinstance(fk_value, model_class):
#                     validated_data[f"{fk_field}_id"] = fk_value.id
#                 else:
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         validated_data[f"{fk_field}_id"] = fk_instance.id
#                     except (ValueError, TypeError, model_class.DoesNotExist):
#                         validated_data[f"{fk_field}_id"] = None
#             validated_data.pop(fk_field, None)

#         # --- Normalize fields ---
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # --- Handle uploaded files, only on update ---        
#         # Get files from request, if available
#         # files = self.context.get("request").FILES if self.context.get("request") else {}

#         # for field in ["aadhaar_card_file", "pan_card_file"]:
#         #     if field in files:
#         #         # If new file uploaded, set it
#         #         setattr(instance, field, files[field])
#         #         # Otherwise ignore (do not override existing file)

#         # --- helper to skip empty dicts ---
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # --- update main client fields ---
#         skip_keys = {
#             "client_passport", "client_visa",
#             "client_documents", "client_companies", "client_frequent_flyers", "travel_insurance",
#         }

#         for attr, value in validated_data.items():
#             if attr in skip_keys:
#                 continue
#             setattr(instance, attr, value)

#         instance.save()

#         # --- passports ---
#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             if is_empty(pd):
#                 continue
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             obj_id = pd.pop("id", None)
#             if obj_id:
#                 ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientPassport.objects.update_or_create(ref_client=instance, **pd)
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- visas ---
#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for vd in visas_data:
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             obj_id = vd.pop("id", None)
#             if obj_id:
#                 ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientVisa.objects.update_or_create(ref_client=instance, **vd)
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- insurances ---
#         ins_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for ins in ins_data:
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             obj_id = ins.pop("id", None)
#             if obj_id:
#                 ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientTravelInsurance.objects.update_or_create(ref_client=instance, **ins)
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- documents ---
#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for doc in docs_data:
#             if is_empty(doc):
#                 continue
#             obj_id = doc.pop("id", None)
#             if obj_id:
#                 ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientDocument.objects.update_or_create(ref_client=instance, **doc)
#                 keep_ids.append(obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- company associations ---
#         company_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for comp in company_data:
#             if is_empty(comp):
#                 continue
#             obj_id = comp.pop("id", None)
#             if obj_id:
#                 AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = AssocClientCompany.objects.update_or_create(ref_client=instance, **comp)
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- frequent flyers ---
#         flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for ff in flyers_data:
#             if is_empty(ff):
#                 continue
#             obj_id = ff.pop("id", None)
#             if obj_id:
#                 ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(ref_client=instance, **ff)
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

#     '''
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # --- Extract nested data ---
#         passports_data = self.ensure_list(validated_data.pop("client_passport", []))
#         visas_data = self.ensure_list(validated_data.pop("client_visa", []))
#         insurances_data = self.ensure_list(validated_data.pop("travel_insurance", []))
#         docs_data = self.ensure_list(validated_data.pop("client_documents", []))
#         companies_data = self.ensure_list(validated_data.pop("client_companies", []))
#         frequent_flyers_data = self.ensure_list(validated_data.pop("client_frequent_flyers", []))

#         validated_data.pop("family_members", None)
#         validated_data.pop("familyMembers", None)

#         # --- Normalize FK fields ---
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#         }

#         for fk_field in fk_fields:
#             fk_value = validated_data.get(fk_field)
#             if fk_value:
#                 if isinstance(fk_value, dict):  # from frontend {"id": 3, ...}
#                     fk_value = fk_value.get("id")
#                 model_class = fk_models.get(fk_field)
#                 if isinstance(fk_value, int):
#                     validated_data[f"{fk_field}_id"] = fk_value
#                 elif isinstance(fk_value, model_class):
#                     validated_data[f"{fk_field}_id"] = fk_value.id
#                 else:
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         validated_data[f"{fk_field}_id"] = fk_instance.id
#                     except (ValueError, TypeError, model_class.DoesNotExist):
#                         validated_data[f"{fk_field}_id"] = None
#             validated_data.pop(fk_field, None)

#         # --- Normalize fields ---
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # --- Handle uploaded files ---
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if not file_val or file_val in ["", "null", None]:
#                     setattr(instance, field, None)

#         # --- Update main client fields ---
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         instance.save()

#         # --- Helper to skip empty nested rows ---
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # --- Nested objects updates ---
#         # Passports
#         for pd in passports_data:
#             if not pd.get("passport_no"):
#                 continue
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             ClientPassport.objects.update_or_create(
#                 ref_client=instance,
#                 passport_no=pd.get("passport_no"),
#                 defaults=pd
#             )

#         # Visas
#         for vd in visas_data:
#             if not vd.get("visa_no"):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             country_val = vd.pop("ref_visa_country", None)
#             if country_val:
#                 if isinstance(country_val, dict):
#                     vd["ref_visa_country_id"] = country_val.get("id")
#                 else:
#                     try:
#                         vd["ref_visa_country_id"] = int(country_val)
#                     except (ValueError, TypeError):
#                         vd["ref_visa_country_id"] = None

#             ClientVisa.objects.update_or_create(
#                 id=vd.get("id"),
#                 ref_client=instance,
#                 defaults=vd
#             )

#         # Travel Insurance
#         for ins in insurances_data:
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             ClientTravelInsurance.objects.update_or_create(
#                 id=ins.get("id"),
#                 ref_client=instance,
#                 defaults=ins
#             )

#         # Documents
#         for doc in docs_data:
#             if is_empty(doc):
#                 continue
#             ClientDocument.objects.update_or_create(
#                 id=doc.get("id"),
#                 ref_client=instance,
#                 defaults=doc
#             )

#         # Companies
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if is_empty(cd):
#                 continue
#             ref_company = cd.pop("ref_company", None)
#             if ref_company and isinstance(ref_company, dict):
#                 cd["ref_company"] = ref_company.get("id")
#             AssocClientCompany.objects.update_or_create(
#                 id=cd.get("id"), designation=cd.get("designation"),
#                 primary_company=cd.get("primary_company"),
#                 ref_company=cd.get("ref_company"),
#                 ref_client=instance,

#             )

#         # Frequent Flyers
#         for flyer in frequent_flyers_data:
#             flyer = self.clean_row(flyer)
#             if not any(flyer.values()):
#                 continue

#             # --- handle airline ---
#             airline_val = flyer.get("ref_airline")
#             if airline_val:
#                 if isinstance(airline_val, dict):
#                     flyer["ref_airline_id"] = airline_val.get("id")
#                 elif isinstance(airline_val, Airlines):
#                     flyer["ref_airline_id"] = airline_val.id
#                 else:
#                     try:
#                         flyer["ref_airline_id"] = int(airline_val)
#                     except (ValueError, TypeError):
#                         flyer.pop("ref_airline_id", None)

#             # --- Clean ff_no ---
#             flyer["ff_no"] = self.clean_str(flyer.get("ff_no"))

#             # --- Keep only valid fields for this model ---
#             valid_fields = {f.name for f in ClientFrequentFlyer._meta.get_fields()}
#             flyer_cleaned = {k: v for k, v in flyer.items() if k in valid_fields}

#             # --- Update or create ---
#             ClientFrequentFlyer.objects.update_or_create(
#                 id=flyer_cleaned.get("id"),
#                 ref_client=instance,
#                 defaults=flyer_cleaned,
#             )

#         return instance
#     '''


#     # Helper method (add inside serializer)
#     def ensure_list(self, value):
#         """
#         Ensure the given value is always a list of dicts.
#         Handles cases where DRF/multipart wraps in extra list.
#         """
#         if isinstance(value, dict):
#             return [value]
#         if isinstance(value, list):
#             # flatten nested lists (e.g. [[{...}]] -> [{...}])
#             flat = []
#             for v in value:
#                 if isinstance(v, list):
#                     flat.extend(v)
#                 elif v:
#                     flat.append(v)
#             return flat
#         return []
    
#     # ---------------- Representation Override ----------------
#     def to_representation(self, instance):
#         data = super().to_representation(instance)

#         # normalize reverse relations to lists using `.all()`
#         if hasattr(instance, "client_passport"):
#             data["client_passport"] = ClientPassportSerializer(
#                 instance.client_passport.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_visa"):
#             data["client_visa"] = ClientVisaSerializer(
#                 instance.client_visa.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "travel_insurance"):
#             data["travel_insurance"] = ClientTravelInsuranceSerializer(
#                 instance.travel_insurance.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_companies"):
#             data["client_companies"] = AssocClientCompanySerializer(
#                 instance.client_companies.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_documents"):
#             data["client_documents"] = OtherDocumentSerializer(
#                 instance.client_documents.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_frequent_flyers"):
#             data["client_frequent_flyers"] = FrequentflyerSerializer(
#                 instance.client_frequent_flyers.all(), many=True, context=self.context
#             ).data

#         # Keep your read-only SerializerMethodField
#         data["familyMembers"] = self.get_familyMembers(instance)

#         return data
#     '''
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # --- Extract related data (normalize to list of dicts) ---
#         passports_data = self.ensure_list(validated_data.pop("client_passport", []))
#         visas_data = self.ensure_list(validated_data.pop("client_visa", []))
#         insurances_data = self.ensure_list(validated_data.pop("travel_insurance", []))
#         docs_data = self.ensure_list(validated_data.pop("client_documents", []))
#         companies_data = self.ensure_list(validated_data.pop("client_companies", []))
#         frequent_flyers_data = self.ensure_list(validated_data.pop("client_frequent_flyers", []))

#         validated_data.pop("family_members", None)  # Ignore family members in update
#         validated_data.pop("familyMembers", None)  # Remove read-only field

#         # --- Normalize foreign keys safely ---
#         fk_fields = ["residential_country", "residential_state", "residential_city"]
#         fk_models = {
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#         }

#         for fk_field in fk_fields:
#             fk_value = validated_data.get(fk_field)
#             if fk_value:
#                 model_class = fk_models.get(fk_field)
#                 if isinstance(fk_value, int):
#                     validated_data[f"{fk_field}_id"] = fk_value
#                 elif isinstance(fk_value, model_class):
#                     validated_data[f"{fk_field}_id"] = fk_value.id
#                 else:
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         validated_data[f"{fk_field}_id"] = fk_instance.id
#                     except (ValueError, model_class.DoesNotExist):
#                         validated_data[f"{fk_field}_id"] = None
#             validated_data.pop(fk_field, None)  # Remove original key to avoid conflicts

#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))

#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # --- Handle uploaded files (main client) ---
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if not file_val or file_val in ["", "null", None]:
#                     setattr(instance, field, None)

#         # --- Update main client fields ---
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         instance.save()

#         # --- Sync Passports ---
#         existing_ids = set(ClientPassport.objects.filter(ref_client=instance).values_list("id", flat=True))
#         incoming_ids = set()
#         for pd in passports_data:
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             passport_id = pd.pop("id", None)
#             if passport_id:
#                 incoming_ids.add(int(passport_id))
#                 try:
#                     passport = ClientPassport.objects.get(id=passport_id, ref_client=instance)
#                     for attr, value in pd.items():
#                         setattr(passport, attr, value)
#                     passport.save()
#                 except ClientPassport.DoesNotExist:
#                     continue
#             else:
#                 new_obj = ClientPassport.objects.create(ref_client=instance, **pd)
#                 incoming_ids.add(new_obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=incoming_ids).delete()

#         # --- Sync Visas ---
#         existing_ids = set(ClientVisa.objects.filter(ref_client=instance).values_list("id", flat=True))
#         incoming_ids = set()
#         for vd in visas_data:
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_id = vd.pop("ref_visa_country", None)
#             if country_id:
#                 try:
#                     vd["ref_visa_country"] = Countries.objects.get(id=int(country_id))
#                 except (Countries.DoesNotExist, ValueError, TypeError):
#                     vd["ref_visa_country"] = None
#             visa_id = vd.pop("id", None)
#             if visa_id:
#                 incoming_ids.add(int(visa_id))
#                 try:
#                     visa = ClientVisa.objects.get(id=visa_id, ref_client=instance)
#                     for attr, value in vd.items():
#                         setattr(visa, attr, value)
#                     visa.save()
#                 except ClientVisa.DoesNotExist:
#                     continue
#             else:
#                 new_obj = ClientVisa.objects.create(ref_client=instance, **vd)
#                 incoming_ids.add(new_obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=incoming_ids).delete()

#         # --- Sync Travel Insurances ---
#         existing_ids = set(ClientTravelInsurance.objects.filter(ref_client=instance).values_list("id", flat=True))
#         incoming_ids = set()
#         for ins in insurances_data:
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             ins_id = ins.pop("id", None)
#             if ins_id:
#                 incoming_ids.add(int(ins_id))
#                 try:
#                     insurance = ClientTravelInsurance.objects.get(id=ins_id, ref_client=instance)
#                     for attr, value in ins.items():
#                         setattr(insurance, attr, value)
#                     insurance.save()
#                 except ClientTravelInsurance.DoesNotExist:
#                     continue
#             else:
#                 new_obj = ClientTravelInsurance.objects.get_or_create(ref_client=instance, **ins)
#                 incoming_ids.add(new_obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=incoming_ids).delete()

#         # --- Sync Documents ---
#         existing_ids = set(ClientDocument.objects.filter(ref_client=instance).values_list("id", flat=True))
#         incoming_ids = set()
#         for doc in docs_data:
#             if not doc:
#                 continue
#             doc_id = doc.pop("id", None)
#             if doc_id:
#                 incoming_ids.add(int(doc_id))
#                 try:
#                     d = ClientDocument.objects.get(id=doc_id, ref_client=instance)
#                     for attr, value in doc.items():
#                         setattr(d, attr, value)
#                     d.save()
#                 except ClientDocument.DoesNotExist:
#                     continue
#             else:
#                 new_obj = ClientDocument.objects.get_or_create(ref_client=instance, **doc)
#                 incoming_ids.add(new_obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=incoming_ids).delete()

#         # --- Sync Companies ---
#         existing_ids = set(AssocClientCompany.objects.filter(ref_client=instance).values_list("id", flat=True))
#         incoming_ids = set()
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_id = cd.pop("id", None)
#             if company_id:
#                 incoming_ids.add(int(company_id))
#                 try:
#                     company = AssocClientCompany.objects.get(id=company_id, ref_client=instance)
#                     for attr, value in cd.items():
#                         setattr(company, attr, value)
#                     company.save()
#                 except AssocClientCompany.DoesNotExist:
#                     continue
#             else:
#                 new_obj = AssocClientCompany.objects.get_or_create(ref_client=instance, **cd)
#                 incoming_ids.add(new_obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=incoming_ids).delete()

#         # --- Sync Frequent Flyers ---
#         existing_ids = set(ClientFrequentFlyer.objects.filter(ref_client=instance).values_list("id", flat=True))
#         incoming_ids = set()
#         for flyer in frequent_flyers_data:
#             flyer = self.clean_row(flyer)
#             if not any(flyer.values()):
#                 continue
#             flyer_id = flyer.pop("id", None)
#             if flyer_id:
#                 incoming_ids.add(int(flyer_id))
#                 try:
#                     ff = ClientFrequentFlyer.objects.get(id=flyer_id, ref_client=instance)
#                     ff.ff_no = flyer.get("ff_no", ff.ff_no)
#                     airline_id = flyer.get("ref_airline")
#                     if airline_id:
#                         try:
#                             ff.ref_airline_id = int(airline_id)
#                         except ValueError:
#                             pass
#                     ff.save()
#                 except ClientFrequentFlyer.DoesNotExist:
#                     continue
#             else:
#                 new_obj = ClientFrequentFlyer.objects.get_or_create(ref_client=instance, **flyer)
#                 incoming_ids.add(new_obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=incoming_ids).delete()

#         return instance
    
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # --- Extract related data (normalize to list of dicts) ---
#         passports_data = self.ensure_list(validated_data.pop("client_passport", []))
#         visas_data = self.ensure_list(validated_data.pop("client_visa", []))
#         insurances_data = self.ensure_list(validated_data.pop("travel_insurance", []))
#         docs_data = self.ensure_list(validated_data.pop("client_documents", []))
#         companies_data = self.ensure_list(validated_data.pop("client_companies", []))
#         frequent_flyers_data = self.ensure_list(validated_data.pop("client_frequent_flyers", []))

#         validated_data.pop("family_members", None)  # Ignore family members in update
#         validated_data.pop("familyMembers", None)  # Remove read-only field

#         # --- Normalize foreign keys safely ---
#         fk_fields = ["residential_country", "residential_state", "residential_city"]
#         fk_models = {
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#         }

#         for fk_field in fk_fields:
#             fk_value = validated_data.get(fk_field)
#             if fk_value:
#                 model_class = fk_models.get(fk_field)
#                 if isinstance(fk_value, int):
#                     validated_data[f"{fk_field}_id"] = fk_value
#                 elif isinstance(fk_value, model_class):
#                     validated_data[f"{fk_field}_id"] = fk_value.id
#                 else:
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         validated_data[f"{fk_field}_id"] = fk_instance.id
#                     except (ValueError, model_class.DoesNotExist):
#                         validated_data[f"{fk_field}_id"] = None
#             validated_data.pop(fk_field, None)  # Remove original key to avoid conflicts

#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))

#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # --- Handle uploaded files (main client) ---
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if not file_val or file_val in ["", "null", None]:
#                     setattr(instance, field, None)
#                 # else ignore silently (don’t overwrite with wrong type)

#         # --- Update main client fields ---
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         instance.save()

#         # --- Update or create related objects ---
#         for pd in passports_data:
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             ClientPassport.objects.get_or_create(
#                 ref_client=instance,
#                 passport_no=pd.get("passport_no"),
#                 defaults=pd
#             )

#         for vd in visas_data:
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             country_id = vd.pop("ref_visa_country", None)
#             if country_id:
#                 try:
#                     vd["ref_visa_country"] = Countries.objects.get(id=int(country_id))
#                 except (Countries.DoesNotExist, ValueError, TypeError):
#                     vd["ref_visa_country"] = None   # gracefully fallback

#             visa_id = vd.pop("id", None)
#             if visa_id:
#                 try:
#                     visa_instance = ClientVisa.objects.get(id=visa_id, ref_client=instance)
#                     for attr, value in vd.items():
#                         setattr(visa_instance, attr, value)
#                     visa_instance.save()
#                 except ClientVisa.DoesNotExist:
#                     continue
#             else:
#                 if vd.get("ref_visa_country") or vd.get("visa_type"):
#                     ClientVisa.objects.create(ref_client=instance, **vd)

#         for ins in insurances_data:
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             ClientTravelInsurance.objects.get_or_create(
#                 ref_client=instance,
#                 id=ins.get("id"),
#                 defaults=ins
#             )

#         for doc in docs_data:
#             if doc:
#                 ClientDocument.objects.get_or_create(
#                     ref_client=instance,
#                     other_document=doc.get("other_document"),
#                     defaults=doc
#                 )

#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_id = cd.pop("id", None)
#             if company_id:
#                 try:
#                     company_instance = AssocClientCompany.objects.get(id=company_id)
#                     company_instance.designation = cd.get("designation", company_instance.designation)
#                     company_instance.primary_company = cd.get("primary_company", company_instance.primary_company)
#                     company_instance.save()
#                 except AssocClientCompany.DoesNotExist:
#                     continue

#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             flyer_id = flyer_data.pop("id", None)
#             if flyer_id:
#                 try:
#                     flyer_instance = ClientFrequentFlyer.objects.get(id=flyer_id)
#                     flyer_instance.ff_no = flyer_data.get("ff_no", flyer_instance.ff_no)
#                     # Update airline FK
#                     airline_id = flyer_data.get("ref_airline")
#                     if airline_id:
#                         try:
#                             flyer_instance.ref_airline_id = int(airline_id)
#                         except ValueError:
#                             pass
#                     flyer_instance.save()
#                 except ClientFrequentFlyer.DoesNotExist:
#                     continue
#         return instance
# '''

class FullClientSerializer(serializers.ModelSerializer):
    
    # --- Foreign keys ---
    country_code = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(),
        required=False,
        allow_null=True
    )

    residential_country = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), required=False, allow_null=True
    )
    residential_state = serializers.PrimaryKeyRelatedField(
        queryset=State.objects.all(), required=False, allow_null=True
    )
    residential_city = serializers.PrimaryKeyRelatedField(
        queryset=Cities.objects.all(), required=False, allow_null=True
    )
    ref_preferred_airline = serializers.PrimaryKeyRelatedField(
        queryset=Airlines.objects.all(), required=False, allow_null=True
    )
    preferred_airline = AirlinesSerializer(read_only=True)

    ref_visa_country = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), required=False, allow_null=True
    )

    # --- Nested serializers (all many=True) ---
    client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
    client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
    travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
    client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
    client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
    client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
    family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
    fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
    relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
    familyMembers = serializers.SerializerMethodField(read_only=True)

    # --- File uploads ---
    aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
    pan_card_file = serializers.FileField(required=False, allow_null=True)

    # --- Flexible date fields ---
    dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    
    class Meta:
        model = Client
        fields = [
            "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
            "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
            "country_code", "contact_no", "email", "gender", "residential_address",
            "residential_city", "residential_state", "residential_country", "residential_pincode",
            "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
            "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
            "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
            "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
            "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
            "client_passport", "client_visa", "travel_insurance", "client_companies",
            "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
        ]
        read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")    
        

    # ---------------- Helper Methods ----------------
    def _normalize_code(self, code: str | None) -> str | None:
        code = (code or "").strip()
        return code or None

    def clean_date(self, value):
        if not value or str(value).strip() == "":
            return None
        if isinstance(value, str):
            try:
                return datetime.strptime(value, "%Y-%m-%d").date()
            except ValueError:
                return None
        return value
    
    def clean_row(self, row, file_map=None):
        print(">>>>>>> clean_row Details <<<<<<<<<<", row)   
        
        cleaned = {}
        for k, v in row.items():
            if v in ["", [], [""]]:
                cleaned[k] = None
            elif isinstance(v, list):
                cleaned[k] = v[0] if len(v) == 1 else v
            elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
                try:
                    parsed = ast.literal_eval(v)
                    if isinstance(parsed, list) and len(parsed) == 1:
                        cleaned[k] = parsed[0]
                    else:
                        cleaned[k] = parsed
                except Exception:
                    cleaned[k] = v
            else:
                cleaned[k] = v

        # remove blank 'id'
        if "id" in cleaned and (cleaned["id"] is None or str(cleaned["id"]).strip() == ""):
            cleaned.pop("id")
            

        # handle file uploads
        if file_map and self.context.get("request"):
            request_files = self.context["request"].FILES
            for field, req_field in file_map.items():
                if req_field in request_files:
                    cleaned[field] = request_files[req_field]

        return cleaned

    def clean_str(self, value):
        print(">>>>>>> clean_str Details <<<<<<<<<<", value)   
        
        """
        Normalize string/choice/char fields:
        - Handle None, "", [], [""] → None
        - Unwrap single-item lists
        - If it's a stringified list like "['Male']", eval to "Male"
        """
        if value in ["", None, [], [""]]:
            return None

        # unwrap Python lists
        if isinstance(value, list):
            if len(value) == 1:
                value = value[0]
            else:
                return " ".join(map(str, value))  # join multi-values

        # unwrap stringified lists (e.g. "['Male']" → "Male")
        if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
            try:
                parsed = ast.literal_eval(value)
                if isinstance(parsed, list) and len(parsed) == 1:
                    value = parsed[0]
                else:
                    value = parsed
            except Exception:
                pass

        return str(value).strip() or None
    
    def safe_fk(self, model_class, value):
        print(">>>>>>> safe_fk Details <<<<<<<<<<", value)   
        
        """
        Return the ID of the foreign key, or None.
        """
        if not value:
            return None
        try:
            # ensure value is integer ID
            if isinstance(value, int):
                return value
            # if value is string, convert to int
            value_int = int(value)
            # check that object exists
            if model_class.objects.filter(id=value_int).exists():
                return value_int
            return None
        except (ValueError, TypeError):
            return None

    def normalize_preferred_contact_method(self, value):
        print(">>>>>>> normalize_preferred_contact_method Details<<<<<<<<<<", value)   
        
        normalized = []
        if not value:
            return []

        # Ensure we always work with a list
        if isinstance(value, str):
            value = [value]

        for v in value:
            key = None
            if isinstance(v, dict):
                key = v.get("id") or v.get("value") or v.get("label")
            else:
                key = str(v)
            if key:
                normalized.append(str(key).lower().strip())

        return normalized
    
    def extract_family_passports(self, fam):
        """
        Returns a list of passport dicts for a family member by trying all standard keys.
        """
        # Try all likely key variants, return the first found (list or single element as list)
        for key in ["fam_passport", "client_passport", "passports"]:
            value = fam.get(key)
            if value:
                if isinstance(value, list):
                    return value
                elif isinstance(value, dict):
                    return [value]
        return []

    # ---------------- Validate ----------------
    def validate(self, data):
        # Unwrap single-item lists for scalar fields
        def unwrap_scalars(data, skip_keys):
            result = {}
            for k, v in data.items():
                if k in skip_keys:
                    result[k] = v
                elif isinstance(v, list) and len(v) == 1:
                    result[k] = v[0]
                elif isinstance(v, list) and len(v) == 0:
                    result[k] = None
                else:
                    result[k] = v
            return result

        data = unwrap_scalars(data, skip_keys=[
            "client_passport", "client_visa", "travel_insurance", "client_companies",
            "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
            "relationsWithOthers"
        ])

        def normalize_nested_dict(d):
            for k, v in list(d.items()):
                if isinstance(v, list):
                    if len(v) == 1:
                        d[k] = v[0]
                    elif len(v) == 0:
                        d[k] = None
                # Explicitly preserve None values
                if v is None:
                    d[k] = None
            return d

        # Step 1: Normalize nested fields
        nested_fields = [
            "client_passport", "client_visa", "travel_insurance", "client_companies",
            "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
        ]

        for field in nested_fields:
            val = data.get(field, [])
            if val is None:
                data[field] = []
                continue
            flat_list = []
            for item in val:
                if isinstance(item, list):
                    flat_list.extend(item)
                else:
                    flat_list.append(item)
            normalized_list = []
            for item in flat_list:
                if isinstance(item, dict):
                    normalized_list.append(normalize_nested_dict(item))
                elif item is None:
                    normalized_list.append(None)
            data[field] = normalized_list

        # --- Uniqueness checks ---
        main_code = self._normalize_code(data.get("client_code"))
        if main_code:
            qs = Client.objects.filter(client_code=main_code)
            if self.instance:
                qs = qs.exclude(pk=self.instance.client_id)
            if qs.exists():
                raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

        if not self.instance:  # Only at create
            for fam in data.get("family_members", []):
                fam_code = self._normalize_code(fam.get("clientCode"))
                if fam_code:
                    qs = Client.objects.filter(client_code=fam_code)
                    if qs.exists():
                        raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

        # --- Clean top-level dates, allowing None ---
        if "dob" in data:
            data["dob"] = self.clean_date(data.get("dob"))
        if "anniversary_date" in data:
            data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

        # --- Helper: Expand passports with multiple values ---
        def expand_passports(passport_dict):
            """
            Expand a passport dict with lists into multiple passport dicts.
            """
            if not passport_dict:
                return []
            max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
            results = []
            for i in range(max_len):
                record = {}
                for key, value in passport_dict.items():
                    if isinstance(value, list):
                        record[key] = value[i] if i < len(value) else None
                    else:
                        record[key] = value
                results.append(record)
            return results

        # --- Nested: Passport (Primary client) ---
        expanded_passports = []
        for p in data.get("client_passport", []):
            if isinstance(p, dict):
                if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
                    expanded_passports.extend(expand_passports(p))
                else:
                    expanded_passports.append(p)
            else:
                continue

        for i, p in enumerate(expanded_passports):
            # Unwrap lists → single values
            if isinstance(p.get("passport_no"), list):
                p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
            if isinstance(p.get("passport_expiry_date"), list):
                p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

            # Pull actual file from request.FILES
            file_key = f"client_passport[{i}][passport_file]"
            if self.context.get("request") and file_key in self.context["request"].FILES:
                p["passport_file"] = self.context["request"].FILES[file_key]
            elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
                p["passport_file"] = None

            # Normalize, allowing None
            if "passport_no" in p:
                p["passport_no"] = self.clean_str(p.get("passport_no"))
            if "passport_expiry_date" in p:
                p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

        data["client_passport"] = expanded_passports

        # # --- Nested: Familiar Passports ---
        for i, p in enumerate(data.get("fam_passport", [])):
            if isinstance(p, dict):
                if "fam_passport_no" in p:
                    p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
                if "fam_passport_expiry_date" in p:
                    p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))
                file_key = f"fam_passport[{i}][fam_passport_file]"
                if self.context.get("request") and file_key in self.context["request"].FILES:
                    p["fam_passport_passport_file"] = self.context["request"].FILES[file_key]
                elif "fam_passport_passport_file" in p and p["fam_passport_passport_file"] in ["", "null", None]:
                    p["fam_passport_passport_file"] = None

        # # --- Nested: Relations with Others ---
        # for r in data.get("relationsWithOthers", []):
        #     if isinstance(r, dict) and "relation_with_other_client_code" in r:
        #         r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

        # --- Nested: Companies ---
        for c in data.get("client_companies", []):
            if isinstance(c, dict):
                if "id" in c:
                    try:
                        c["id"] = int(c["id"]) if c["id"] else None
                    except (ValueError, TypeError):
                        c["id"] = None
                if "designation" in c:
                    c["designation"] = self.clean_str(c.get("designation"))
                if "primary_company" in c and c["primary_company"] in ["", "null"]:
                    c["primary_company"] = None
                if "ref_company" in c and c["ref_company"] in ["", "null", None]:
                    c["ref_company"] = None

        # --- Nested: Documents ---
        for i, d in enumerate(data.get("client_documents", [])):
            if isinstance(d, dict):
                file_key = f"client_documents[{i}][other_document]"
                if self.context.get("request") and file_key in self.context["request"].FILES:
                    d["other_document"] = self.context["request"].FILES[file_key]
                elif "other_document" in d and d["other_document"] in ["", "null", None]:
                    d["other_document"] = None
                if "other_document_name" in d:
                    d["other_document_name"] = self.clean_str(d.get("other_document_name"))

        # --- Nested: Frequent Flyers ---
        for f in data.get("client_frequent_flyers", []):
            if isinstance(f, dict):
                if "ff_no" in f:
                    f["ff_no"] = self.clean_str(f.get("ff_no"))
                if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
                    f["ref_airline"] = None

        # --- Nested: Visa ---
        
        for v in data.get("client_visa", []):
            
            if isinstance(v, dict):
                # print("here we are printing validate data of client visa ", v)
                if "id" in v:
                    v["id"] = self.clean_date(v.get("id"))
                if "visa_from_date" in v:
                    v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
                if "visa_to_date" in v:
                    v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
                if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
                    v["ref_visa_country"] = None

        # --- Nested: Travel Insurance ---
        for t in data.get("travel_insurance", []):
            if isinstance(t, dict):
                if "insurance_from_date" in t:
                    t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
                if "insurance_to_date" in t:
                    t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))

        # --- Nested: Family Members ---
        for fam_index, fam in enumerate(data.get("family_members", [])):
            if isinstance(fam, dict):
                if "id" in fam:
                    try:
                        fam["id"] = int(fam["id"]) if fam["id"] else None
                    except (ValueError, TypeError):
                        fam["id"] = None
                if "dob" in fam:
                    fam["dob"] = self.clean_date(fam.get("dob"))
                if "anniversary_date" in fam:
                    fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
                if "clientCode" in fam:
                    fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
                if "salutation" in fam:
                    fam["salutation"] = self.clean_str(fam.get("salutation"))
                if "firstName" in fam:
                    fam["firstName"] = self.clean_str(fam.get("firstName"))
                if "middleName" in fam:
                    fam["middleName"] = self.clean_str(fam.get("middleName"))
                if "lastName" in fam:
                    fam["lastName"] = self.clean_str(fam.get("lastName"))
                if "relation" in fam:
                    fam["relation"] = self.clean_str(fam.get("relation"))
                if "crossrelation" in fam:
                    fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
                if "contactNo" in fam:
                    fam["contactNo"] = self.clean_str(fam.get("contactNo"))
                if "email" in fam:
                    fam["email"] = self.clean_str(fam.get("email"))
                if "gender" in fam:
                    fam["gender"] = self.clean_str(fam.get("gender"))
                if "occupation" in fam:
                    fam["occupation"] = self.clean_str(fam.get("occupation"))
                if "aadhaarNo" in fam:
                    fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
                if "panNo" in fam:
                    fam["panNo"] = self.clean_str(fam.get("panNo"))
                if "residential_address" in fam:
                    fam["residential_address"] = self.clean_str(fam.get("residential_address"))
                if "residential_pincode" in fam:
                    fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
                if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
                    fam["residential_country"] = None
                if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
                    fam["residential_state"] = None
                if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
                    fam["residential_city"] = None

                if "fam_passport" in fam:
                    # Ensure fam_passport is a list of dictionaries
                    fam_passports = self.ensure_list(fam.get("fam_passport", []))
                    expanded_fam_passports = []
                    for p in fam_passports:
                        if not isinstance(p, dict):
                            continue
                        if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
                            expanded_fam_passports.extend(expand_passports(p))
                        else:
                            expanded_fam_passports.append(p)

                    for pi, p in enumerate(expanded_fam_passports):
                        if isinstance(p.get("passport_no"), list):
                            p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
                        if isinstance(p.get("passport_expiry_date"), list):
                            p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
                        if isinstance(p.get("passport_file"), list):
                            p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

                        file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
                        if self.context.get("request") and file_key in self.context["request"].FILES:
                            p["passport_file"] = self.context["request"].FILES[file_key]
                        elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
                            p["passport_file"] = None

                        if "passport_no" in p:
                            p["passport_no"] = self.clean_str(p.get("passport_no"))
                        if "passport_expiry_date" in p:
                            p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

                    fam["fam_passport"] = expanded_fam_passports
                    
        # --- Nested: Relations with Others ---
        for r in data.get("relationsWithOthers", []):
            if isinstance(r, dict):
                if "id" in r:
                    try:
                        r["id"] = int(r["id"]) if r["id"] else None
                    except (ValueError, TypeError):
                        r["id"] = None
                if "relation_with_other_client_code" in r:
                    r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))
                if "relation" in r:
                    r["relation"] = self.clean_str(r.get("relation"))
                if "crossRelation" in r:
                    r["crossRelation"] = self.clean_str(r.get("crossRelation"))
                if "fromIndex" in r and r["fromIndex"] in ["", "null", None]:
                    r["fromIndex"] = None
                if "toIndex" in r and r["toIndex"] in ["", "null", None]:
                    r["toIndex"] = None
                    
        # Validate client_documents using OtherDocumentSerializer
        documents = data.get("client_documents", [])
        validated_documents = []
        for i, doc in enumerate(documents):
            if isinstance(doc, dict):
                serializer = OtherDocumentSerializer(data=doc, context={**self.context, "index": i})
                if not serializer.is_valid():
                    raise serializers.ValidationError({f"client_documents[{i}]": serializer.errors})
                validated_documents.append(serializer.validated_data)
        data["client_documents"] = validated_documents

        return data
    # ---------------- Serializer Methods ----------------
    def get_familyMembers(self, obj):
        members = Client.objects.filter(ref_client=obj)
        return FullClientSerializer(members, many=True, context=self.context).data

    # ---------------- Create ----------------
    @transaction.atomic
    def create(self, validated_data):
        
        def unwrap(value):
            # Single-item list to scalar, blank string to None
            if isinstance(value, list):
                value = value if value else None
            return value if value not in ["", "null"] else None

        # --- Pop related data ---
        passports_data = validated_data.pop("client_passport", [])
        visas_data = validated_data.pop("client_visa", [])
        insurances_data = validated_data.pop("travel_insurance", [])
        docs_data = validated_data.pop("client_documents", [])
        companies_data = validated_data.pop("client_companies", [])
        frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
        family_members_data = validated_data.pop("family_members", [])
        relationsWithOthers = validated_data.pop("relationsWithOthers", [])
        fam_passports = validated_data.pop("fam_passport", [])

        # --- Pop FKs first ---
        airline = validated_data.pop("ref_preferred_airline", None)
        country = validated_data.pop("residential_country", None)
        state = validated_data.pop("residential_state", None)
        city = validated_data.pop("residential_city", None)
        country_code = validated_data.pop("country_code", None)

        # Normalize country_code
        if country_code:
            if isinstance(country_code, dict):
                country_code_instance = Countries.objects.get(id=country_code["id"])
            elif isinstance(country_code, int):
                country_code_instance = Countries.objects.get(id=country_code)
            elif isinstance(country_code, Countries):
                country_code_instance = country_code
            else:
                country_code_instance = None
        else:
            country_code_instance = None

        # finally assign back to validated_data so it saves properly
        validated_data["country_code"] = country_code_instance

        validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
        validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
        validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
        validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
        validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
        validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
        validated_data["client_type"] = "Primary Member"
        validated_data["client_status"] = 1

                
        request_files = self.context.get("request").FILES if self.context.get("request") else {}
        for file_field in ["aadhaar_card_file", "pan_card_file"]:
            validated_data[file_field] = request_files.get(file_field)

        client = Client.objects.create(**validated_data)

        # --- Create main client ---

        # --- Assign FK fields after creation ---
        # Use normalized instances, not raw values
        if country_code_instance:
            client.country_code = country_code_instance
        if airline:
            client.ref_preferred_airline = (
                airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
            )
        if country:
            client.residential_country = (
                country if isinstance(country, Countries) else self.safe_fk(country, Countries)
            )
        if state:
            client.residential_state = (
                state if isinstance(state, State) else self.safe_fk(state, State)
            )
        if city:
            client.residential_city = (
                city if isinstance(city, Cities) else self.safe_fk(city, Cities)
            )
        client.save()

        # --- Related: Passports ---
        for pd in passports_data:
            pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
            if not any(pd.values()):
                continue
            pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
            pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
            if pd["passport_no"] or pd["passport_expiry_date"]:
                ClientPassport.objects.create(ref_client=client, **pd)

        # --- Related: Visas ---
        for vd in visas_data:
            vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
            vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
            vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

            # Normalize ref_visa_country
            country_value = vd.pop("ref_visa_country", None)
            if country_value:
                if isinstance(country_value, (str, int)):
                    vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
                elif isinstance(country_value, dict):
                    vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
                elif isinstance(country_value, Countries):
                    vd["ref_visa_country"] = country_value

            # Only save if at least one meaningful field is present
            if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
                ClientVisa.objects.create(ref_client=client, **vd)

        # --- Related: Travel Insurance ---
        for ins in insurances_data:
            ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
            if not any(ins.values()):
                continue
            ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
            ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
            if ins["insurance_from_date"] or ins["insurance_to_date"]:
                ClientTravelInsurance.objects.create(ref_client=client, **ins)

        # --- Other Documents ---
        for doc in docs_data:
            doc = self.clean_row(doc, file_map={"other_document": "other_document"})
            if any(doc.values()):
                doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
                ClientDocument.objects.create(ref_client=client, **doc)

        for cd in companies_data:
            cd = self.clean_row(cd)
            if not any(cd.values()):
                continue
            company_name = cd.get("ref_company")
            if not company_name:
                continue
            try:
                company_instance = Company.objects.get(company_name=company_name)
            except Company.DoesNotExist:
                continue
            cd["ref_company_id"] = company_instance.id
            cd.pop("ref_company", None)
            AssocClientCompany.objects.create(ref_client=client, **cd)     


        for flyer_data in frequent_flyers_data:
            flyer_data = self.clean_row(flyer_data)
            if not any(flyer_data.values()):
                continue
            airline_value = flyer_data.get("ref_airline")
            if not airline_value:
                continue
            try:
                airline_instance = Airlines.objects.get(airline=airline_value)
            except Airlines.DoesNotExist:
                continue
            flyer_data["ref_airline_id"] = airline_instance.id
            flyer_data.pop("ref_airline", None)
            # flyer_data["ref_airline_id"] = airline_instance.id
            # flyer_data.pop("ref_airline", None)
            flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
            
            # print("RAW ff_no:", flyer_data.get("ff_no"))
            # flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
            # print("CLEANED ff_no:", flyer_data["ff_no"])


            ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

        # --- Family Members ---
        meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

        def is_blank_field(value):
            return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

        prev_family_client = None
        created_family_members = {}

        for fam_index, fam in enumerate(family_members_data):
            if not isinstance(fam, dict):
                try:
                    fam = ast.literal_eval(fam)
                except Exception:
                    continue
            if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
                continue

            fam_code = self._normalize_code(fam.get("clientCode"))
            fam_data = {
                "ref_client": client,
                "client_type": "Family Member",
                "client_status": 1,
                "client_code": fam_code,
                "client_salutation": fam.get("salutation"),
                "client_first_name": fam.get("firstName"),
                "client_middle_name": fam.get("middleName"),
                "client_last_name": fam.get("lastName"),
                "relation": fam.get("relation"),
                "crossrelation": fam.get("crossrelation"),
                "contact_no": fam.get("contactNo"),
                "email": fam.get("email"),
                "dob": self.clean_date(fam.get("dob")),
                "anniversary_date": self.clean_date(fam.get("anniversary_date")),
                "gender": fam.get("gender"),
                "occupation": fam.get("occupation"),
                "aadhaar_no": fam.get("aadhaarNo"),
                "aadhaar_card_file": fam.get("aadhaarCard"),
                "pan_no": fam.get("panNo"),
                "pan_card_file": fam.get("panCard"),
                "residential_address": fam.get("residential_address") or client.residential_address,
                "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
                "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
                "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
                "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
            }

            fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
            fam_pan_key = f"family_members[{fam_index}][panCard]"
            if fam_aadhaar_key in request_files:
                fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
            if fam_pan_key in request_files:
                fam_data["pan_card_file"] = request_files.get(fam_pan_key)

            family_client = Client.objects.create(
                **fam_data,
                created_by=self.context["request"].user if self.context.get("request") else None,
                created_at=timezone.now()
            )

            # Family passports
            fam_passports = self.ensure_list(fam.pop("fam_passport", []))  # Ensure fam_passport is a list
            for pd_index, pd in enumerate(fam_passports):
                if not isinstance(pd, dict):
                    continue

                f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
                f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))

                # Look inside request.FILES
                fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
                f_passport_file = request_files.get(fam_passport_key)

                # Relax the condition to allow creation with either passport_no or passport_expiry_date
                if f_passport_no or f_passport_expiry_date or f_passport_file:
                    ClientPassport.objects.create(
                        ref_client=family_client,
                        passport_no=f_passport_no,
                        passport_expiry_date=f_passport_expiry_date,
                        passport_file=f_passport_file,
                    )

            # Log family member creation (includes passports in changed_data)
            ClientLog.objects.create(
                ref_client_id=family_client,
                ref_table_name=family_client._meta.db_table,
                ref_id=family_client.pk,
                action_type="CLIENT CREATED",
                changed_data=json.loads(json.dumps(
                    build_changes(None, serialize_client_with_related(family_client)),
                    cls=DjangoJSONEncoder
                )),
                performed_by=family_client.created_by,
                performed_at=timezone.now(),
            )

            # --- Relation with previous family member ---
            if prev_family_client:
                if fam.get("relation"):
                    ClientRelation.objects.create(
                        from_client=prev_family_client,
                        to_client=family_client,
                        relation=fam.get("relation")
                    )
                if fam.get("crossrelation") or fam.get("crossRelation"):
                    cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
                    ClientRelation.objects.create(
                        from_client=family_client,
                        to_client=prev_family_client,
                        cross_relation=cross_rel
                    )

            prev_family_client = family_client
            created_family_members[fam_index] = family_client

        # --- Extra Relations (relationsWithOthers) processed once ---
        for rel in relationsWithOthers:
            if isinstance(rel, str):
                try:
                    rel = ast.literal_eval(rel)
                except Exception:
                    continue
            if not isinstance(rel, dict):
                continue

            from_index = rel.get("fromIndex")
            to_index = rel.get("toIndex")
            relation = rel.get("relation")
            cross_relation = rel.get("crossRelation")

            if from_index is None or to_index is None:
                continue

            from_client = created_family_members.get(int(from_index))
            if not from_client:
                continue

            target_client = created_family_members.get(int(to_index))
            if not target_client:
                try:
                    target_client = Client.objects.get(pk=int(to_index))
                except Client.DoesNotExist:
                    continue

            ClientRelation.objects.create(
                from_client=from_client,
                to_client=target_client,
                relation=relation,
                cross_relation=cross_relation
            )
        return client

    @transaction.atomic
    def update(self, instance, validated_data):
        # --- Pop nested data ---
        # passports_data = validated_data.pop("client_passport", [])
        # visas_data = validated_data.pop("client_visa", [])
        # insurances_data = validated_data.pop("travel_insurance", [])
        # docs_data = validated_data.pop("client_documents", [])
        # companies_data = validated_data.pop("client_companies", [])
        # frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
        # validated_data.pop("family_members", None)  # Ensure family_members is not processed here
        # validated_data.pop("familyMembers", None)

        # --- Define FK fields and their corresponding models ---
        fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
        fk_models = {
            "country_code": Countries,
            "residential_country": Countries,
            "residential_state": State,
            "residential_city": Cities,
            "ref_preferred_airline": Airlines,
        }
                

        # --- Handle FK fields, allowing None ---
        for fk_field in fk_fields:
            if fk_field in validated_data:
                fk_value = validated_data.pop(fk_field)
                model_class = fk_models.get(fk_field)
                
                if fk_value is None:
                    # Explicitly set to None if provided
                    validated_data[f"{fk_field}_id"] = None
                else:
                    # Handle non-None values
                    if isinstance(fk_value, dict):  # From frontend, e.g., {"id": 3}
                        fk_value = fk_value.get("id")
                    if isinstance(fk_value, model_class):
                        validated_data[f"{fk_field}_id"] = fk_value.id
                    elif isinstance(fk_value, (int, str)):
                        try:
                            fk_instance = model_class.objects.get(id=int(fk_value))
                            validated_data[f"{fk_field}_id"] = fk_instance.id
                        except (ValueError, TypeError, model_class.DoesNotExist):
                            validated_data[f"{fk_field}_id"] = None
                    else:
                        validated_data[f"{fk_field}_id"] = None
        
        # for fk_field in fk_fields:
        #     fk_value = validated_data.get(fk_field)
        #     if fk_value:
        #         if isinstance(fk_value, dict):  # from frontend {"id": 3, ...}
        #             fk_value = fk_value.get("id")
        #         model_class = fk_models.get(fk_field)
        #         if isinstance(fk_value, int):
        #             validated_data[f"{fk_field}_id"] = fk_value
        #         elif isinstance(fk_value, model_class):
        #             validated_data[f"{fk_field}_id"] = fk_value.id
        #         else:
        #             try:
        #                 fk_instance = model_class.objects.get(id=int(fk_value))
        #                 validated_data[f"{fk_field}_id"] = fk_instance.id
        #             except (ValueError, TypeError, model_class.DoesNotExist):
        #                 validated_data[f"{fk_field}_id"] = None
        #     validated_data.pop(fk_field, None)

        # --- Normalize fields, allowing None ---
        # if "client_code" in validated_data:
        #     validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
        # if "dob" in validated_data:
        #     validated_data["dob"] = self.clean_date(validated_data.get("dob"))
        # if "anniversary_date" in validated_data:
        #     validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
        # if "preferred_contact_method" in validated_data:
        #     validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
        #         validated_data.get("preferred_contact_method")
        #     )
        
        validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
        validated_data["dob"] = self.clean_date(validated_data.get("dob"))
        validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
        if "preferred_contact_method" in validated_data:
            validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
                validated_data.get("preferred_contact_method")
            )

        # --- Handle uploaded files, allowing None ---
        files = self.context.get("request").FILES if self.context.get("request") else {}
        for field in ["aadhaar_card_file", "pan_card_file"]:
            if field in files:
                # If a new file is uploaded, set it
                setattr(instance, field, files[field])
            elif field in validated_data:
                # If field is explicitly set to None or empty, allow it
                file_val = validated_data.pop(field)
                if file_val is None or file_val in ["", "null"]:
                    setattr(instance, field, None)
                    
         # --- Helper to skip empty dicts ---
        def is_empty(d):
            return not any(v for v in d.values() if v not in [None, "", [], {}])


        # --- Update main client fields, preserving existing values ---
        skip_keys = {
            "client_passport", "client_visa", "client_documents",
            "client_companies", "client_frequent_flyers", "travel_insurance",
        }
        
        # for attr, value in validated_data.items():
        #     if attr not in skip_keys:
        #         setattr(instance, attr, value)
        
        for attr, value in validated_data.items():
            if attr in skip_keys:
                continue
            setattr(instance, attr, value)
        
        instance.save()

       
        # --- Passports ---
        passports_data = validated_data.pop("client_passport", [])
        keep_ids = []
        for pd in passports_data:
            if is_empty(pd):
                continue
            pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
            obj_id = pd.pop("id", None)
            if obj_id:
                ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
                keep_ids.append(obj_id)
            else:
                obj, created = ClientPassport.objects.update_or_create(ref_client=instance, **pd)
                keep_ids.append(obj.id)
        ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

        # --- Visas ---
        visas_data = validated_data.pop("client_visa", [])
        keep_ids = []
        for vd in visas_data:
            print("here we are printing the client visa obj : ", vd)
            obj_id = vd.pop("id", None)
            print("here we are printing the client visa obj id : ", obj_id)
            if is_empty(vd):
                continue
            vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
            vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
            vd["visa_type"] = self.clean_str(vd.get("visa_type"))
            if "ref_visa_country" in vd:
                country_val = vd.pop("ref_visa_country", None)
                if country_val is None or country_val in ["", "null"]:
                    vd["ref_visa_country_id"] = None
                else:
                    if isinstance(country_val, dict):
                        vd["ref_visa_country_id"] = country_val.get("id")
                    elif isinstance(country_val, Countries):
                        vd["ref_visa_country_id"] = country_val.id
                    else:
                        try:
                            vd["ref_visa_country_id"] = int(country_val)
                        except (ValueError, TypeError):
                            vd["ref_visa_country_id"] = None
            if obj_id:
                try:
                    print(f"Updating ClientVisa id={obj_id} for client {instance.pk}")
                    ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
                    keep_ids.append(obj_id)
                except ClientVisa.DoesNotExist:
                    print(f"ClientVisa with id {obj_id} not found for client {instance.pk}")
            else:
                print(f"Creating new ClientVisa for client {instance.pk}")
                obj, created = ClientVisa.objects.update_or_create(
                    ref_client=instance,
                    visa_type=vd.get("visa_type"),
                    ref_visa_country_id=vd.get("ref_visa_country_id"),
                    defaults=vd
                )
                keep_ids.append(obj.id)
        ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

        # --- Travel Insurance ---
        insurances_data = validated_data.pop("travel_insurance", [])
        keep_ids = []
        for ins in insurances_data:
            if is_empty(ins):
                continue
            ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
            ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
            obj_id = ins.pop("id", None)
            if obj_id:
                ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
                keep_ids.append(obj_id)
            else:
                obj, created = ClientTravelInsurance.objects.update_or_create(ref_client=instance, **ins)
                keep_ids.append(obj.id)
        ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

        # --- Documents ---
        docs_data = validated_data.pop("client_documents", [])
        keep_ids = []
        for doc in docs_data:
            if is_empty(doc):
                continue
            obj_id = doc.pop("id", None)
            if obj_id:
                ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
                keep_ids.append(obj_id)
            else:
                obj, created = ClientDocument.objects.update_or_create(ref_client=instance, **doc)
                keep_ids.append(obj.id)
        ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

        # --- Company Associations ---
        companies_data = validated_data.pop("client_companies", [])
        keep_ids = []
        for comp in companies_data:
            if is_empty(comp):
                continue
            ref_company = comp.pop("ref_company", None)
            if ref_company is None:
                comp["ref_company_id"] = None
            else:
                if isinstance(ref_company, dict):
                    comp["ref_company_id"] = ref_company.get("id")
                elif isinstance(ref_company, Company):
                    comp["ref_company_id"] = ref_company.id
                else:
                    try:
                        comp["ref_company_id"] = int(ref_company)
                    except (ValueError, TypeError):
                        comp["ref_company_id"] = None
            obj_id = comp.pop("id", None)
            if obj_id:
                AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
                keep_ids.append(obj_id)
            else:
                obj, created = AssocClientCompany.objects.update_or_create(ref_client=instance, **comp)
                keep_ids.append(obj.id)
        AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

        # --- Frequent Flyers ---
        frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
        keep_ids = []
        for ff in frequent_flyers_data:
            if is_empty(ff):
                continue
            airline_val = ff.pop("ref_airline", None)
            if airline_val is None:
                ff["ref_airline_id"] = None
            else:
                if isinstance(airline_val, dict):
                    ff["ref_airline_id"] = airline_val.get("id")
                elif isinstance(airline_val, Airlines):
                    ff["ref_airline_id"] = airline_val.id
                else:
                    try:
                        ff["ref_airline_id"] = int(airline_val)
                    except (ValueError, TypeError):
                        ff["ref_airline_id"] = None
            ff["ff_no"] = self.clean_str(ff.get("ff_no"))
            obj_id = ff.pop("id", None)
            if obj_id:
                ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
                keep_ids.append(obj_id)
            else:
                obj, created = ClientFrequentFlyer.objects.update_or_create(ref_client=instance, **ff)
                keep_ids.append(obj.id)
        ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

        return instance
    
    # Helper method (add inside serializer)
    def ensure_list(self, value):
        """
        Ensure the given value is always a list of dicts.
        Handles cases where DRF/multipart wraps in extra list.
        """
        if isinstance(value, dict):
            return [value]
        if isinstance(value, list):
            # flatten nested lists (e.g. [[{...}]] -> [{...}])
            flat = []
            for v in value:
                if isinstance(v, list):
                    flat.extend(v)
                elif v:
                    flat.append(v)
            return flat
        return []
    
    # ---------------- Representation Override ----------------
    def to_representation(self, instance):
        data = super().to_representation(instance)

        # normalize reverse relations to lists using `.all()`
        if hasattr(instance, "client_passport"):
            data["client_passport"] = ClientPassportSerializer(
                instance.client_passport.all(), many=True, context=self.context
            ).data

        if hasattr(instance, "client_visa"):
            data["client_visa"] = ClientVisaSerializer(
                instance.client_visa.all(), many=True, context=self.context
            ).data

        if hasattr(instance, "travel_insurance"):
            data["travel_insurance"] = ClientTravelInsuranceSerializer(
                instance.travel_insurance.all(), many=True, context=self.context
            ).data

        if hasattr(instance, "client_companies"):
            data["client_companies"] = AssocClientCompanySerializer(
                instance.client_companies.all(), many=True, context=self.context
            ).data

        if hasattr(instance, "client_documents"):
            data["client_documents"] = OtherDocumentSerializer(
                instance.client_documents.all(), many=True, context=self.context
            ).data

        if hasattr(instance, "client_frequent_flyers"):
            data["client_frequent_flyers"] = FrequentflyerSerializer(
                instance.client_frequent_flyers.all(), many=True, context=self.context
            ).data

        # Keep your read-only SerializerMethodField
        data["familyMembers"] = self.get_familyMembers(instance)

        return data

# override the 1st nested obj of multiple ogj of fk models 
# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True
#     )
#     preferred_airline = AirlinesSerializer(read_only=True)

#     ref_visa_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )

#     # --- Nested serializers (all many=True) ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
#             "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_row(self, row, file_map=None):
#         print(">>>>>>> clean_row Details <<<<<<<<<<", row)
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         if "id" in cleaned and (cleaned["id"] is None or str(cleaned["id"]).strip() == ""):
#             cleaned.pop("id")

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def clean_str(self, value):
#         print(">>>>>>> clean_str Details <<<<<<<<<<", value)
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def safe_fk(self, model_class, value):
#         print(">>>>>>> safe_fk Details <<<<<<<<<<", value)
#         if not value:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             value_int = int(value)
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         print(">>>>>>> normalize_preferred_contact_method Details<<<<<<<<<<", value)
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         def unwrap_scalars(data, skip_keys):
#             result = {}
#             for k, v in data.items():
#                 if k in skip_keys:
#                     result[k] = v
#                 elif isinstance(v, list) and len(v) == 1:
#                     result[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     result[k] = None
#                 else:
#                     result[k] = v
#             return result

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue

#         for i, p in enumerate(expanded_passports):
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                 p["passport_file"] = None

#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         for i, p in enumerate(data.get("fam_passport", [])):
#             if isinstance(p, dict):
#                 if "fam_passport_no" in p:
#                     p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
#                 if "fam_passport_expiry_date" in p:
#                     p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))
#                 file_key = f"fam_passport[{i}][fam_passport_file]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     p["fam_passport_passport_file"] = self.context["request"].FILES[file_key]
#                 elif "fam_passport_passport_file" in p and p["fam_passport_passport_file"] in ["", "null", None]:
#                     p["fam_passport_passport_file"] = None

#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict) and "relation_with_other_client_code" in r:
#                 r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None

#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 file_key = f"client_documents[{i}][other_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     d["other_document"] = self.context["request"].FILES[file_key]
#                 elif "other_document" in d and d["other_document"] in ["", "null", None]:
#                     d["other_document"] = None
#                 if "other_document_name" in d:
#                     d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # --- Nested: Visa ---
#         print("here we are printing client visa data", data.get("client_visa", []))
#         print("here we are printing data", data)
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 # Validate id as an integer
#                 if "id" in v:
#                     try:
#                         v["id"] = int(v["id"]) if v["id"] else None
#                     except (ValueError, TypeError):
#                         v["id"] = None
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None

#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))

#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for p in fam.get("fam_passport", []):
#                         if isinstance(p, dict):
#                             if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                                 expanded_fam_passports.extend(expand_passports(p))
#                             else:
#                                 expanded_fam_passports.append(p)
#                         else:
#                             continue

#                     for pi, p in enumerate(expanded_fam_passports):
#                         if isinstance(p.get("passport_no"), list):
#                             p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                         if isinstance(p.get("passport_expiry_date"), list):
#                             p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         if isinstance(p.get("passport_file"), list):
#                             p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                         elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                             p["passport_file"] = None

#                         if "passport_no" in p:
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         if "passport_expiry_date" in p:
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                     fam["fam_passport"] = expanded_fam_passports

#         return data

#     # ---------------- Serializer Methods ----------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # Define FK fields and their corresponding models
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         # Handle FK fields
#         for fk_field in fk_fields:
#             fk_value = validated_data.get(fk_field)
#             if fk_value:
#                 if isinstance(fk_value, dict):
#                     fk_value = fk_value.get("id")
#                 model_class = fk_models.get(fk_field)
#                 if isinstance(fk_value, int):
#                     validated_data[f"{fk_field}_id"] = fk_value
#                 elif isinstance(fk_value, model_class):
#                     validated_data[f"{fk_field}_id"] = fk_value.id
#                 else:
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         validated_data[f"{fk_field}_id"] = fk_instance.id
#                     except (ValueError, TypeError, model_class.DoesNotExist):
#                         validated_data[f"{fk_field}_id"] = None
#             validated_data.pop(fk_field, None)

#         # Normalize fields
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # Handle uploaded files
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if file_val is None or file_val in ["", "null"]:
#                     setattr(instance, field, None)

#         # Helper to skip empty dicts
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # Update main client fields
#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#             "family_members", "fam_passport", "relationsWithOthers"
#         }

#         for attr, value in validated_data.items():
#             if attr in skip_keys:
#                 continue
#             setattr(instance, attr, value)

#         instance.save()

#         # --- Passports ---
#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             if is_empty(pd):
#                 continue
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             obj_id = pd.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating ClientPassport id={obj_id} for client {instance.pk}")
#                     ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                     keep_ids.append(obj_id)
#                 except ClientPassport.DoesNotExist:
#                     print(f"ClientPassport with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientPassport for client {instance.pk}")
#                 obj, created = ClientPassport.objects.update_or_create(ref_client=instance, defaults=pd)
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Visas ---
#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for vd in visas_data:
#             print("here we are printing the client visa obj : ", vd)
#             obj_id = vd.pop("id", None)
#             print("here we are printing the client visa obj id : ", obj_id)
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_val = vd.pop("ref_visa_country", None)
#             if country_val is None:
#                 vd["ref_visa_country_id"] = None
#             else:
#                 if isinstance(country_val, dict):
#                     vd["ref_visa_country_id"] = country_val.get("id")
#                 elif isinstance(country_val, Countries):
#                     vd["ref_visa_country_id"] = country_val.id
#                 else:
#                     try:
#                         vd["ref_visa_country_id"] = int(country_val)
#                     except (ValueError, TypeError):
#                         vd["ref_visa_country_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientVisa id={obj_id} for client {instance.pk}")
#                     ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                     keep_ids.append(obj_id)
#                 except ClientVisa.DoesNotExist:
#                     print(f"ClientVisa with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientVisa for client {instance.pk}")
#                 obj, created = ClientVisa.objects.update_or_create(ref_client=instance, defaults=vd)
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Travel Insurance ---
#         insurances_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for ins in insurances_data:
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             obj_id = ins.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating ClientTravelInsurance id={obj_id} for client {instance.pk}")
#                     ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                     keep_ids.append(obj_id)
#                 except ClientTravelInsurance.DoesNotExist:
#                     print(f"ClientTravelInsurance with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientTravelInsurance for client {instance.pk}")
#                 obj, created = ClientTravelInsurance.objects.update_or_create(ref_client=instance, defaults=ins)
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Documents ---
#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for doc in docs_data:
#             if is_empty(doc):
#                 continue
#             obj_id = doc.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating ClientDocument id={obj_id} for client {instance.pk}")
#                     ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                     keep_ids.append(obj_id)
#                 except ClientDocument.DoesNotExist:
#                     print(f"ClientDocument with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientDocument for client {instance.pk}")
#                 obj, created = ClientDocument.objects.update_or_create(ref_client=instance, defaults=doc)
#                 keep_ids.append(obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Company Associations ---
#         companies_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for comp in companies_data:
#             if is_empty(comp):
#                 continue
#             ref_company = comp.pop("ref_company", None)
#             if ref_company is None:
#                 comp["ref_company_id"] = None
#             else:
#                 if isinstance(ref_company, dict):
#                     comp["ref_company_id"] = ref_company.get("id")
#                 elif isinstance(ref_company, Company):
#                     comp["ref_company_id"] = ref_company.id
#                 else:
#                     try:
#                         comp["ref_company_id"] = int(ref_company)
#                     except (ValueError, TypeError):
#                         comp["ref_company_id"] = None
#             obj_id = comp.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating AssocClientCompany id={obj_id} for client {instance.pk}")
#                     AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                     keep_ids.append(obj_id)
#                 except AssocClientCompany.DoesNotExist:
#                     print(f"AssocClientCompany with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new AssocClientCompany for client {instance.pk}")
#                 obj, created = AssocClientCompany.objects.update_or_create(ref_client=instance, defaults=comp)
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Frequent Flyers ---
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for ff in frequent_flyers_data:
#             if is_empty(ff):
#                 continue
#             airline_val = ff.pop("ref_airline", None)
#             if airline_val is None:
#                 ff["ref_airline_id"] = None
#             else:
#                 if isinstance(airline_val, dict):
#                     ff["ref_airline_id"] = airline_val.get("id")
#                 elif isinstance(airline_val, Airlines):
#                     ff["ref_airline_id"] = airline_val.id
#                 else:
#                     try:
#                         ff["ref_airline_id"] = int(airline_val)
#                     except (ValueError, TypeError):
#                         ff["ref_airline_id"] = None
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             obj_id = ff.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating ClientFrequentFlyer id={obj_id} for client {instance.pk}")
#                     ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                     keep_ids.append(obj_id)
#                 except ClientFrequentFlyer.DoesNotExist:
#                     print(f"ClientFrequentFlyer with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientFrequentFlyer for client {instance.pk}")
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(ref_client=instance, defaults=ff)
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

#     # ---------------- Create ----------------
#     # (Unchanged, included for completeness)
#     @transaction.atomic
#     def create(self, validated_data):
#         def unwrap(value):
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         validated_data["country_code"] = country_code_instance
#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = (
#                 airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#             )
#         if country:
#             client.residential_country = (
#                 country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#             )
#         if state:
#             client.residential_state = (
#                 state if isinstance(state, State) else self.safe_fk(state, State)
#             )
#         if city:
#             client.residential_city = (
#                 city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#             )
#         client.save()

#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"]:
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value

#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"]:
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())

#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))

#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no and f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#         return client

#     # ---------------- Representation Override ----------------
#     def to_representation(self, instance):
#         data = super().to_representation(instance)

#         if hasattr(instance, "client_passport"):
#             data["client_passport"] = ClientPassportSerializer(
#                 instance.client_passport.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_visa"):
#             data["client_visa"] = ClientVisaSerializer(
#                 instance.client_visa.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "travel_insurance"):
#             data["travel_insurance"] = ClientTravelInsuranceSerializer(
#                 instance.travel_insurance.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_companies"):
#             data["client_companies"] = AssocClientCompanySerializer(
#                 instance.client_companies.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_documents"):
#             data["client_documents"] = OtherDocumentSerializer(
#                 instance.client_documents.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_frequent_flyers"):
#             data["client_frequent_flyers"] = FrequentflyerSerializer(
#                 instance.client_frequent_flyers.all(), many=True, context=self.context
#             ).data

#         data["familyMembers"] = self.get_familyMembers(instance)

#         return data

#     def ensure_list(self, value):
#         if isinstance(value, dict):
#             return [value]
#         if isinstance(value, list):
#             flat = []
#             for v in value:
#                 if isinstance(v, list):
#                     flat.extend(v)
#                 elif v:
#                     flat.append(v)
#             return flat
#         return []

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True
#     )
#     preferred_airline = AirlinesSerializer(read_only=True)
#     ref_visa_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )

#     # --- Nested serializers (all many=True) ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
#             "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_row(self, row, file_map=None):
#         print(">>>>>>> clean_row Details <<<<<<<<<<", row)
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         # Preserve id as an integer
#         if "id" in cleaned:
#             try:
#                 cleaned["id"] = int(cleaned["id"]) if cleaned["id"] else None
#             except (ValueError, TypeError):
#                 cleaned["id"] = None

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def clean_str(self, value):
#         print(">>>>>>> clean_str Details <<<<<<<<<<", value)
#         # Handle empty or null-like values
#         if value in ["", None, [], [""]]:
#             return None
#         # If value is a list, extract single item or join multiple items
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         # Handle strings that represent serialized lists (e.g., "[item]")
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         # Convert to string, strip whitespace, and return None if empty
#         return str(value).strip() or None

#     def safe_fk(self, model_class, value):
#         print(">>>>>>> safe_fk Details <<<<<<<<<<", value)
#         if not value:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             value_int = int(value)
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         print(">>>>>>> normalize_preferred_contact_method Details<<<<<<<<<<", value)
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         def unwrap_scalars(data, skip_keys):
#             result = {}
#             for k, v in data.items():
#                 if k in skip_keys:
#                     result[k] = v
#                 elif isinstance(v, list) and len(v) == 1:
#                     result[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     result[k] = None
#                 else:
#                     result[k] = v
#             return result

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     # Preserve id as an integer
#                     if "id" in item:
#                         try:
#                             item["id"] = int(item["id"]) if item["id"] else None
#                         except (ValueError, TypeError):
#                             item["id"] = None
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # --- Nested: Passport (Primary client) ---
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 # Preserve id as an integer
#                 if "id" in p:
#                     try:
#                         p["id"] = int(p["id"]) if p["id"] else None
#                     except (ValueError, TypeError):
#                         p["id"] = None
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue

#         for i, p in enumerate(expanded_passports):
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                 p["passport_file"] = None

#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         # --- Nested: Familiar Passports ---
#         for i, p in enumerate(data.get("fam_passport", [])):
#             if isinstance(p, dict):
#                 if "fam_passport_no" in p:
#                     p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
#                 if "fam_passport_expiry_date" in p:
#                     p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))
#                 file_key = f"fam_passport[{i}][fam_passport_file]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     p["fam_passport_passport_file"] = self.context["request"].FILES[file_key]
#                 elif "fam_passport_passport_file" in p and p["fam_passport_passport_file"] in ["", "null", None]:
#                     p["fam_passport_passport_file"] = None

#         # --- Nested: Relations with Others ---
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict) and "relation_with_other_client_code" in r:
#                 r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

#         # --- Nested: Companies ---
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None

#         # --- Nested: Documents ---
#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 file_key = f"client_documents[{i}][other_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     d["other_document"] = self.context["request"].FILES[file_key]
#                 elif "other_document" in d and d["other_document"] in ["", "null", None]:
#                     d["other_document"] = None
#                 if "other_document_name" in d:
#                     d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         # --- Nested: Frequent Flyers ---
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # --- Nested: Visa ---
#         print("here we are printing client visa data", data.get("client_visa", []))
#         print("here we are printing data", data)
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 # Preserve id as an integer
#                 if "id" in v:
#                     try:
#                         v["id"] = int(v["id"]) if v["id"] else None
#                     except (ValueError, TypeError):
#                         v["id"] = None
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None
#                 if "passport_size_photograph" in v and v["passport_size_photograph"] in ["", "null", None]:
#                     v["passport_size_photograph"] = None

#         # --- Nested: Travel Insurance ---
#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))
#                 if "insurance_document" in t and t["insurance_document"] in ["", "null", None]:
#                     t["insurance_document"] = None

#         # --- Nested: Family Members ---
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for p in fam.get("fam_passport", []):
#                         if isinstance(p, dict):
#                             # Preserve id as an integer
#                             if "id" in p:
#                                 try:
#                                     p["id"] = int(p["id"]) if p["id"] else None
#                                 except (ValueError, TypeError):
#                                     p["id"] = None
#                             if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                                 expanded_fam_passports.extend(expand_passports(p))
#                             else:
#                                 expanded_fam_passports.append(p)
#                         else:
#                             continue

#                     for pi, p in enumerate(expanded_fam_passports):
#                         if isinstance(p.get("passport_no"), list):
#                             p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                         if isinstance(p.get("passport_expiry_date"), list):
#                             p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         if isinstance(p.get("passport_file"), list):
#                             p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                         elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                             p["passport_file"] = None

#                         if "passport_no" in p:
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         if "passport_expiry_date" in p:
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                     fam["fam_passport"] = expanded_fam_passports

#         return data

#     # ---------------- Serializer Methods ----------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # Define FK fields and their corresponding models
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         # Handle FK fields
#         for fk_field in fk_fields:
#             fk_value = validated_data.get(fk_field)
#             if fk_value:
#                 if isinstance(fk_value, dict):
#                     fk_value = fk_value.get("id")
#                 model_class = fk_models.get(fk_field)
#                 if isinstance(fk_value, int):
#                     validated_data[f"{fk_field}_id"] = fk_value
#                 elif isinstance(fk_value, model_class):
#                     validated_data[f"{fk_field}_id"] = fk_value.id
#                 else:
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         validated_data[f"{fk_field}_id"] = fk_instance.id
#                     except (ValueError, TypeError, model_class.DoesNotExist):
#                         validated_data[f"{fk_field}_id"] = None
#             validated_data.pop(fk_field, None)

#         # Normalize fields
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # Handle uploaded files
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if file_val is None or file_val in ["", "null"]:
#                     setattr(instance, field, None)

#         # Helper to skip empty dicts
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # Update main client fields
#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#             "family_members", "fam_passport", "relationsWithOthers"
#         }

#         for attr, value in validated_data.items():
#             if attr in skip_keys:
#                 continue
#             setattr(instance, attr, value)

#         instance.save()

#         # --- Passports ---
#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             print("here we are printing the client passport obj : ", pd)
#             obj_id = pd.pop("id", None)
#             print("here we are printing the client passport obj id : ", obj_id)
#             if is_empty(pd):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             if obj_id:
#                 try:
#                     print(f"Updating ClientPassport id={obj_id} for client {instance.pk}")
#                     ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                     keep_ids.append(obj_id)
#                 except ClientPassport.DoesNotExist:
#                     print(f"ClientPassport with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientPassport for client {instance.pk}")
#                 obj, created = ClientPassport.objects.update_or_create(
#                     ref_client=instance,
#                     passport_no=pd.get("passport_no"),
#                     defaults=pd
#                 )
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Visas ---
#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for vd in visas_data:
#             print("here we are printing the client visa obj : ", vd)
#             obj_id = vd.pop("id", None)
#             print("here we are printing the client visa obj id : ", obj_id)
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_val = vd.pop("ref_visa_country", None)
#             if country_val is None:
#                 vd["ref_visa_country_id"] = None
#             else:
#                 if isinstance(country_val, dict):
#                     vd["ref_visa_country_id"] = country_val.get("id")
#                 elif isinstance(country_val, Countries):
#                     vd["ref_visa_country_id"] = country_val.id
#                 else:
#                     try:
#                         vd["ref_visa_country_id"] = int(country_val)
#                     except (ValueError, TypeError):
#                         vd["ref_visa_country_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientVisa id={obj_id} for client {instance.pk}")
#                     ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                     keep_ids.append(obj_id)
#                 except ClientVisa.DoesNotExist:
#                     print(f"ClientVisa with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientVisa for client {instance.pk}")
#                 obj, created = ClientVisa.objects.update_or_create(
#                     ref_client=instance,
#                     visa_type=vd.get("visa_type"),
#                     ref_visa_country_id=vd.get("ref_visa_country_id"),
#                     defaults=vd
#                 )
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Travel Insurance ---
#         insurances_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for ins in insurances_data:
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             obj_id = ins.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating ClientTravelInsurance id={obj_id} for client {instance.pk}")
#                     ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                     keep_ids.append(obj_id)
#                 except ClientTravelInsurance.DoesNotExist:
#                     print(f"ClientTravelInsurance with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientTravelInsurance for client {instance.pk}")
#                 obj, created = ClientTravelInsurance.objects.update_or_create(
#                     ref_client=instance,
#                     defaults=ins
#                 )
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Documents ---
#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for doc in docs_data:
#             if is_empty(doc):
#                 continue
#             doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#             obj_id = doc.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating ClientDocument id={obj_id} for client {instance.pk}")
#                     ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                     keep_ids.append(obj_id)
#                 except ClientDocument.DoesNotExist:
#                     print(f"ClientDocument with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientDocument for client {instance.pk}")
#                 obj, created = ClientDocument.objects.update_or_create(
#                     ref_client=instance,
#                     other_document_name=doc.get("other_document_name"),
#                     defaults=doc
#                 )
#                 keep_ids.append(obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Company Associations ---
#         companies_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for comp in companies_data:
#             if is_empty(comp):
#                 continue
#             ref_company = comp.pop("ref_company", None)
#             if ref_company is None:
#                 comp["ref_company_id"] = None
#             else:
#                 if isinstance(ref_company, dict):
#                     comp["ref_company_id"] = ref_company.get("id")
#                 elif isinstance(ref_company, Company):
#                     comp["ref_company_id"] = ref_company.id
#                 else:
#                     try:
#                         comp["ref_company_id"] = int(ref_company)
#                     except (ValueError, TypeError):
#                         comp["ref_company_id"] = None
#             comp["designation"] = self.clean_str(comp.get("designation"))
#             obj_id = comp.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating AssocClientCompany id={obj_id} for client {instance.pk}")
#                     AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                     keep_ids.append(obj_id)
#                 except AssocClientCompany.DoesNotExist:
#                     print(f"AssocClientCompany with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new AssocClientCompany for client {instance.pk}")
#                 obj, created = AssocClientCompany.objects.update_or_create(
#                     ref_client=instance,
#                     ref_company_id=comp.get("ref_company_id"),
#                     defaults=comp
#                 )
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Frequent Flyers ---
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for ff in frequent_flyers_data:
#             if is_empty(ff):
#                 continue
#             airline_val = ff.pop("ref_airline", None)
#             if airline_val is None:
#                 ff["ref_airline_id"] = None
#             else:
#                 if isinstance(airline_val, dict):
#                     ff["ref_airline_id"] = airline_val.get("id")
#                 elif isinstance(airline_val, Airlines):
#                     ff["ref_airline_id"] = airline_val.id
#                 else:
#                     try:
#                         ff["ref_airline_id"] = int(airline_val)
#                     except (ValueError, TypeError):
#                         ff["ref_airline_id"] = None
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             obj_id = ff.pop("id", None)
#             if obj_id:
#                 try:
#                     print(f"Updating ClientFrequentFlyer id={obj_id} for client {instance.pk}")
#                     ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                     keep_ids.append(obj_id)
#                 except ClientFrequentFlyer.DoesNotExist:
#                     print(f"ClientFrequentFlyer with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientFrequentFlyer for client {instance.pk}")
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(
#                     ref_client=instance,
#                     ref_airline_id=ff.get("ref_airline_id"),
#                     defaults=ff
#                 )
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
#         def unwrap(value):
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         validated_data["country_code"] = country_code_instance
#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = (
#                 airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#             )
#         if country:
#             client.residential_country = (
#                 country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#             )
#         if state:
#             client.residential_state = (
#                 state if isinstance(state, State) else self.safe_fk(state, State)
#             )
#         if city:
#             client.residential_city = (
#                 city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#             )
#         client.save()

#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd.get("passport_no") or pd.get("passport_expiry_date"):
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins.get("insurance_from_date") or ins.get("insurance_to_date"):
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())

#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))

#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no and f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#         return client

#     # ---------------- Representation Override ----------------
#     def to_representation(self, instance):
#         data = super().to_representation(instance)

#         if hasattr(instance, "client_passport"):
#             data["client_passport"] = ClientPassportSerializer(
#                 instance.client_passport.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_visa"):
#             data["client_visa"] = ClientVisaSerializer(
#                 instance.client_visa.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "travel_insurance"):
#             data["travel_insurance"] = ClientTravelInsuranceSerializer(
#                 instance.travel_insurance.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_companies"):
#             data["client_companies"] = AssocClientCompanySerializer(
#                 instance.client_companies.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_documents"):
#             data["client_documents"] = OtherDocumentSerializer(
#                 instance.client_documents.all(), many=True, context=self.context
#             ).data

#         if hasattr(instance, "client_frequent_flyers"):
#             data["client_frequent_flyers"] = FrequentflyerSerializer(
#                 instance.client_frequent_flyers.all(), many=True, context=self.context
#             ).data

#         data["familyMembers"] = self.get_familyMembers(instance)

#         return data

#     def ensure_list(self, value):
#         if isinstance(value, dict):
#             return [value]
#         if isinstance(value, list):
#             flat = []
#             for v in value:
#                 if isinstance(v, list):
#                     flat.extend(v)
#                 elif v:
#                     flat.append(v)
#             return flat
#         return []
    
# second last used serilaiser 
# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_state = serializers.PrimaryKeyRelatedField(queryset=State.objects.all(), required=False, allow_null=True)
#     residential_city = serializers.PrimaryKeyRelatedField(queryset=Cities.objects.all(), required=False, allow_null=True)
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(queryset=Airlines.objects.all(), required=False, allow_null=True)

#     # --- Nested serializers ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
#             "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_str(self, value):
#         print(">>>>>>> clean_str Details <<<<<<<<<<", value)
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def clean_row(self, row, file_map=None):
#         print(">>>>>>> clean_row Details <<<<<<<<<<", row)
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         # Preserve id as an integer
#         if "id" in cleaned:
#             try:
#                 cleaned["id"] = int(cleaned["id"]) if cleaned["id"] else None
#             except (ValueError, TypeError):
#                 cleaned["id"] = None

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def safe_fk(self, model_class, value):
#         print(">>>>>>> safe_fk Details <<<<<<<<<<", value)
#         if not value:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             value_int = int(value)
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         print(">>>>>>> normalize_preferred_contact_method Details<<<<<<<<<<", value)
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         def unwrap_scalars(data, skip_keys):
#             result = {}
#             for k, v in data.items():
#                 if k in skip_keys:
#                     result[k] = v
#                 elif isinstance(v, list) and len(v) == 1:
#                     result[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     result[k] = None
#                 else:
#                     result[k] = v
#             return result

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     # Preserve id as an integer
#                     if "id" in item:
#                         try:
#                             item["id"] = int(item["id"]) if item["id"] else None
#                         except (ValueError, TypeError):
#                             item["id"] = None
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # --- Nested: Client Passport ---
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if "id" in p:
#                     try:
#                         p["id"] = int(p["id"]) if p["id"] else None
#                     except (ValueError, TypeError):
#                         p["id"] = None
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue

#         for i, p in enumerate(expanded_passports):
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                 p["passport_file"] = None

#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         # --- Nested: Client Visa ---
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 if "id" in v:
#                     try:
#                         v["id"] = int(v["id"]) if v["id"] else None
#                     except (ValueError, TypeError):
#                         v["id"] = None
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None
#                 if "passport_size_photograph" in v and v["passport_size_photograph"] in ["", "null", None]:
#                     v["passport_size_photograph"] = None
#                 if "visa_type" in v:
#                     v["visa_type"] = self.clean_str(v.get("visa_type"))

#         # --- Nested: Travel Insurance ---
#         # Inside the validate method of FullClientSerializer
#         # --- Nested: Travel Insurance ---
#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "id" in t:
#                     try:
#                         t["id"] = int(t["id"]) if t["id"] else None
#                     except (ValueError, TypeError):
#                         t["id"] = None
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))
#                 if "insurance_document" in t and t["insurance_document"] in ["", "null", None]:
#                     t["insurance_document"] = None
                    
#         # --- Nested: Client Documents ---
#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 if "id" in d:
#                     try:
#                         d["id"] = int(d["id"]) if d["id"] else None
#                     except (ValueError, TypeError):
#                         d["id"] = None
#                 file_key = f"client_documents[{i}][other_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     d["other_document"] = self.context["request"].FILES[file_key]
#                 elif "other_document" in d and d["other_document"] in ["", "null", None]:
#                     d["other_document"] = None
#                 if "other_document_name" in d:
#                     d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         # --- Nested: Client Companies ---
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "id" in c:
#                     try:
#                         c["id"] = int(c["id"]) if c["id"] else None
#                     except (ValueError, TypeError):
#                         c["id"] = None
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None
#                 if "ref_company" in c and c["ref_company"] in ["", "null", None]:
#                     c["ref_company"] = None

#         # --- Nested: Frequent Flyers ---
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "id" in f:
#                     try:
#                         f["id"] = int(f["id"]) if f["id"] else None
#                     except (ValueError, TypeError):
#                         f["id"] = None
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # --- Nested: Family Members ---
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "id" in fam:
#                     try:
#                         fam["id"] = int(fam["id"]) if fam["id"] else None
#                     except (ValueError, TypeError):
#                         fam["id"] = None
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "salutation" in fam:
#                     fam["salutation"] = self.clean_str(fam.get("salutation"))
#                 if "firstName" in fam:
#                     fam["firstName"] = self.clean_str(fam.get("firstName"))
#                 if "middleName" in fam:
#                     fam["middleName"] = self.clean_str(fam.get("middleName"))
#                 if "lastName" in fam:
#                     fam["lastName"] = self.clean_str(fam.get("lastName"))
#                 if "relation" in fam:
#                     fam["relation"] = self.clean_str(fam.get("relation"))
#                 if "crossrelation" in fam:
#                     fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#                 if "contactNo" in fam:
#                     fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#                 if "email" in fam:
#                     fam["email"] = self.clean_str(fam.get("email"))
#                 if "gender" in fam:
#                     fam["gender"] = self.clean_str(fam.get("gender"))
#                 if "occupation" in fam:
#                     fam["occupation"] = self.clean_str(fam.get("occupation"))
#                 if "aadhaarNo" in fam:
#                     fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#                 if "panNo" in fam:
#                     fam["panNo"] = self.clean_str(fam.get("panNo"))
#                 if "residential_address" in fam:
#                     fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#                 if "residential_pincode" in fam:
#                     fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for p in fam.get("fam_passport", []):
#                         if isinstance(p, dict):
#                             if "id" in p:
#                                 try:
#                                     p["id"] = int(p["id"]) if p["id"] else None
#                                 except (ValueError, TypeError):
#                                     p["id"] = None
#                             if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                                 expanded_fam_passports.extend(expand_passports(p))
#                             else:
#                                 expanded_fam_passports.append(p)
#                         else:
#                             continue

#                     for pi, p in enumerate(expanded_fam_passports):
#                         if isinstance(p.get("passport_no"), list):
#                             p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                         if isinstance(p.get("passport_expiry_date"), list):
#                             p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         if isinstance(p.get("passport_file"), list):
#                             p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                         elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                             p["passport_file"] = None

#                         if "passport_no" in p:
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         if "passport_expiry_date" in p:
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                     fam["fam_passport"] = expanded_fam_passports

#         # --- Nested: Relations with Others ---
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict):
#                 if "id" in r:
#                     try:
#                         r["id"] = int(r["id"]) if r["id"] else None
#                     except (ValueError, TypeError):
#                         r["id"] = None
#                 if "relation_with_other_client_code" in r:
#                     r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))
#                 if "relation" in r:
#                     r["relation"] = self.clean_str(r.get("relation"))
#                 if "crossRelation" in r:
#                     r["crossRelation"] = self.clean_str(r.get("crossRelation"))
#                 if "fromIndex" in r and r["fromIndex"] in ["", "null", None]:
#                     r["fromIndex"] = None
#                 if "toIndex" in r and r["toIndex"] in ["", "null", None]:
#                     r["toIndex"] = None

#         return data

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # Define FK fields and their corresponding models
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         # Handle FK fields
#         for fk_field in fk_fields:
#             fk_value = validated_data.get(fk_field)
#             if fk_value:
#                 if isinstance(fk_value, dict):
#                     fk_value = fk_value.get("id")
#                 model_class = fk_models.get(fk_field)
#                 if isinstance(fk_value, int):
#                     validated_data[f"{fk_field}_id"] = fk_value
#                 elif isinstance(fk_value, model_class):
#                     validated_data[f"{fk_field}_id"] = fk_value.id
#                 else:
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         validated_data[f"{fk_field}_id"] = fk_instance.id
#                     except (ValueError, TypeError, model_class.DoesNotExist):
#                         validated_data[f"{fk_field}_id"] = None
#             validated_data.pop(fk_field, None)

#         # Normalize fields
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # Handle uploaded files
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if file_val is None or file_val in ["", "null"]:
#                     setattr(instance, field, None)

#         # Helper to skip empty dicts
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # Update main client fields
#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#             "family_members", "fam_passport", "relationsWithOthers"
#         }

#         for attr, value in validated_data.items():
#             if attr in skip_keys or value is None:
#                 continue
#             setattr(instance, attr, value)

#         instance.save()

#         # --- Client Passport ---
#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             print("here we are printing the client passport obj : ", pd)
#             obj_id = pd.pop("id", None)
#             print("here we are printing the client passport obj id : ", obj_id)
#             if is_empty(pd):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             if obj_id:
#                 try:
#                     print(f"Updating ClientPassport id={obj_id} for client {instance.pk}")
#                     ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                     keep_ids.append(obj_id)
#                 except ClientPassport.DoesNotExist:
#                     print(f"ClientPassport with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientPassport for client {instance.pk}")
#                 obj, created = ClientPassport.objects.update_or_create(
#                     ref_client=instance,
#                     passport_no=pd.get("passport_no"),
#                     defaults=pd
#                 )
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Visa ---
#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for vd in visas_data:
#             print("here we are printing the client visa obj : ", vd)
#             obj_id = vd.pop("id", None)
#             print("here we are printing the client visa obj id : ", obj_id)
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             vd["visa_type"] = self.clean_str(vd.get("visa_type"))
#             country_val = vd.pop("ref_visa_country", None)
#             if country_val is None:
#                 vd["ref_visa_country_id"] = None
#             else:
#                 if isinstance(country_val, dict):
#                     vd["ref_visa_country_id"] = country_val.get("id")
#                 elif isinstance(country_val, Countries):
#                     vd["ref_visa_country_id"] = country_val.id
#                 else:
#                     try:
#                         vd["ref_visa_country_id"] = int(country_val)
#                     except (ValueError, TypeError):
#                         vd["ref_visa_country_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientVisa id={obj_id} for client {instance.pk}")
#                     ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                     keep_ids.append(obj_id)
#                 except ClientVisa.DoesNotExist:
#                     print(f"ClientVisa with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientVisa for client {instance.pk}")
#                 obj, created = ClientVisa.objects.update_or_create(
#                     ref_client=instance,
#                     visa_type=vd.get("visa_type"),
#                     ref_visa_country_id=vd.get("ref_visa_country_id"),
#                     defaults=vd
#                 )
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Travel Insurance ---
#         insurances_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for ins in insurances_data:
#             print("here we are printing the travel insurance obj : ", ins)
#             obj_id = ins.pop("id", None)
#             print("here we are printing the travel insurance obj id : ", obj_id)
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             # if ins.get("insurance_document") in ["", "null", None]:
#             #     ins["insurance_document"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientTravelInsurance id={obj_id} for client {instance.pk}")
#                     ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                     keep_ids.append(obj_id)
#                 except ClientTravelInsurance.DoesNotExist:
#                     print(f"ClientTravelInsurance with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientTravelInsurance for client {instance.pk}")
#                 lookup = {
#                     "ref_client": instance,
#                     "insurance_from_date": ins.get("insurance_from_date"),
#                     "insurance_to_date": ins.get("insurance_to_date")
#                 }
#                 obj, created = ClientTravelInsurance.objects.update_or_create(
#                     **lookup,
#                     defaults=ins
#                 )
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Documents ---
#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for doc in docs_data:
#             print("here we are printing the client document obj : ", doc)
#             obj_id = doc.pop("id", None)
#             print("here we are printing the client document obj id : ", obj_id)
#             if is_empty(doc):
#                 continue
#             doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#             if obj_id:
#                 try:
#                     print(f"Updating ClientDocument id={obj_id} for client {instance.pk}")
#                     ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                     keep_ids.append(obj_id)
#                 except ClientDocument.DoesNotExist:
#                     print(f"ClientDocument with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientDocument for client {instance.pk}")
#                 obj, created = ClientDocument.objects.update_or_create(
#                     ref_client=instance,
#                     other_document_name=doc.get("other_document_name"),
#                     defaults=doc
#                 )
#                 keep_ids.append(obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Companies ---
#         companies_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for comp in companies_data:
#             print("here we are printing the client company obj : ", comp)
#             obj_id = comp.pop("id", None)
#             print("here we are printing the client company obj id : ", obj_id)
#             if is_empty(comp):
#                 continue
#             comp["designation"] = self.clean_str(comp.get("designation"))
#             ref_company = comp.pop("ref_company", None)
#             if ref_company is None:
#                 comp["ref_company_id"] = None
#             else:
#                 if isinstance(ref_company, dict):
#                     comp["ref_company_id"] = ref_company.get("id")
#                 elif isinstance(ref_company, Company):
#                     comp["ref_company_id"] = ref_company.id
#                 else:
#                     try:
#                         comp["ref_company_id"] = int(ref_company)
#                     except (ValueError, TypeError):
#                         comp["ref_company_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating AssocClientCompany id={obj_id} for client {instance.pk}")
#                     AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                     keep_ids.append(obj_id)
#                 except AssocClientCompany.DoesNotExist:
#                     print(f"AssocClientCompany with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new AssocClientCompany for client {instance.pk}")
#                 obj, created = AssocClientCompany.objects.update_or_create(
#                     ref_client=instance,
#                     ref_company_id=comp.get("ref_company_id"),
#                     defaults=comp
#                 )
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Frequent Flyers ---
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for ff in frequent_flyers_data:
#             print("here we are printing the frequent flyer obj : ", ff)
#             obj_id = ff.pop("id", None)
#             print("here we are printing the frequent flyer obj id : ", obj_id)
#             if is_empty(ff):
#                 continue
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             ref_airline = ff.pop("ref_airline", None)
#             if ref_airline is None:
#                 ff["ref_airline_id"] = None
#             else:
#                 if isinstance(ref_airline, dict):
#                     ff["ref_airline_id"] = ref_airline.get("id")
#                 elif isinstance(ref_airline, Airlines):
#                     ff["ref_airline_id"] = ref_airline.id
#                 else:
#                     try:
#                         ff["ref_airline_id"] = int(ref_airline)
#                     except (ValueError, TypeError):
#                         ff["ref_airline_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientFrequentFlyer id={obj_id} for client {instance.pk}")
#                     ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                     keep_ids.append(obj_id)
#                 except ClientFrequentFlyer.DoesNotExist:
#                     print(f"ClientFrequentFlyer with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientFrequentFlyer for client {instance.pk}")
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(
#                     ref_client=instance,
#                     ref_airline_id=ff.get("ref_airline_id"),
#                     defaults=ff
#                 )
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Family Members ---
#         family_members_data = validated_data.pop("family_members", [])
#         keep_ids = []
#         for fam in family_members_data:
#             print("here we are printing the family member obj : ", fam)
#             obj_id = fam.pop("id", None)
#             print("here we are printing the family member obj id : ", obj_id)
#             if is_empty(fam):
#                 continue
#             fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#             fam["salutation"] = self.clean_str(fam.get("salutation"))
#             fam["firstName"] = self.clean_str(fam.get("firstName"))
#             fam["middleName"] = self.clean_str(fam.get("middleName"))
#             fam["lastName"] = self.clean_str(fam.get("lastName"))
#             fam["relation"] = self.clean_str(fam.get("relation"))
#             fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#             fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#             fam["email"] = self.clean_str(fam.get("email"))
#             fam["gender"] = self.clean_str(fam.get("gender"))
#             fam["occupation"] = self.clean_str(fam.get("occupation"))
#             fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#             fam["panNo"] = self.clean_str(fam.get("panNo"))
#             fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#             fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#             fam["dob"] = self.clean_date(fam.get("dob"))
#             fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#             for fk_field in ["residential_country", "residential_state", "residential_city"]:
#                 fk_value = fam.get(fk_field)
#                 if fk_value:
#                     model_class = {
#                         "residential_country": Countries,
#                         "residential_state": State,
#                         "residential_city": Cities
#                     }[fk_field]
#                     if isinstance(fk_value, dict):
#                         fam[f"{fk_field}_id"] = fk_value.get("id")
#                     elif isinstance(fk_value, model_class):
#                         fam[f"{fk_field}_id"] = fk_value.id
#                     else:
#                         try:
#                             fam[f"{fk_field}_id"] = int(fk_value)
#                         except (ValueError, TypeError):
#                             fam[f"{fk_field}_id"] = None
#                 else:
#                     fam[f"{fk_field}_id"] = None
#                 fam.pop(fk_field, None)

#             # Handle family member passports
#             fam_passports = fam.pop("fam_passport", [])
#             fam_passport_ids = []
#             for pd in fam_passports:
#                 print("here we are printing the fam passport obj : ", pd)
#                 pd_id = pd.pop("id", None)
#                 print("here we are printing the fam passport obj id : ", pd_id)
#                 if is_empty(pd):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 if obj_id:
#                     try:
#                         family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#                         if pd_id:
#                             try:
#                                 print(f"Updating ClientPassport id={pd_id} for family member {family_client.client_id}")
#                                 ClientPassport.objects.filter(id=pd_id, ref_client=family_client).update(**pd)
#                                 fam_passport_ids.append(pd_id)
#                             except ClientPassport.DoesNotExist:
#                                 print(f"ClientPassport with id {pd_id} not found for family member {family_client.client_id}")
#                         else:
#                             print(f"Creating new ClientPassport for family member {family_client.client_id}")
#                             obj, created = ClientPassport.objects.update_or_create(
#                                 ref_client=family_client,
#                                 passport_no=pd.get("passport_no"),
#                                 defaults=pd
#                             )
#                             fam_passport_ids.append(obj.id)
#                     except Client.DoesNotExist:
#                         print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#                         continue
#                 else:
#                     print(f"Skipping family member passport creation due to missing family member id")
#                     continue
#             if obj_id:
#                 try:
#                     family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#                     ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=fam_passport_ids).delete()
#                 except Client.DoesNotExist:
#                     pass

#             if obj_id:
#                 try:
#                     print(f"Updating Family Member client_id={obj_id} for client {instance.client_id}")
#                     Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam)
#                     keep_ids.append(obj_id)
#                 except Client.DoesNotExist:
#                     print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#             else:
#                 print(f"Creating new Family Member for client {instance.client_id}")
#                 fam["ref_client"] = instance
#                 fam["client_type"] = "Family Member"
#                 fam["client_status"] = 1
#                 obj = Client.objects.create(**fam)
#                 keep_ids.append(obj.client_id)
#         Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()

#         # --- Relations with Others ---
#         relations_data = validated_data.pop("relationsWithOthers", [])
#         keep_ids = []
#         for rel in relations_data:
#             print("here we are printing the relation obj : ", rel)
#             obj_id = rel.pop("id", None)
#             print("here we are printing the relation obj id : ", obj_id)
#             if is_empty(rel):
#                 continue
#             rel["relation"] = self.clean_str(rel.get("relation"))
#             rel["crossRelation"] = self.clean_str(rel.get("crossRelation"))
#             from_index = rel.pop("fromIndex", None)
#             to_index = rel.pop("toIndex", None)
#             if from_index is None or to_index is None:
#                 continue
#             try:
#                 from_client = Client.objects.get(id=from_index)
#                 to_client = Client.objects.get(id=to_index)
#                 rel["from_client_id"] = from_client.id
#                 rel["to_client_id"] = to_client.id
#                 if obj_id:
#                     try:
#                         print(f"Updating ClientRelation id={obj_id} for client {instance.pk}")
#                         ClientRelation.objects.filter(id=obj_id).update(**rel)
#                         keep_ids.append(obj_id)
#                     except ClientRelation.DoesNotExist:
#                         print(f"ClientRelation with id {obj_id} not found")
#                 else:
#                     print(f"Creating new ClientRelation for client {instance.pk}")
#                     obj, created = ClientRelation.objects.update_or_create(
#                         from_client_id=from_client.id,
#                         to_client_id=to_client.id,
#                         defaults=rel
#                     )
#                     keep_ids.append(obj.id)
#             except Client.DoesNotExist:
#                 print(f"Client not found for fromIndex={from_index} or toIndex={to_index}")
#                 continue
#         ClientRelation.objects.filter(from_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
        
#         def unwrap(value):
#             # Single-item list to scalar, blank string to None
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # --- Pop related data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # --- Pop FKs first ---
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         # Normalize country_code
#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         # finally assign back to validated_data so it saves properly
#         validated_data["country_code"] = country_code_instance

#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

                
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # --- Create main client ---

#         # --- Assign FK fields after creation ---
#         # Use normalized instances, not raw values
#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = (
#                 airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#             )
#         if country:
#             client.residential_country = (
#                 country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#             )
#         if state:
#             client.residential_state = (
#                 state if isinstance(state, State) else self.safe_fk(state, State)
#             )
#         if city:
#             client.residential_city = (
#                 city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#             )
#         client.save()

#         # --- Related: Passports ---
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"]:
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # --- Related: Visas ---
#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             # Normalize ref_visa_country
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value

#             # Only save if at least one meaningful field is present
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # --- Related: Travel Insurance ---
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"]:
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # --- Other Documents ---
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)     


#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             # flyer_data["ref_airline_id"] = airline_instance.id
#             # flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
            
#             # print("RAW ff_no:", flyer_data.get("ff_no"))
#             # flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             # print("CLEANED ff_no:", flyer_data["ff_no"])


#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # --- Family Members ---
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)
        
#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())
#             # print("family member:", family_client.client_id)

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])  # only passports for this family member
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))

#                 # Look inside request.FILES
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no and f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             # --- Relation with previous family member ---
#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         # --- Extra Relations (relationsWithOthers) processed once ---
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#         return client
#     # Helper method (add inside serializer)
#     def ensure_list(self, value):
#         """
#         Ensure the given value is always a list of dicts.
#         Handles cases where DRF/multipart wraps in extra list.
#         """
#         if isinstance(value, dict):
#             return [value]
#         if isinstance(value, list):
#             # flatten nested lists (e.g. [[{...}]] -> [{...}])
#             flat = []
#             for v in value:
#                 if isinstance(v, list):
#                     flat.extend(v)
#                 elif v:
#                     flat.append(v)
#             return flat
#         return []

#     # ---------------- Representation Override ----------------
#     def to_representation(self, instance):
#         data = super().to_representation(instance)

#         if hasattr(instance, "client_passport"):
#             data["client_passport"] = ClientPassportSerializer(
#                 instance.client_passport.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_visa"):
#             data["client_visa"] = ClientVisaSerializer(
#                 instance.client_visa.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "travel_insurance"):
#             data["travel_insurance"] = ClientTravelInsuranceSerializer(
#                 instance.travel_insurance.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_companies"):
#             data["client_companies"] = AssocClientCompanySerializer(
#                 instance.client_companies.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_documents"):
#             data["client_documents"] = OtherDocumentSerializer(
#                 instance.client_documents.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_frequent_flyers"):
#             data["client_frequent_flyers"] = FrequentflyerSerializer(
#                 instance.frequent_flyers.all(), many=True, context=self.context
#             ).data
                
#         data["familyMembers"] = self.get_familyMembers(instance)

#         return data

#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data


# last used
# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_state = serializers.PrimaryKeyRelatedField(queryset=State.objects.all(), required=False, allow_null=True)
#     residential_city = serializers.PrimaryKeyRelatedField(queryset=Cities.objects.all(), required=False, allow_null=True)
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(queryset=Airlines.objects.all(), required=False, allow_null=True)

#     # --- Nested serializers ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
#             "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_str(self, value):
#         print(">>>>>>> clean_str Details <<<<<<<<<<", value)
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def clean_row(self, row, file_map=None):
#         print(">>>>>>> clean_row Details <<<<<<<<<<", row)
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         # Preserve id as an integer
#         if "id" in cleaned:
#             try:
#                 cleaned["id"] = int(cleaned["id"]) if cleaned["id"] else None
#             except (ValueError, TypeError):
#                 cleaned["id"] = None

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def safe_fk(self, model_class, value):
#         print(">>>>>>> safe_fk Details <<<<<<<<<<", value)
#         if not value:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             value_int = int(value)
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         print(">>>>>>> normalize_preferred_contact_method Details<<<<<<<<<<", value)
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         def unwrap_scalars(data, skip_keys):
#             result = {}
#             for k, v in data.items():
#                 if k in skip_keys:
#                     result[k] = v
#                 elif isinstance(v, list) and len(v) == 1:
#                     result[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     result[k] = None
#                 else:
#                     result[k] = v
#             return result

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     # Preserve id as an integer
#                     if "id" in item:
#                         try:
#                             item["id"] = int(item["id"]) if item["id"] else None
#                         except (ValueError, TypeError):
#                             item["id"] = None
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # --- Nested: Client Passport ---
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if "id" in p:
#                     try:
#                         p["id"] = int(p["id"]) if p["id"] else None
#                     except (ValueError, TypeError):
#                         p["id"] = None
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue

#         for i, p in enumerate(expanded_passports):
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                 p["passport_file"] = None

#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         # --- Nested: Client Visa ---
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 if "id" in v:
#                     try:
#                         v["id"] = int(v["id"]) if v["id"] else None
#                     except (ValueError, TypeError):
#                         v["id"] = None
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None
#                 if "passport_size_photograph" in v and v["passport_size_photograph"] in ["", "null", None]:
#                     v["passport_size_photograph"] = None
#                 if "visa_type" in v:
#                     v["visa_type"] = self.clean_str(v.get("visa_type"))

#         # --- Nested: Travel Insurance ---
#         # Inside the validate method of FullClientSerializer
#         # --- Nested: Travel Insurance ---
#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "id" in t:
#                     try:
#                         t["id"] = int(t["id"]) if t["id"] else None
#                     except (ValueError, TypeError):
#                         t["id"] = None
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))
#                 if "insurance_document" in t and t["insurance_document"] in ["", "null", None]:
#                     t["insurance_document"] = None
                    
#         # # --- Nested: Client Documents ---
#         # for i, d in enumerate(data.get("client_documents", [])):
#         #     if isinstance(d, dict):
#         #         if "id" in d:
#         #             try:
#         #                 d["id"] = int(d["id"]) if d["id"] else None
#         #             except (ValueError, TypeError):
#         #                 d["id"] = None
#         #         file_key = f"client_documents[{i}][other_document]"
#         #         if self.context.get("request") and file_key in self.context["request"].FILES:
#         #             d["other_document"] = self.context["request"].FILES[file_key]
#         #         elif "other_document" in d and d["other_document"] in ["", "null", None]:
#         #             d["other_document"] = None
#         #         if "other_document_name" in d:
#         #             d["other_document_name"] = self.clean_str(d.get("other_document_name"))
        
        

#         # --- Nested: Client Companies ---
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "id" in c:
#                     try:
#                         c["id"] = int(c["id"]) if c["id"] else None
#                     except (ValueError, TypeError):
#                         c["id"] = None
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None
#                 if "ref_company" in c and c["ref_company"] in ["", "null", None]:
#                     c["ref_company"] = None

#         # --- Nested: Frequent Flyers ---
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "id" in f:
#                     try:
#                         f["id"] = int(f["id"]) if f["id"] else None
#                     except (ValueError, TypeError):
#                         f["id"] = None
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # --- Nested: Family Members ---
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "id" in fam:
#                     try:
#                         fam["id"] = int(fam["id"]) if fam["id"] else None
#                     except (ValueError, TypeError):
#                         fam["id"] = None
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "salutation" in fam:
#                     fam["salutation"] = self.clean_str(fam.get("salutation"))
#                 if "firstName" in fam:
#                     fam["firstName"] = self.clean_str(fam.get("firstName"))
#                 if "middleName" in fam:
#                     fam["middleName"] = self.clean_str(fam.get("middleName"))
#                 if "lastName" in fam:
#                     fam["lastName"] = self.clean_str(fam.get("lastName"))
#                 if "relation" in fam:
#                     fam["relation"] = self.clean_str(fam.get("relation"))
#                 if "crossrelation" in fam:
#                     fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#                 if "contactNo" in fam:
#                     fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#                 if "email" in fam:
#                     fam["email"] = self.clean_str(fam.get("email"))
#                 if "gender" in fam:
#                     fam["gender"] = self.clean_str(fam.get("gender"))
#                 if "occupation" in fam:
#                     fam["occupation"] = self.clean_str(fam.get("occupation"))
#                 if "aadhaarNo" in fam:
#                     fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#                 if "panNo" in fam:
#                     fam["panNo"] = self.clean_str(fam.get("panNo"))
#                 if "residential_address" in fam:
#                     fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#                 if "residential_pincode" in fam:
#                     fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for p in fam.get("fam_passport", []):
#                         if isinstance(p, dict):
#                             if "id" in p:
#                                 try:
#                                     p["id"] = int(p["id"]) if p["id"] else None
#                                 except (ValueError, TypeError):
#                                     p["id"] = None
#                             if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                                 expanded_fam_passports.extend(expand_passports(p))
#                             else:
#                                 expanded_fam_passports.append(p)
#                         else:
#                             continue

#                     for pi, p in enumerate(expanded_fam_passports):
#                         if isinstance(p.get("passport_no"), list):
#                             p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                         if isinstance(p.get("passport_expiry_date"), list):
#                             p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         if isinstance(p.get("passport_file"), list):
#                             p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                         elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                             p["passport_file"] = None

#                         if "passport_no" in p:
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         if "passport_expiry_date" in p:
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                     fam["fam_passport"] = expanded_fam_passports

#         # --- Nested: Relations with Others ---
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict):
#                 if "id" in r:
#                     try:
#                         r["id"] = int(r["id"]) if r["id"] else None
#                     except (ValueError, TypeError):
#                         r["id"] = None
#                 if "relation_with_other_client_code" in r:
#                     r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))
#                 if "relation" in r:
#                     r["relation"] = self.clean_str(r.get("relation"))
#                 if "crossRelation" in r:
#                     r["crossRelation"] = self.clean_str(r.get("crossRelation"))
#                 if "fromIndex" in r and r["fromIndex"] in ["", "null", None]:
#                     r["fromIndex"] = None
#                 if "toIndex" in r and r["toIndex"] in ["", "null", None]:
#                     r["toIndex"] = None
                    
#         # Validate client_documents using OtherDocumentSerializer
#         documents = data.get("client_documents", [])
#         validated_documents = []
#         for i, doc in enumerate(documents):
#             if isinstance(doc, dict):
#                 serializer = OtherDocumentSerializer(data=doc, context={**self.context, "index": i})
#                 if not serializer.is_valid():
#                     raise serializers.ValidationError({f"client_documents[{i}]": serializer.errors})
#                 validated_documents.append(serializer.validated_data)
#         data["client_documents"] = validated_documents

#         return data

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # Define FK fields and their corresponding models
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         # Handle FK fields
#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 model_class = fk_models.get(fk_field)
#                 if fk_value is None:
#                     setattr(instance, fk_field, None)
#                 else:
#                     if isinstance(fk_value, model_class):
#                         setattr(instance, fk_field, fk_value)
#                     else:
#                         try:
#                             id_val = int(fk_value) if not isinstance(fk_value, dict) else int(fk_value.get("id"))
#                             fk_instance = model_class.objects.get(id=id_val)
#                             setattr(instance, fk_field, fk_instance)
#                         except (ValueError, TypeError, model_class.DoesNotExist):
#                             setattr(instance, fk_field, None)

#         # Normalize fields
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # Handle uploaded files
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if file_val is None or file_val in ["", "null"]:
#                     setattr(instance, field, None)

#         # Helper to skip empty dicts
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # Update main client fields
#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#             "family_members", "fam_passport", "relationsWithOthers"
#         }

#         for attr, value in validated_data.items():
#             if attr in skip_keys or value is None:
#                 continue
#             setattr(instance, attr, value)

#         instance.save()

#         # --- Client Passport ---
#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             print("here we are printing the client passport obj : ", pd)
#             obj_id = pd.pop("id", None)
#             print("here we are printing the client passport obj id : ", obj_id)
#             if is_empty(pd):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             if obj_id:
#                 try:
#                     print(f"Updating ClientPassport id={obj_id} for client {instance.pk}")
#                     ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                     keep_ids.append(obj_id)
#                 except ClientPassport.DoesNotExist:
#                     print(f"ClientPassport with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientPassport for client {instance.pk}")
#                 obj, created = ClientPassport.objects.update_or_create(
#                     ref_client=instance,
#                     passport_no=pd.get("passport_no"),
#                     defaults=pd
#                 )
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Visa ---
#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for vd in visas_data:
#             print("here we are printing the client visa obj : ", vd)
#             obj_id = vd.pop("id", None)
#             print("here we are printing the client visa obj id : ", obj_id)
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             vd["visa_type"] = self.clean_str(vd.get("visa_type"))
#             if "ref_visa_country" in vd:
#                 country_val = vd.pop("ref_visa_country", None)
#                 if country_val is None or country_val in ["", "null"]:
#                     vd["ref_visa_country_id"] = None
#                 else:
#                     if isinstance(country_val, dict):
#                         vd["ref_visa_country_id"] = country_val.get("id")
#                     elif isinstance(country_val, Countries):
#                         vd["ref_visa_country_id"] = country_val.id
#                     else:
#                         try:
#                             vd["ref_visa_country_id"] = int(country_val)
#                         except (ValueError, TypeError):
#                             vd["ref_visa_country_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientVisa id={obj_id} for client {instance.pk}")
#                     ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                     keep_ids.append(obj_id)
#                 except ClientVisa.DoesNotExist:
#                     print(f"ClientVisa with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientVisa for client {instance.pk}")
#                 obj, created = ClientVisa.objects.update_or_create(
#                     ref_client=instance,
#                     visa_type=vd.get("visa_type"),
#                     ref_visa_country_id=vd.get("ref_visa_country_id"),
#                     defaults=vd
#                 )
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Travel Insurance ---
#         insurances_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for ins in insurances_data:
#             print("here we are printing the travel insurance obj : ", ins)
#             obj_id = ins.pop("id", None)
#             print("here we are printing the travel insurance obj id : ", obj_id)
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if "insurance_document" in ins and ins["insurance_document"] in ["", "null", None]:
#                 ins["insurance_document"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientTravelInsurance id={obj_id} for client {instance.pk}")
#                     ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                     keep_ids.append(obj_id)
#                 except ClientTravelInsurance.DoesNotExist:
#                     print(f"ClientTravelInsurance with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientTravelInsurance for client {instance.pk}")
#                 lookup = {
#                     "ref_client": instance,
#                     "insurance_from_date": ins.get("insurance_from_date"),
#                     "insurance_to_date": ins.get("insurance_to_date")
#                 }
#                 obj, created = ClientTravelInsurance.objects.update_or_create(
#                     **lookup,
#                     defaults=ins
#                 )
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # # --- Client Documents ---
#         # docs_data = validated_data.pop("client_documents", [])
#         # keep_ids = []
#         # for doc in docs_data:
#         #     print("here we are printing the client document obj : ", doc)
#         #     obj_id = doc.pop("id", None)
#         #     print("here we are printing the client document obj id : ", obj_id)
#         #     if is_empty(doc):
#         #         continue
#         #     doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#         #     if obj_id:
#         #         try:
#         #             print(f"Updating ClientDocument id={obj_id} for client {instance.pk}")
#         #             ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#         #             keep_ids.append(obj_id)
#         #         except ClientDocument.DoesNotExist:
#         #             print(f"ClientDocument with id {obj_id} not found for client {instance.pk}")
#         #     else:
#         #         print(f"Creating new ClientDocument for client {instance.pk}")
#         #         obj, created = ClientDocument.objects.update_or_create(
#         #             ref_client=instance,
#         #             other_document_name=doc.get("other_document_name"),
#         #             defaults=doc
#         #         )
#         #         keep_ids.append(obj.id)
#         # ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Handle client_documents
#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for i, doc in enumerate(docs_data):
#             print(f"Processing client document {i}: {doc}")
#             obj_id = doc.get("id")  # Do not pop id
#             if is_empty(doc):
#                 print(f"Skipping empty client document data at index {i}")
#                 continue
#             doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#             file_key = f"client_documents[{i}][other_document]"
#             data_key = f"client_documents[{i}][other_document]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 doc["other_document"] = self.context["request"].FILES[file_key]
#                 print(f"Other document found for index {i}: {file_key}")
#             elif self.context.get("request") and data_key in self.context["request"].data and self.context["request"].data[data_key] in ["", "null", None]:
#                 doc["other_document"] = None
#                 print(f"Clearing other_document for index {i} (explicit null in request.data)")
#             if obj_id:
#                 try:
#                     obj = ClientDocument.objects.get(id=obj_id, ref_client=instance)
#                     for key, value in doc.items():
#                         if key != "id" and key != "ref_client":
#                             setattr(obj, key, value)
#                     obj.save()
#                     keep_ids.append(obj_id)
#                     print(f"Updated client document {obj_id}: {doc}")
#                 except ClientDocument.DoesNotExist:
#                     print(f"ClientDocument {obj_id} does not exist, creating new")
#                     if doc.get("other_document_name") or doc.get("other_document"):
#                         obj = ClientDocument.objects.create(ref_client=instance, **doc)
#                         keep_ids.append(obj.id)
#                         print(f"Created client document {obj.id}: {doc}")
#                 except ClientDocument.MultipleObjectsReturned:
#                     print(f"Multiple client document records found for id {obj_id} and ref_client {instance.client_id}")
#                     raise serializers.ValidationError(f"Multiple client document records found for id {obj_id}")
#             else:
#                 if doc.get("other_document_name") or doc.get("other_document"):
#                     try:
#                         obj, created = ClientDocument.objects.update_or_create(
#                             ref_client=instance,
#                             other_document_name=doc.get("other_document_name"),
#                             defaults=doc
#                         )
#                         keep_ids.append(obj.id)
#                         print(f"Created/Updated client document {obj.id}: {doc}")
#                     except ClientDocument.MultipleObjectsReturned:
#                         print(f"Multiple client document records found for ref_client {instance.client_id}, "
#                                      f"other_document_name {doc.get('other_document_name')}")
#                         raise serializers.ValidationError(
#                             f"Duplicate client document records for client {instance.client_id} with "
#                             f"other_document_name {doc.get('other_document_name')}"
#                         )
#         if docs_data:  # Only delete if new data is provided
#             deleted_docs = ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids)
#             for doc in deleted_docs:
#                 if doc.other_document:
#                     doc.other_document.delete(save=False)  # Clean up file from storage
#             deleted_docs.delete()
#             print(f"Deleted client documents not in {keep_ids}")
            
#         # --- Client Companies ---
#         companies_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for comp in companies_data:
#             print("here we are printing the client company obj : ", comp)
#             obj_id = comp.pop("id", None)
#             print("here we are printing the client company obj id : ", obj_id)
#             if is_empty(comp):
#                 continue
#             comp["designation"] = self.clean_str(comp.get("designation"))
#             if "ref_company" in comp:
#                 ref_company = comp.pop("ref_company", None)
#                 if ref_company is None or ref_company in ["", "null"]:
#                     comp["ref_company_id"] = None
#                 else:
#                     if isinstance(ref_company, dict):
#                         comp["ref_company_id"] = ref_company.get("id")
#                     elif isinstance(ref_company, Company):
#                         comp["ref_company_id"] = ref_company.id
#                     else:
#                         try:
#                             comp["ref_company_id"] = int(ref_company)
#                         except (ValueError, TypeError):
#                             comp["ref_company_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating AssocClientCompany id={obj_id} for client {instance.pk}")
#                     AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                     keep_ids.append(obj_id)
#                 except AssocClientCompany.DoesNotExist:
#                     print(f"AssocClientCompany with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new AssocClientCompany for client {instance.pk}")
#                 obj, created = AssocClientCompany.objects.update_or_create(
#                     ref_client=instance,
#                     ref_company_id=comp.get("ref_company_id"),
#                     defaults=comp
#                 )
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Frequent Flyers ---
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for ff in frequent_flyers_data:
#             print("here we are printing the frequent flyer obj : ", ff)
#             obj_id = ff.pop("id", None)
#             print("here we are printing the frequent flyer obj id : ", obj_id)
#             if is_empty(ff):
#                 continue
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             if "ref_airline" in ff:
#                 ref_airline = ff.pop("ref_airline", None)
#                 if ref_airline is None or ref_airline in ["", "null"]:
#                     ff["ref_airline_id"] = None
#                 else:
#                     if isinstance(ref_airline, dict):
#                         ff["ref_airline_id"] = ref_airline.get("id")
#                     elif isinstance(ref_airline, Airlines):
#                         ff["ref_airline_id"] = ref_airline.id
#                     else:
#                         try:
#                             ff["ref_airline_id"] = int(ref_airline)
#                         except (ValueError, TypeError):
#                             ff["ref_airline_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientFrequentFlyer id={obj_id} for client {instance.pk}")
#                     ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                     keep_ids.append(obj_id)
#                 except ClientFrequentFlyer.DoesNotExist:
#                     print(f"ClientFrequentFlyer with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientFrequentFlyer for client {instance.pk}")
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(
#                     ref_client=instance,
#                     ref_airline_id=ff.get("ref_airline_id"),
#                     defaults=ff
#                 )
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Family Members ---
#         # family_members_data = validated_data.pop("family_members", [])
#         # keep_ids = []
#         # for fam in family_members_data:
#         #     print("here we are printing the family member obj : ", fam)
#         #     obj_id = fam.pop("id", None)
#         #     print("here we are printing the family member obj id : ", obj_id)
#         #     if is_empty(fam):
#         #         continue
#         #     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#         #     fam["salutation"] = self.clean_str(fam.get("salutation"))
#         #     fam["firstName"] = self.clean_str(fam.get("firstName"))
#         #     fam["middleName"] = self.clean_str(fam.get("middleName"))
#         #     fam["lastName"] = self.clean_str(fam.get("lastName"))
#         #     fam["relation"] = self.clean_str(fam.get("relation"))
#         #     fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#         #     fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#         #     fam["email"] = self.clean_str(fam.get("email"))
#         #     fam["gender"] = self.clean_str(fam.get("gender"))
#         #     fam["occupation"] = self.clean_str(fam.get("occupation"))
#         #     fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#         #     fam["panNo"] = self.clean_str(fam.get("panNo"))
#         #     fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#         #     fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#         #     fam["dob"] = self.clean_date(fam.get("dob"))
#         #     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#         #     for fk_field in ["residential_country", "residential_state", "residential_city"]:
#         #         if fk_field in fam:
#         #             fk_value = fam.pop(fk_field)
#         #             model_class = {
#         #                 "residential_country": Countries,
#         #                 "residential_state": State,
#         #                 "residential_city": Cities
#         #             }[fk_field]
#         #             if fk_value is None:
#         #                 fam[f"{fk_field}_id"] = None
#         #             else:
#         #                 if isinstance(fk_value, dict):
#         #                     fam[f"{fk_field}_id"] = fk_value.get("id")
#         #                 elif isinstance(fk_value, model_class):
#         #                     fam[f"{fk_field}_id"] = fk_value.id
#         #                 else:
#         #                     try:
#         #                         fam[f"{fk_field}_id"] = int(fk_value)
#         #                     except (ValueError, TypeError):
#         #                         fam[f"{fk_field}_id"] = None

#         #     # Handle family member passports
#         #     fam_passports = fam.pop("fam_passport", [])
#         #     fam_passport_ids = []
#         #     for pd in fam_passports:
#         #         print("here we are printing the fam passport obj : ", pd)
#         #         pd_id = pd.pop("id", None)
#         #         print("here we are printing the fam passport obj id : ", pd_id)
#         #         if is_empty(pd):
#         #             continue
#         #         pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#         #         pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#         #         if obj_id:
#         #             try:
#         #                 family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#         #                 if pd_id:
#         #                     try:
#         #                         print(f"Updating ClientPassport id={pd_id} for family member {family_client.client_id}")
#         #                         ClientPassport.objects.filter(id=pd_id, ref_client=family_client).update(**pd)
#         #                         fam_passport_ids.append(pd_id)
#         #                     except ClientPassport.DoesNotExist:
#         #                         print(f"ClientPassport with id {pd_id} not found for family member {family_client.client_id}")
#         #                 else:
#         #                     print(f"Creating new ClientPassport for family member {family_client.client_id}")
#         #                     obj, created = ClientPassport.objects.update_or_create(
#         #                         ref_client=family_client,
#         #                         passport_no=pd.get("passport_no"),
#         #                         defaults=pd
#         #                     )
#         #                     fam_passport_ids.append(obj.id)
#         #             except Client.DoesNotExist:
#         #                 print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#         #                 continue
#         #         else:
#         #             print(f"Skipping family member passport creation due to missing family member id")
#         #             continue
#         #     if obj_id:
#         #         try:
#         #             family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#         #             ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=fam_passport_ids).delete()
#         #         except Client.DoesNotExist:
#         #             pass

#         #     if obj_id:
#         #         try:
#         #             print(f"Updating Family Member client_id={obj_id} for client {instance.client_id}")
#         #             Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam)
#         #             keep_ids.append(obj_id)
#         #         except Client.DoesNotExist:
#         #             print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#         #     else:
#         #         print(f"Creating new Family Member for client {instance.client_id}")
#         #         fam["ref_client"] = instance
#         #         fam["client_type"] = "Family Member"
#         #         fam["client_status"] = 1
#         #         obj = Client.objects.create(**fam)
#         #         keep_ids.append(obj.client_id)
#         # Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()

#         # # --- Relations with Others ---
#         # relations_data = validated_data.pop("relationsWithOthers", [])
#         # keep_ids = []
#         # for rel in relations_data:
#         #     print("here we are printing the relation obj : ", rel)
#         #     obj_id = rel.pop("id", None)
#         #     print("here we are printing the relation obj id : ", obj_id)
#         #     if is_empty(rel):
#         #         continue
#         #     rel["relation"] = self.clean_str(rel.get("relation"))
#         #     rel["crossRelation"] = self.clean_str(rel.get("crossRelation"))
#         #     from_index = rel.pop("fromIndex", None)
#         #     to_index = rel.pop("toIndex", None)
#         #     if from_index is None or to_index is None:
#         #         continue
#         #     try:
#         #         from_client = Client.objects.get(id=from_index)
#         #         to_client = Client.objects.get(id=to_index)
#         #         rel["from_client_id"] = from_client.id
#         #         rel["to_client_id"] = to_client.id
#         #         if obj_id:
#         #             try:
#         #                 print(f"Updating ClientRelation id={obj_id} for client {instance.pk}")
#         #                 ClientRelation.objects.filter(id=obj_id).update(**rel)
#         #                 keep_ids.append(obj_id)
#         #             except ClientRelation.DoesNotExist:
#         #                 print(f"ClientRelation with id {obj_id} not found")
#         #         else:
#         #             print(f"Creating new ClientRelation for client {instance.pk}")
#         #             obj, created = ClientRelation.objects.update_or_create(
#         #                 from_client_id=from_client.id,
#         #                 to_client_id=to_client.id,
#         #                 defaults=rel
#         #             )
#         #             keep_ids.append(obj.id)
#         #     except Client.DoesNotExist:
#         #         print(f"Client not found for fromIndex={from_index} or toIndex={to_index}")
#         #         continue
#         # ClientRelation.objects.filter(from_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
        
#         def unwrap(value):
#             # Single-item list to scalar, blank string to None
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # --- Pop related data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # --- Pop FKs first ---
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         # Normalize country_code
#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         # finally assign back to validated_data so it saves properly
#         validated_data["country_code"] = country_code_instance

#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

                
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # --- Create main client ---

#         # --- Assign FK fields after creation ---
#         # Use normalized instances, not raw values
#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = (
#                 airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#             )
#         if country:
#             client.residential_country = (
#                 country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#             )
#         if state:
#             client.residential_state = (
#                 state if isinstance(state, State) else self.safe_fk(state, State)
#             )
#         if city:
#             client.residential_city = (
#                 city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#             )
#         client.save()

#         # --- Related: Passports ---
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"]:
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # --- Related: Visas ---
#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             # Normalize ref_visa_country
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value

#             # Only save if at least one meaningful field is present
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # --- Related: Travel Insurance ---
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"]:
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # --- Other Documents ---
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)     


#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             # flyer_data["ref_airline_id"] = airline_instance.id
#             # flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
            
#             # print("RAW ff_no:", flyer_data.get("ff_no"))
#             # flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             # print("CLEANED ff_no:", flyer_data["ff_no"])


#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # --- Family Members ---
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)
        
#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())
#             # print("family member:", family_client.client_id)

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])  # only passports for this family member
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))

#                 # Look inside request.FILES
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no and f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             # --- Relation with previous family member ---
#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         # --- Extra Relations (relationsWithOthers) processed once ---
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#         return client
#     # Helper method (add inside serializer)
#     def ensure_list(self, value):
#         """
#         Ensure the given value is always a list of dicts.
#         Handles cases where DRF/multipart wraps in extra list.
#         """
#         if isinstance(value, dict):
#             return [value]
#         if isinstance(value, list):
#             # flatten nested lists (e.g. [[{...}]] -> [{...}])
#             flat = []
#             for v in value:
#                 if isinstance(v, list):
#                     flat.extend(v)
#                 elif v:
#                     flat.append(v)
#             return flat
#         return []

#     # ---------------- Representation Override ----------------
#     def to_representation(self, instance):
#         data = super().to_representation(instance)

#         if hasattr(instance, "client_passport"):
#             data["client_passport"] = ClientPassportSerializer(
#                 instance.client_passport.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_visa"):
#             data["client_visa"] = ClientVisaSerializer(
#                 instance.client_visa.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "travel_insurance"):
#             data["travel_insurance"] = ClientTravelInsuranceSerializer(
#                 instance.travel_insurance.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_companies"):
#             data["client_companies"] = AssocClientCompanySerializer(
#                 instance.client_companies.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_documents"):
#             data["client_documents"] = OtherDocumentSerializer(
#                 instance.client_documents.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_frequent_flyers"):
#             data["client_frequent_flyers"] = FrequentflyerSerializer(
#                 instance.frequent_flyers.all(), many=True, context=self.context
#             ).data
                
#         data["familyMembers"] = self.get_familyMembers(instance)

#         return data

#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_state = serializers.PrimaryKeyRelatedField(queryset=State.objects.all(), required=False, allow_null=True)
#     residential_city = serializers.PrimaryKeyRelatedField(queryset=Cities.objects.all(), required=False, allow_null=True)
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(queryset=Airlines.objects.all(), required=False, allow_null=True)

#     # --- Nested serializers ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
#             "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_str(self, value):
#         print(">>>>>>> clean_str Details <<<<<<<<<<", value)
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def clean_row(self, row, file_map=None):
#         print(">>>>>>> clean_row Details <<<<<<<<<<", row)
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", "null", None, [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         # Preserve id as an integer
#         if "id" in cleaned:
#             try:
#                 cleaned["id"] = int(cleaned["id"]) if cleaned["id"] else None
#             except (ValueError, TypeError):
#                 cleaned["id"] = None

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def safe_fk(self, model_class, value):
#         print(">>>>>>> safe_fk Details <<<<<<<<<<", value)
#         if not value:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             value_int = int(value)
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         if value in ["", "null", None, [], [""]]:
#             return None  # Changed to allow None
#         normalized = []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = v.get("id") or v.get("value") or v.get("label") if isinstance(v, dict) else str(v)
#             if key and key not in ["", "null"]:
#                 normalized.append(key.lower().strip())
#         return normalized or None # Return None if empty after processing

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         def unwrap_scalars(data, skip_keys):
#             result = {}
#             for k, v in data.items():
#                 if k in skip_keys:
#                     result[k] = v
#                 elif isinstance(v, list) and len(v) == 1:
#                     result[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     result[k] = None
#                 else:
#                     result[k] = v
#             return result

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     # Preserve id as an integer
#                     if "id" in item:
#                         try:
#                             item["id"] = int(item["id"]) if item["id"] else None
#                         except (ValueError, TypeError):
#                             item["id"] = None
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # --- Nested: Client Passport ---
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if "id" in p:
#                     try:
#                         p["id"] = int(p["id"]) if p["id"] else None
#                     except (ValueError, TypeError):
#                         p["id"] = None
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue

#         for i, p in enumerate(expanded_passports):
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                 p["passport_file"] = None

#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         # --- Nested: Client Visa ---
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 if "id" in v:
#                     try:
#                         v["id"] = int(v["id"]) if v["id"] else None
#                     except (ValueError, TypeError):
#                         v["id"] = None
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None
#                 if "passport_size_photograph" in v and v["passport_size_photograph"] in ["", "null", None]:
#                     v["passport_size_photograph"] = None
#                 if "visa_type" in v:
#                     v["visa_type"] = self.clean_str(v.get("visa_type"))

#         # --- Nested: Travel Insurance ---
#         # Inside the validate method of FullClientSerializer
#         # --- Nested: Travel Insurance ---
#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "id" in t:
#                     try:
#                         t["id"] = int(t["id"]) if t["id"] else None
#                     except (ValueError, TypeError):
#                         t["id"] = None
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))
#                 if "insurance_document" in t and t["insurance_document"] in ["", "null", None]:
#                     t["insurance_document"] = None
                    
#         # # --- Nested: Client Documents ---
#         # for i, d in enumerate(data.get("client_documents", [])):
#         #     if isinstance(d, dict):
#         #         if "id" in d:
#         #             try:
#         #                 d["id"] = int(d["id"]) if d["id"] else None
#         #             except (ValueError, TypeError):
#         #                 d["id"] = None
#         #         file_key = f"client_documents[{i}][other_document]"
#         #         if self.context.get("request") and file_key in self.context["request"].FILES:
#         #             d["other_document"] = self.context["request"].FILES[file_key]
#         #         elif "other_document" in d and d["other_document"] in ["", "null", None]:
#         #             d["other_document"] = None
#         #         if "other_document_name" in d:
#         #             d["other_document_name"] = self.clean_str(d.get("other_document_name"))
        
        

#         # --- Nested: Client Companies ---
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "id" in c:
#                     try:
#                         c["id"] = int(c["id"]) if c["id"] else None
#                     except (ValueError, TypeError):
#                         c["id"] = None
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None
#                 if "ref_company" in c and c["ref_company"] in ["", "null", None]:
#                     c["ref_company"] = None

#         # --- Nested: Frequent Flyers ---
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "id" in f:
#                     try:
#                         f["id"] = int(f["id"]) if f["id"] else None
#                     except (ValueError, TypeError):
#                         f["id"] = None
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # --- Nested: Family Members ---
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "id" in fam:
#                     try:
#                         fam["id"] = int(fam["id"]) if fam["id"] else None
#                     except (ValueError, TypeError):
#                         fam["id"] = None
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "salutation" in fam:
#                     fam["salutation"] = self.clean_str(fam.get("salutation"))
#                 if "firstName" in fam:
#                     fam["firstName"] = self.clean_str(fam.get("firstName"))
#                 if "middleName" in fam:
#                     fam["middleName"] = self.clean_str(fam.get("middleName"))
#                 if "lastName" in fam:
#                     fam["lastName"] = self.clean_str(fam.get("lastName"))
#                 if "relation" in fam:
#                     fam["relation"] = self.clean_str(fam.get("relation"))
#                 if "crossrelation" in fam:
#                     fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#                 if "contactNo" in fam:
#                     fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#                 if "email" in fam:
#                     fam["email"] = self.clean_str(fam.get("email"))
#                 if "gender" in fam:
#                     fam["gender"] = self.clean_str(fam.get("gender"))
#                 if "occupation" in fam:
#                     fam["occupation"] = self.clean_str(fam.get("occupation"))
#                 if "aadhaarNo" in fam:
#                     fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#                 if "panNo" in fam:
#                     fam["panNo"] = self.clean_str(fam.get("panNo"))
#                 if "residential_address" in fam:
#                     fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#                 if "residential_pincode" in fam:
#                     fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for p in fam.get("fam_passport", []):
#                         if isinstance(p, dict):
#                             if "id" in p:
#                                 try:
#                                     p["id"] = int(p["id"]) if p["id"] else None
#                                 except (ValueError, TypeError):
#                                     p["id"] = None
#                             if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                                 expanded_fam_passports.extend(expand_passports(p))
#                             else:
#                                 expanded_fam_passports.append(p)
#                         else:
#                             continue

#                     for pi, p in enumerate(expanded_fam_passports):
#                         if isinstance(p.get("passport_no"), list):
#                             p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                         if isinstance(p.get("passport_expiry_date"), list):
#                             p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         if isinstance(p.get("passport_file"), list):
#                             p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                         elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                             p["passport_file"] = None

#                         if "passport_no" in p:
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         if "passport_expiry_date" in p:
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                     fam["fam_passport"] = expanded_fam_passports

#         # --- Nested: Relations with Others ---
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict):
#                 if "id" in r:
#                     try:
#                         r["id"] = int(r["id"]) if r["id"] else None
#                     except (ValueError, TypeError):
#                         r["id"] = None
#                 if "relation_with_other_client_code" in r:
#                     r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))
#                 if "relation" in r:
#                     r["relation"] = self.clean_str(r.get("relation"))
#                 if "crossRelation" in r:
#                     r["crossRelation"] = self.clean_str(r.get("crossRelation"))
#                 if "fromIndex" in r and r["fromIndex"] in ["", "null", None]:
#                     r["fromIndex"] = None
#                 if "toIndex" in r and r["toIndex"] in ["", "null", None]:
#                     r["toIndex"] = None
                    
#         # Validate client_documents using OtherDocumentSerializer
#         documents = data.get("client_documents", [])
#         validated_documents = []
#         for i, doc in enumerate(documents):
#             if isinstance(doc, dict):
#                 serializer = OtherDocumentSerializer(data=doc, context={**self.context, "index": i})
#                 if not serializer.is_valid():
#                     raise serializers.ValidationError({f"client_documents[{i}]": serializer.errors})
#                 validated_documents.append(serializer.validated_data)
#         data["client_documents"] = validated_documents

#         return data

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # Define FK fields and their corresponding models
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         # Handle FK fields
#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 model_class = fk_models.get(fk_field)
#                 if fk_value is None:
#                     setattr(instance, fk_field, None)
#                 else:
#                     if isinstance(fk_value, model_class):
#                         setattr(instance, fk_field, fk_value)
#                     else:
#                         try:
#                             id_val = int(fk_value) if not isinstance(fk_value, dict) else int(fk_value.get("id"))
#                             fk_instance = model_class.objects.get(id=id_val)
#                             setattr(instance, fk_field, fk_instance)
#                         except (ValueError, TypeError, model_class.DoesNotExist):
#                             setattr(instance, fk_field, None)

#         # Normalize fields
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # Handle uploaded files
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if file_val is None or file_val in ["", "null"]:
#                     setattr(instance, field, None)

#         # Helper to skip empty dicts
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # Update main client fields
#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#             "family_members", "fam_passport", "relationsWithOthers"
#         }

#         for attr, value in validated_data.items():
#             if attr in skip_keys or value is None:
#                 continue
#             setattr(instance, attr, value)

#         instance.save()

#         # --- Client Passport ---
#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             print("here we are printing the client passport obj : ", pd)
#             obj_id = pd.pop("id", None)
#             print("here we are printing the client passport obj id : ", obj_id)
#             if is_empty(pd):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             if obj_id:
#                 try:
#                     print(f"Updating ClientPassport id={obj_id} for client {instance.pk}")
#                     ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                     keep_ids.append(obj_id)
#                 except ClientPassport.DoesNotExist:
#                     print(f"ClientPassport with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientPassport for client {instance.pk}")
#                 obj, created = ClientPassport.objects.update_or_create(
#                     ref_client=instance,
#                     passport_no=pd.get("passport_no"),
#                     defaults=pd
#                 )
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Visa ---
#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for vd in visas_data:
#             print("here we are printing the client visa obj : ", vd)
#             obj_id = vd.pop("id", None)
#             print("here we are printing the client visa obj id : ", obj_id)
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             vd["visa_type"] = self.clean_str(vd.get("visa_type"))
#             if "ref_visa_country" in vd:
#                 country_val = vd.pop("ref_visa_country", None)
#                 if country_val is None or country_val in ["", "null"]:
#                     vd["ref_visa_country_id"] = None
#                 else:
#                     if isinstance(country_val, dict):
#                         vd["ref_visa_country_id"] = country_val.get("id")
#                     elif isinstance(country_val, Countries):
#                         vd["ref_visa_country_id"] = country_val.id
#                     else:
#                         try:
#                             vd["ref_visa_country_id"] = int(country_val)
#                         except (ValueError, TypeError):
#                             vd["ref_visa_country_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientVisa id={obj_id} for client {instance.pk}")
#                     ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                     keep_ids.append(obj_id)
#                 except ClientVisa.DoesNotExist:
#                     print(f"ClientVisa with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientVisa for client {instance.pk}")
#                 obj, created = ClientVisa.objects.update_or_create(
#                     ref_client=instance,
#                     visa_type=vd.get("visa_type"),
#                     ref_visa_country_id=vd.get("ref_visa_country_id"),
#                     defaults=vd
#                 )
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Travel Insurance ---
#         insurances_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for ins in insurances_data:
#             print("here we are printing the travel insurance obj : ", ins)
#             obj_id = ins.pop("id", None)
#             print("here we are printing the travel insurance obj id : ", obj_id)
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if "insurance_document" in ins and ins["insurance_document"] in ["", "null", None]:
#                 ins["insurance_document"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientTravelInsurance id={obj_id} for client {instance.pk}")
#                     ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                     keep_ids.append(obj_id)
#                 except ClientTravelInsurance.DoesNotExist:
#                     print(f"ClientTravelInsurance with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientTravelInsurance for client {instance.pk}")
#                 lookup = {
#                     "ref_client": instance,
#                     "insurance_from_date": ins.get("insurance_from_date"),
#                     "insurance_to_date": ins.get("insurance_to_date")
#                 }
#                 obj, created = ClientTravelInsurance.objects.update_or_create(
#                     **lookup,
#                     defaults=ins
#                 )
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # # --- Client Documents ---
#         # docs_data = validated_data.pop("client_documents", [])
#         # keep_ids = []
#         # for doc in docs_data:
#         #     print("here we are printing the client document obj : ", doc)
#         #     obj_id = doc.pop("id", None)
#         #     print("here we are printing the client document obj id : ", obj_id)
#         #     if is_empty(doc):
#         #         continue
#         #     doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#         #     if obj_id:
#         #         try:
#         #             print(f"Updating ClientDocument id={obj_id} for client {instance.pk}")
#         #             ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#         #             keep_ids.append(obj_id)
#         #         except ClientDocument.DoesNotExist:
#         #             print(f"ClientDocument with id {obj_id} not found for client {instance.pk}")
#         #     else:
#         #         print(f"Creating new ClientDocument for client {instance.pk}")
#         #         obj, created = ClientDocument.objects.update_or_create(
#         #             ref_client=instance,
#         #             other_document_name=doc.get("other_document_name"),
#         #             defaults=doc
#         #         )
#         #         keep_ids.append(obj.id)
#         # ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Handle client_documents
#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for i, doc in enumerate(docs_data):
#             print(f"Processing client document {i}: {doc}")
#             obj_id = doc.get("id")  # Do not pop id
#             if is_empty(doc):
#                 print(f"Skipping empty client document data at index {i}")
#                 continue
#             doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#             file_key = f"client_documents[{i}][other_document]"
#             data_key = f"client_documents[{i}][other_document]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 doc["other_document"] = self.context["request"].FILES[file_key]
#                 print(f"Other document found for index {i}: {file_key}")
#             elif self.context.get("request") and data_key in self.context["request"].data and self.context["request"].data[data_key] in ["", "null", None]:
#                 doc["other_document"] = None
#                 print(f"Clearing other_document for index {i} (explicit null in request.data)")
#             if obj_id:
#                 try:
#                     obj = ClientDocument.objects.get(id=obj_id, ref_client=instance)
#                     for key, value in doc.items():
#                         if key != "id" and key != "ref_client":
#                             setattr(obj, key, value)
#                     obj.save()
#                     keep_ids.append(obj_id)
#                     print(f"Updated client document {obj_id}: {doc}")
#                 except ClientDocument.DoesNotExist:
#                     print(f"ClientDocument {obj_id} does not exist, creating new")
#                     if doc.get("other_document_name") or doc.get("other_document"):
#                         obj = ClientDocument.objects.create(ref_client=instance, **doc)
#                         keep_ids.append(obj.id)
#                         print(f"Created client document {obj.id}: {doc}")
#                 except ClientDocument.MultipleObjectsReturned:
#                     print(f"Multiple client document records found for id {obj_id} and ref_client {instance.client_id}")
#                     raise serializers.ValidationError(f"Multiple client document records found for id {obj_id}")
#             else:
#                 if doc.get("other_document_name") or doc.get("other_document"):
#                     try:
#                         obj, created = ClientDocument.objects.update_or_create(
#                             ref_client=instance,
#                             other_document_name=doc.get("other_document_name"),
#                             defaults=doc
#                         )
#                         keep_ids.append(obj.id)
#                         print(f"Created/Updated client document {obj.id}: {doc}")
#                     except ClientDocument.MultipleObjectsReturned:
#                         print(f"Multiple client document records found for ref_client {instance.client_id}, "
#                                      f"other_document_name {doc.get('other_document_name')}")
#                         raise serializers.ValidationError(
#                             f"Duplicate client document records for client {instance.client_id} with "
#                             f"other_document_name {doc.get('other_document_name')}"
#                         )
#         if docs_data:  # Only delete if new data is provided
#             deleted_docs = ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids)
#             for doc in deleted_docs:
#                 if doc.other_document:
#                     doc.other_document.delete(save=False)  # Clean up file from storage
#             deleted_docs.delete()
#             print(f"Deleted client documents not in {keep_ids}")
            
#         # --- Client Companies ---
#         companies_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for comp in companies_data:
#             print("here we are printing the client company obj : ", comp)
#             obj_id = comp.pop("id", None)
#             print("here we are printing the client company obj id : ", obj_id)
#             if is_empty(comp):
#                 continue
#             comp["designation"] = self.clean_str(comp.get("designation"))
#             if "ref_company" in comp:
#                 ref_company = comp.pop("ref_company", None)
#                 if ref_company is None or ref_company in ["", "null"]:
#                     comp["ref_company_id"] = None
#                 else:
#                     if isinstance(ref_company, dict):
#                         comp["ref_company_id"] = ref_company.get("id")
#                     elif isinstance(ref_company, Company):
#                         comp["ref_company_id"] = ref_company.id
#                     else:
#                         try:
#                             comp["ref_company_id"] = int(ref_company)
#                         except (ValueError, TypeError):
#                             comp["ref_company_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating AssocClientCompany id={obj_id} for client {instance.pk}")
#                     AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                     keep_ids.append(obj_id)
#                 except AssocClientCompany.DoesNotExist:
#                     print(f"AssocClientCompany with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new AssocClientCompany for client {instance.pk}")
#                 obj, created = AssocClientCompany.objects.update_or_create(
#                     ref_client=instance,
#                     ref_company_id=comp.get("ref_company_id"),
#                     defaults=comp
#                 )
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Client Frequent Flyers ---
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for ff in frequent_flyers_data:
#             print("here we are printing the frequent flyer obj : ", ff)
#             obj_id = ff.pop("id", None)
#             print("here we are printing the frequent flyer obj id : ", obj_id)
#             if is_empty(ff):
#                 continue
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             if "ref_airline" in ff:
#                 ref_airline = ff.pop("ref_airline", None)
#                 if ref_airline is None or ref_airline in ["", "null"]:
#                     ff["ref_airline_id"] = None
#                 else:
#                     if isinstance(ref_airline, dict):
#                         ff["ref_airline_id"] = ref_airline.get("id")
#                     elif isinstance(ref_airline, Airlines):
#                         ff["ref_airline_id"] = ref_airline.id
#                     else:
#                         try:
#                             ff["ref_airline_id"] = int(ref_airline)
#                         except (ValueError, TypeError):
#                             ff["ref_airline_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientFrequentFlyer id={obj_id} for client {instance.pk}")
#                     ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                     keep_ids.append(obj_id)
#                 except ClientFrequentFlyer.DoesNotExist:
#                     print(f"ClientFrequentFlyer with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientFrequentFlyer for client {instance.pk}")
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(
#                     ref_client=instance,
#                     ref_airline_id=ff.get("ref_airline_id"),
#                     defaults=ff
#                 )
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Family Members ---
#         # family_members_data = validated_data.pop("family_members", [])
#         # keep_ids = []
#         # for fam in family_members_data:
#         #     print("here we are printing the family member obj : ", fam)
#         #     obj_id = fam.pop("id", None)
#         #     print("here we are printing the family member obj id : ", obj_id)
#         #     if is_empty(fam):
#         #         continue
#         #     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#         #     fam["salutation"] = self.clean_str(fam.get("salutation"))
#         #     fam["firstName"] = self.clean_str(fam.get("firstName"))
#         #     fam["middleName"] = self.clean_str(fam.get("middleName"))
#         #     fam["lastName"] = self.clean_str(fam.get("lastName"))
#         #     fam["relation"] = self.clean_str(fam.get("relation"))
#         #     fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#         #     fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#         #     fam["email"] = self.clean_str(fam.get("email"))
#         #     fam["gender"] = self.clean_str(fam.get("gender"))
#         #     fam["occupation"] = self.clean_str(fam.get("occupation"))
#         #     fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#         #     fam["panNo"] = self.clean_str(fam.get("panNo"))
#         #     fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#         #     fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#         #     fam["dob"] = self.clean_date(fam.get("dob"))
#         #     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#         #     for fk_field in ["residential_country", "residential_state", "residential_city"]:
#         #         if fk_field in fam:
#         #             fk_value = fam.pop(fk_field)
#         #             model_class = {
#         #                 "residential_country": Countries,
#         #                 "residential_state": State,
#         #                 "residential_city": Cities
#         #             }[fk_field]
#         #             if fk_value is None:
#         #                 fam[f"{fk_field}_id"] = None
#         #             else:
#         #                 if isinstance(fk_value, dict):
#         #                     fam[f"{fk_field}_id"] = fk_value.get("id")
#         #                 elif isinstance(fk_value, model_class):
#         #                     fam[f"{fk_field}_id"] = fk_value.id
#         #                 else:
#         #                     try:
#         #                         fam[f"{fk_field}_id"] = int(fk_value)
#         #                     except (ValueError, TypeError):
#         #                         fam[f"{fk_field}_id"] = None

#         #     # Handle family member passports
#         #     fam_passports = fam.pop("fam_passport", [])
#         #     fam_passport_ids = []
#         #     for pd in fam_passports:
#         #         print("here we are printing the fam passport obj : ", pd)
#         #         pd_id = pd.pop("id", None)
#         #         print("here we are printing the fam passport obj id : ", pd_id)
#         #         if is_empty(pd):
#         #             continue
#         #         pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#         #         pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#         #         if obj_id:
#         #             try:
#         #                 family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#         #                 if pd_id:
#         #                     try:
#         #                         print(f"Updating ClientPassport id={pd_id} for family member {family_client.client_id}")
#         #                         ClientPassport.objects.filter(id=pd_id, ref_client=family_client).update(**pd)
#         #                         fam_passport_ids.append(pd_id)
#         #                     except ClientPassport.DoesNotExist:
#         #                         print(f"ClientPassport with id {pd_id} not found for family member {family_client.client_id}")
#         #                 else:
#         #                     print(f"Creating new ClientPassport for family member {family_client.client_id}")
#         #                     obj, created = ClientPassport.objects.update_or_create(
#         #                         ref_client=family_client,
#         #                         passport_no=pd.get("passport_no"),
#         #                         defaults=pd
#         #                     )
#         #                     fam_passport_ids.append(obj.id)
#         #             except Client.DoesNotExist:
#         #                 print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#         #                 continue
#         #         else:
#         #             print(f"Skipping family member passport creation due to missing family member id")
#         #             continue
#         #     if obj_id:
#         #         try:
#         #             family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#         #             ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=fam_passport_ids).delete()
#         #         except Client.DoesNotExist:
#         #             pass

#         #     if obj_id:
#         #         try:
#         #             print(f"Updating Family Member client_id={obj_id} for client {instance.client_id}")
#         #             Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam)
#         #             keep_ids.append(obj_id)
#         #         except Client.DoesNotExist:
#         #             print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#         #     else:
#         #         print(f"Creating new Family Member for client {instance.client_id}")
#         #         fam["ref_client"] = instance
#         #         fam["client_type"] = "Family Member"
#         #         fam["client_status"] = 1
#         #         obj = Client.objects.create(**fam)
#         #         keep_ids.append(obj.client_id)
#         # Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()

#         # # --- Relations with Others ---
#         # relations_data = validated_data.pop("relationsWithOthers", [])
#         # keep_ids = []
#         # for rel in relations_data:
#         #     print("here we are printing the relation obj : ", rel)
#         #     obj_id = rel.pop("id", None)
#         #     print("here we are printing the relation obj id : ", obj_id)
#         #     if is_empty(rel):
#         #         continue
#         #     rel["relation"] = self.clean_str(rel.get("relation"))
#         #     rel["crossRelation"] = self.clean_str(rel.get("crossRelation"))
#         #     from_index = rel.pop("fromIndex", None)
#         #     to_index = rel.pop("toIndex", None)
#         #     if from_index is None or to_index is None:
#         #         continue
#         #     try:
#         #         from_client = Client.objects.get(id=from_index)
#         #         to_client = Client.objects.get(id=to_index)
#         #         rel["from_client_id"] = from_client.id
#         #         rel["to_client_id"] = to_client.id
#         #         if obj_id:
#         #             try:
#         #                 print(f"Updating ClientRelation id={obj_id} for client {instance.pk}")
#         #                 ClientRelation.objects.filter(id=obj_id).update(**rel)
#         #                 keep_ids.append(obj_id)
#         #             except ClientRelation.DoesNotExist:
#         #                 print(f"ClientRelation with id {obj_id} not found")
#         #         else:
#         #             print(f"Creating new ClientRelation for client {instance.pk}")
#         #             obj, created = ClientRelation.objects.update_or_create(
#         #                 from_client_id=from_client.id,
#         #                 to_client_id=to_client.id,
#         #                 defaults=rel
#         #             )
#         #             keep_ids.append(obj.id)
#         #     except Client.DoesNotExist:
#         #         print(f"Client not found for fromIndex={from_index} or toIndex={to_index}")
#         #         continue
#         # ClientRelation.objects.filter(from_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
        
#         def unwrap(value):
#             # Single-item list to scalar, blank string to None
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # --- Pop related data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # --- Pop FKs first ---
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         # Normalize country_code
#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         # finally assign back to validated_data so it saves properly
#         validated_data["country_code"] = country_code_instance

#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

                
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # --- Create main client ---

#         # --- Assign FK fields after creation ---
#         # Use normalized instances, not raw values
#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = (
#                 airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#             )
#         if country:
#             client.residential_country = (
#                 country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#             )
#         if state:
#             client.residential_state = (
#                 state if isinstance(state, State) else self.safe_fk(state, State)
#             )
#         if city:
#             client.residential_city = (
#                 city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#             )
#         client.save()

#         # --- Related: Passports ---
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"]:
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # --- Related: Visas ---
#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             # Normalize ref_visa_country
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value

#             # Only save if at least one meaningful field is present
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # --- Related: Travel Insurance ---
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"]:
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # --- Other Documents ---
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)     


#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             # flyer_data["ref_airline_id"] = airline_instance.id
#             # flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
            
#             # print("RAW ff_no:", flyer_data.get("ff_no"))
#             # flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             # print("CLEANED ff_no:", flyer_data["ff_no"])


#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # --- Family Members ---
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)
        
#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())
#             # print("family member:", family_client.client_id)

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])  # only passports for this family member
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))

#                 # Look inside request.FILES
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no and f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             # --- Relation with previous family member ---
#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         # --- Extra Relations (relationsWithOthers) processed once ---
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#         return client
#     # Helper method (add inside serializer)
#     def ensure_list(self, value):
#         """
#         Ensure the given value is always a list of dicts.
#         Handles cases where DRF/multipart wraps in extra list.
#         """
#         if isinstance(value, dict):
#             return [value]
#         if isinstance(value, list):
#             # flatten nested lists (e.g. [[{...}]] -> [{...}])
#             flat = []
#             for v in value:
#                 if isinstance(v, list):
#                     flat.extend(v)
#                 elif v:
#                     flat.append(v)
#             return flat
#         return []

#     # ---------------- Representation Override ----------------
#     def to_representation(self, instance):
#         data = super().to_representation(instance)

#         if hasattr(instance, "client_passport"):
#             data["client_passport"] = ClientPassportSerializer(
#                 instance.client_passport.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_visa"):
#             data["client_visa"] = ClientVisaSerializer(
#                 instance.client_visa.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "travel_insurance"):
#             data["travel_insurance"] = ClientTravelInsuranceSerializer(
#                 instance.travel_insurance.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_companies"):
#             data["client_companies"] = AssocClientCompanySerializer(
#                 instance.client_companies.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_documents"):
#             data["client_documents"] = OtherDocumentSerializer(
#                 instance.client_documents.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_frequent_flyers"):
#             data["client_frequent_flyers"] = FrequentflyerSerializer(
#                 instance.frequent_flyers.all(), many=True, context=self.context
#             ).data
                
#         data["familyMembers"] = self.get_familyMembers(instance)

#         return data

#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Fields ---
#     country_code = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_state = serializers.PrimaryKeyRelatedField(queryset=State.objects.all(), required=False, allow_null=True)
#     residential_city = serializers.PrimaryKeyRelatedField(queryset=Cities.objects.all(), required=False, allow_null=True)
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(queryset=Airlines.objects.all(), required=False, allow_null=True)
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
#             "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # --- Helper Methods ---
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_str(self, value):
#         if value in ["", "null", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def clean_row(self, row, file_map=None):
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", "null", None, [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     cleaned[k] = parsed[0] if isinstance(parsed, list) and len(parsed) == 1 else parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v
#         if "id" in cleaned:
#             cleaned["id"] = int(cleaned["id"]) if cleaned["id"] else None
#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             request_data = self.context["request"].data
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]
#                 elif req_field in request_data and request_data[req_field] in ["", "null", None]:
#                     cleaned[field] = None
#                 else:
#                     cleaned.pop(field, None)  # Exclude to preserve existing file
#         return cleaned

#     def safe_fk(self, model_class, value):
#         if not value:
#             return None
#         try:
#             value_int = int(value) if not isinstance(value, dict) else int(value.get("id"))
#             return value_int if model_class.objects.filter(id=value_int).exists() else None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         if value in ["", "null", None, [], [""]]:
#             return None  # Changed to allow None
#         normalized = []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = v.get("id") or v.get("value") or v.get("label") if isinstance(v, dict) else str(v)
#             if key and key not in ["", "null"]:
#                 normalized.append(key.lower().strip())
#         return normalized or None  # Return None if empty after processing

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 return value if isinstance(value, list) else [value]
#         return []

#     # --- Validate ---
#     def validate(self, data):
#         def unwrap_scalars(data, skip_keys):
#             result = {}
#             for k, v in data.items():
#                 if k in skip_keys:
#                     result[k] = v
#                 elif isinstance(v, list) and len(v) == 1:
#                     result[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     result[k] = None
#                 else:
#                     result[k] = v
#             return result
#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])
#         def normalize_nested_dict(d):
#             file_fields = ["passport_file", "other_document", "passport_size_photograph", "insurance_document", "aadhaarCard", "panCard"]
#             result = {}
#             for k, v in d.items():
#                 if k in file_fields and v not in [None] and not isinstance(v, InMemoryUploadedFile):
#                     continue  # Skip invalid file field values
#                 result[k] = v
#             return result
#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]
#         for field in nested_fields:
#             val = data.get(field, []) or []
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             data[field] = [
#                 normalize_nested_dict(item) if isinstance(item, dict) else None
#                 for item in flat_list if item is not None
#             ]
#         # Validate client_code
#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})
#         # Clean dates
#         data["dob"] = self.clean_date(data.get("dob"))
#         data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))
#         # Handle is_prepayment explicitly
#         if "is_prepayment" in data:
#             data["is_prepayment"] = None if data["is_prepayment"] in ["", "null", None, [""]] else bool(data["is_prepayment"])
#         # Client Passport
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 p["id"] = int(p["id"]) if p.get("id") else None
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(self.expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#         for i, p in enumerate(expanded_passports):
#             p["passport_no"] = self.clean_str(p.get("passport_no"))
#             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))
#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#             elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
#                 p["passport_file"] = None
#             else:
#                 p.pop("passport_file", None)
#         data["client_passport"] = expanded_passports
#         # Client Visa
#         for i, v in enumerate(data.get("client_visa", [])):
#             if isinstance(v, dict):
#                 v["id"] = int(v["id"]) if v.get("id") else None
#                 v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 v["visa_type"] = self.clean_str(v.get("visa_type"))
#                 v["ref_visa_country"] = None if v.get("ref_visa_country") in ["", "null", None] else v.get("ref_visa_country")
#                 file_key = f"client_visa[{i}][passport_size_photograph]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     v["passport_size_photograph"] = self.context["request"].FILES[file_key]
#                 elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
#                     v["passport_size_photograph"] = None
#                 else:
#                     v.pop("passport_size_photograph", None)
#                 # Validate using ClientVisaSerializer
#                 serializer = ClientVisaSerializer(data=v, context=self.context, partial=True)
#                 if not serializer.is_valid():
#                     raise serializers.ValidationError({f"client_visa[{i}]": serializer.errors})
#                 v.update(serializer.validated_data)
#         # Travel Insurance
#         for i, t in enumerate(data.get("travel_insurance", [])):
#             if isinstance(t, dict):
#                 t["id"] = int(t["id"]) if t.get("id") else None
#                 t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))
#                 file_key = f"travel_insurance[{i}][insurance_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     t["insurance_document"] = self.context["request"].FILES[file_key]
#                 elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
#                     t["insurance_document"] = None
#                 else:
#                     t.pop("insurance_document", None)
#                 serializer = ClientTravelInsuranceSerializer(data=t, context=self.context, partial=True)
#                 if not serializer.is_valid():
#                     raise serializers.ValidationError({f"travel_insurance[{i}]": serializer.errors})
#                 t.update(serializer.validated_data)
#         # Client Documents
#         validated_documents = []
#         for i, doc in enumerate(data.get("client_documents", [])):
#             if isinstance(doc, dict):
#                 doc["id"] = int(doc["id"]) if doc.get("id") else None
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 file_key = f"client_documents[{i}][other_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     doc["other_document"] = self.context["request"].FILES[file_key]
#                 elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
#                     doc["other_document"] = None
#                 else:
#                     doc.pop("other_document", None)
#                 serializer = OtherDocumentSerializer(data=doc, context={**self.context, "index": i}, partial=True)
#                 if not serializer.is_valid():
#                     raise serializers.ValidationError({f"client_documents[{i}]": serializer.errors})
#                 validated_documents.append(serializer.validated_data)
#         data["client_documents"] = validated_documents
#         # Client Companies
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 c["id"] = int(c["id"]) if c.get("id") else None
#                 c["designation"] = self.clean_str(c.get("designation"))
#                 c["ref_company"] = None if c.get("ref_company") in ["", "null", None] else c.get("ref_company")
#                 c["primary_company"] = None if c.get("primary_company") in ["", "null"] else c.get("primary_company")
#         # Frequent Flyers
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 f["id"] = int(f["id"]) if f.get("id") else None
#                 f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 f["ref_airline"] = None if f.get("ref_airline") in ["", "null", None] else f.get("ref_airline")
#         # Family Members
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 fam["id"] = int(fam["id"]) if fam.get("id") else None
#                 fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 fam["salutation"] = self.clean_str(fam.get("salutation"))
#                 fam["firstName"] = self.clean_str(fam.get("firstName"))
#                 fam["middleName"] = self.clean_str(fam.get("middleName"))
#                 fam["lastName"] = self.clean_str(fam.get("lastName"))
#                 fam["relation"] = self.clean_str(fam.get("relation"))
#                 fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#                 fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#                 fam["email"] = self.clean_str(fam.get("email"))
#                 fam["gender"] = self.clean_str(fam.get("gender"))
#                 fam["occupation"] = self.clean_str(fam.get("occupation"))
#                 fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#                 fam["panNo"] = self.clean_str(fam.get("panNo"))
#                 fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#                 fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#                 fam["dob"] = self.clean_date(fam.get("dob"))
#                 fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 for fk in ["residential_country", "residential_state", "residential_city"]:
#                     fam[fk] = None if fam.get(fk) in ["", "null", None] else fam.get(fk)
#                 for pi, p in enumerate(fam.get("fam_passport", [])):
#                     if isinstance(p, dict):
#                         p["id"] = int(p["id"]) if p.get("id") else None
#                         p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))
#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                         elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
#                             p["passport_file"] = None
#                         else:
#                             p.pop("passport_file", None)
#                 fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#                 fam_pan_key = f"family_members[{fam_index}][panCard]"
#                 if self.context.get("request"):
#                     if fam_aadhaar_key in self.context["request"].FILES:
#                         fam["aadhaar_card_file"] = self.context["request"].FILES[fam_aadhaar_key]
#                     elif fam_aadhaar_key in self.context["request"].data and self.context["request"].data[fam_aadhaar_key] in ["", "null", None]:
#                         fam["aadhaar_card_file"] = None
#                     else:
#                         fam.pop("aadhaarCard", None)
#                         fam.pop("aadhaar_card_file", None)
#                     if fam_pan_key in self.context["request"].FILES:
#                         fam["pan_card_file"] = self.context["request"].FILES[fam_pan_key]
#                     elif fam_pan_key in self.context["request"].data and self.context["request"].data[fam_pan_key] in ["", "null", None]:
#                         fam["pan_card_file"] = None
#                     else:
#                         fam.pop("panCard", None)
#                         fam.pop("pan_card_file", None)
#         # Relations with Others
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict):
#                 r["id"] = int(r["id"]) if r.get("id") else None
#                 r["relation"] = self.clean_str(r.get("relation"))
#                 r["crossRelation"] = self.clean_str(r.get("crossRelation"))
#                 r["fromIndex"] = None if r.get("fromIndex") in ["", "null", None] else r.get("fromIndex")
#                 r["toIndex"] = None if r.get("toIndex") in ["", "null", None] else r.get("toIndex")
#         return data

#     # --- Update ---
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }
#         # Handle FK fields
#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 if fk_value is None:
#                     setattr(instance, fk_field, None)
#                 else:
#                     model_class = fk_models[fk_field]
#                     if isinstance(fk_value, model_class):
#                         setattr(instance, fk_field, fk_value)
#                     else:
#                         try:
#                             id_val = int(fk_value.get("id") if isinstance(fk_value, dict) else fk_value)
#                             setattr(instance, fk_field, model_class.objects.get(id=id_val))
#                         except (ValueError, TypeError, model_class.DoesNotExist):
#                             setattr(instance, fk_field, None)
#         # Normalize fields
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#             validated_data.get("preferred_contact_method")
#         )
#         # Handle file fields
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         request_data = self.context.get("request").data if self.context.get("request") else {}
#         file_fields = ["aadhaar_card_file", "pan_card_file"]
#         for field in file_fields:
#             if field in request_files:
#                 setattr(instance, field, request_files[field])
#             elif field in request_data and request_data[field] in ["", "null", None]:
#                 setattr(instance, field, None)
#             validated_data.pop(field, None)
#         # Update main client fields
#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#             "family_members", "fam_passport", "relationsWithOthers"
#         }
#         for attr, value in validated_data.items():
#             if attr not in skip_keys:
#                 setattr(instance, attr, value)
#         instance.save()
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])
#         # Client Passport
#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             obj_id = pd.pop("id", None)
#             if is_empty(pd):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             if "passport_file" not in pd or pd["passport_file"] is None:
#                 pd.pop("passport_file", None)
#             if obj_id:
#                 try:
#                     ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                     keep_ids.append(obj_id)
#                 except ClientPassport.DoesNotExist:
#                     pass
#             else:
#                 obj, created = ClientPassport.objects.update_or_create(
#                     ref_client=instance, passport_no=pd.get("passport_no"), defaults=pd
#                 )
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         # --- Client Visa ---
#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for vd in visas_data:
#             print("here we are printing the client visa obj : ", vd)
#             obj_id = vd.pop("id", None)
#             print("here we are printing the client visa obj id : ", obj_id)
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             vd["visa_type"] = self.clean_str(vd.get("visa_type"))
#             if "ref_visa_country" in vd:
#                 country_val = vd.pop("ref_visa_country", None)
#                 if country_val is None or country_val in ["", "null"]:
#                     vd["ref_visa_country_id"] = None
#                 else:
#                     if isinstance(country_val, dict):
#                         vd["ref_visa_country_id"] = country_val.get("id")
#                     elif isinstance(country_val, Countries):
#                         vd["ref_visa_country_id"] = country_val.id
#                     else:
#                         try:
#                             vd["ref_visa_country_id"] = int(country_val)
#                         except (ValueError, TypeError):
#                             vd["ref_visa_country_id"] = None
#             if obj_id:
#                 try:
#                     print(f"Updating ClientVisa id={obj_id} for client {instance.pk}")
#                     ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                     keep_ids.append(obj_id)
#                 except ClientVisa.DoesNotExist:
#                     print(f"ClientVisa with id {obj_id} not found for client {instance.pk}")
#             else:
#                 print(f"Creating new ClientVisa for client {instance.pk}")
#                 obj, created = ClientVisa.objects.update_or_create(
#                     ref_client=instance,
#                     visa_type=vd.get("visa_type"),
#                     ref_visa_country_id=vd.get("ref_visa_country_id"),
#                     defaults=vd
#                 )
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         # Travel Insurance
#         insurances_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for ins in insurances_data:
#             obj_id = ins.pop("id", None)
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if "insurance_document" not in ins or ins["insurance_document"] is None:
#                 ins.pop("insurance_document", None)
#             if obj_id:
#                 try:
#                     ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                     keep_ids.append(obj_id)
#                 except ClientTravelInsurance.DoesNotExist:
#                     pass
#             else:
#                 obj, created = ClientTravelInsurance.objects.update_or_create(
#                     ref_client=instance, insurance_from_date=ins.get("insurance_from_date"), insurance_to_date=ins.get("insurance_to_date"), defaults=ins
#                 )
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         # Client Documents
#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for i, doc in enumerate(docs_data):
#             obj_id = doc.get("id")
#             if is_empty(doc):
#                 continue
#             doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#             file_key = f"client_documents[{i}][other_document]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 doc["other_document"] = self.context["request"].FILES[file_key]
#             elif self.context.get("request") and file_key in self.context["request"].data and self.context["request"].data[file_key] in ["", "null", None]:
#                 doc["other_document"] = None
#             else:
#                 doc.pop("other_document", None)
#             try:
#                 if obj_id:
#                     obj = ClientDocument.objects.get(id=obj_id, ref_client=instance)
#                     for key, value in doc.items():
#                         if key != "id" and key != "ref_client":
#                             setattr(obj, key, value)
#                     obj.save()
#                     keep_ids.append(obj_id)
#                 else:
#                     if doc.get("other_document_name") or doc.get("other_document"):
#                         obj = ClientDocument.objects.create(ref_client=instance, **doc)
#                         keep_ids.append(obj.id)
#             except ClientDocument.DoesNotExist:
#                 if doc.get("other_document_name") or doc.get("other_document"):
#                     obj = ClientDocument.objects.create(ref_client=instance, **doc)
#                     keep_ids.append(obj.id)
#             except ClientDocument.MultipleObjectsReturned:
#                 raise serializers.ValidationError(f"Multiple client document records found for id {obj_id}")
#         if docs_data:
#             deleted_docs = ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids)
#             for doc in deleted_docs:
#                 if doc.other_document:
#                     doc.other_document.delete(save=False)
#             deleted_docs.delete()
#         # Client Companies
#         companies_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for comp in companies_data:
#             obj_id = comp.pop("id", None)
#             if is_empty(comp):
#                 continue
#             comp["designation"] = self.clean_str(comp.get("designation"))
#             ref_company = comp.pop("ref_company", None)
#             comp["ref_company_id"] = None
#             if ref_company:
#                 if isinstance(ref_company, dict):
#                     comp["ref_company_id"] = ref_company.get("id")
#                 elif isinstance(ref_company, Company):
#                     comp["ref_company_id"] = ref_company.id
#                 else:
#                     try:
#                         comp["ref_company_id"] = int(ref_company)
#                     except (ValueError, TypeError):
#                         pass
#             if obj_id:
#                 try:
#                     AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                     keep_ids.append(obj_id)
#                 except AssocClientCompany.DoesNotExist:
#                     pass
#             else:
#                 obj, created = AssocClientCompany.objects.update_or_create(
#                     ref_client=instance, ref_company_id=comp.get("ref_company_id"), defaults=comp
#                 )
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         # Frequent Flyers
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for ff in frequent_flyers_data:
#             obj_id = ff.pop("id", None)
#             if is_empty(ff):
#                 continue
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             ref_airline = ff.pop("ref_airline", None)
#             ff["ref_airline_id"] = None
#             if ref_airline:
#                 if isinstance(ref_airline, dict):
#                     ff["ref_airline_id"] = ref_airline.get("id")
#                 elif isinstance(ref_airline, Airlines):
#                     ff["ref_airline_id"] = ref_airline.id
#                 else:
#                     try:
#                         ff["ref_airline_id"] = int(ref_airline)
#                     except (ValueError, TypeError):
#                         pass
#             if obj_id:
#                 try:
#                     ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                     keep_ids.append(obj_id)
#                 except ClientFrequentFlyer.DoesNotExist:
#                     pass
#             else:
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(
#                     ref_client=instance, ref_airline_id=ff.get("ref_airline_id"), defaults=ff
#                 )
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Family Members (commented out as per original)
#         # family_members_data = validated_data.pop("family_members", [])
#         # keep_ids = []
#         # for fam in family_members_data:
#         #     print("here we are printing the family member obj : ", fam)
#         #     obj_id = fam.pop("id", None)
#         #     print("here we are printing the family member obj id : ", obj_id)
#         #     if is_empty(fam):
#         #         continue
#         #     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#         #     fam["salutation"] = self.clean_str(fam.get("salutation"))
#         #     fam["firstName"] = self.clean_str(fam.get("firstName"))
#         #     fam["middleName"] = self.clean_str(fam.get("middleName"))
#         #     fam["lastName"] = self.clean_str(fam.get("lastName"))
#         #     fam["relation"] = self.clean_str(fam.get("relation"))
#         #     fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#         #     fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#         #     fam["email"] = self.clean_str(fam.get("email"))
#         #     fam["gender"] = self.clean_str(fam.get("gender"))
#         #     fam["occupation"] = self.clean_str(fam.get("occupation"))
#         #     fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#         #     fam["panNo"] = self.clean_str(fam.get("panNo"))
#         #     fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#         #     fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#         #     fam["dob"] = self.clean_date(fam.get("dob"))
#         #     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#         #     for fk_field in ["residential_country", "residential_state", "residential_city"]:
#         #         if fk_field in fam:
#         #             fk_value = fam.pop(fk_field)
#         #             model_class = {
#         #                 "residential_country": Countries,
#         #                 "residential_state": State,
#         #                 "residential_city": Cities
#         #             }[fk_field]
#         #             if fk_value is None:
#         #                 fam[f"{fk_field}_id"] = None
#         #             else:
#         #                 if isinstance(fk_value, dict):
#         #                     fam[f"{fk_field}_id"] = fk_value.get("id")
#         #                 elif isinstance(fk_value, model_class):
#         #                     fam[f"{fk_field}_id"] = fk_value.id
#         #                 else:
#         #                     try:
#         #                         fam[f"{fk_field}_id"] = int(fk_value)
#         #                     except (ValueError, TypeError):
#         #                         fam[f"{fk_field}_id"] = None
#         #     # Handle family member passports
#         #     fam_passports = fam.pop("fam_passport", [])
#         #     fam_passport_ids = []
#         #     for pd in fam_passports:
#         #         print("here we are printing the fam passport obj : ", pd)
#         #         pd_id = pd.pop("id", None)
#         #         print("here we are printing the fam passport obj id : ", pd_id)
#         #         if is_empty(pd):
#         #             continue
#         #         pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#         #         pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#         #         if obj_id:
#         #             try:
#         #                 family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#         #                 if pd_id:
#         #                     try:
#         #                         print(f"Updating ClientPassport id={pd_id} for family member {family_client.client_id}")
#         #                         ClientPassport.objects.filter(id=pd_id, ref_client=family_client).update(**pd)
#         #                         fam_passport_ids.append(pd_id)
#         #                     except ClientPassport.DoesNotExist:
#         #                         print(f"ClientPassport with id {pd_id} not found for family member {family_client.client_id}")
#         #                 else:
#         #                     print(f"Creating new ClientPassport for family member {family_client.client_id}")
#         #                     obj, created = ClientPassport.objects.update_or_create(
#         #                         ref_client=family_client,
#         #                         passport_no=pd.get("passport_no"),
#         #                         defaults=pd
#         #                     )
#         #                     fam_passport_ids.append(obj.id)
#         #             except Client.DoesNotExist:
#         #                 print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#         #                 continue
#         #         else:
#         #             print(f"Skipping family member passport creation due to missing family member id")
#         #             continue
#         #         if obj_id:
#         #             try:
#         #                 family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#         #                 ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=fam_passport_ids).delete()
#         #             except Client.DoesNotExist:
#         #                 pass
#         #     if obj_id:
#         #         try:
#         #             print(f"Updating Family Member client_id={obj_id} for client {instance.client_id}")
#         #             Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam)
#         #             keep_ids.append(obj_id)
#         #         except Client.DoesNotExist:
#         #             print(f"Family member with client_id {obj_id} not found for client {instance.client_id}")
#         #     else:
#         #         print(f"Creating new Family Member for client {instance.client_id}")
#         #         fam["ref_client"] = instance
#         #         fam["client_type"] = "Family Member"
#         #         fam["client_status"] = 1
#         #         obj = Client.objects.create(**fam)
#         #         keep_ids.append(obj.client_id)
#         # Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()

#         # Relations with Others (commented out as per original)
#         # relations_data = validated_data.pop("relationsWithOthers", [])
#         # keep_ids = []
#         # for rel in relations_data:
#         #     print("here we are printing the relation obj : ", rel)
#         #     obj_id = rel.pop("id", None)
#         #     print("here we are printing the relation obj id : ", obj_id)
#         #     if is_empty(rel):
#         #         continue
#         #     rel["relation"] = self.clean_str(rel.get("relation"))
#         #     rel["crossRelation"] = self.clean_str(rel.get("crossRelation"))
#         #     from_index = rel.pop("fromIndex", None)
#         #     to_index = rel.pop("toIndex", None)
#         #     if from_index is None or to_index is None:
#         #         continue
#         #     try:
#         #         from_client = Client.objects.get(id=from_index)
#         #         to_client = Client.objects.get(id=to_index)
#         #         rel["from_client_id"] = from_client.id
#         #         rel["to_client_id"] = to_client.id
#         #         if obj_id:
#         #             try:
#         #                 print(f"Updating ClientRelation id={obj_id} for client {instance.pk}")
#         #                 ClientRelation.objects.filter(id=obj_id).update(**rel)
#         #                 keep_ids.append(obj_id)
#         #             except ClientRelation.DoesNotExist:
#         #                 print(f"ClientRelation with id {obj_id} not found")
#         #         else:
#         #             print(f"Creating new ClientRelation for client {instance.pk}")
#         #             obj, created = ClientRelation.objects.update_or_create(
#         #                 from_client_id=from_client.id,
#         #                 to_client_id=to_client.id,
#         #                 defaults=rel
#         #             )
#         #             keep_ids.append(obj.id)
#         #     except Client.DoesNotExist:
#         #         print(f"Client not found for fromIndex={from_index} or toIndex={to_index}")
#         #         continue
#         # ClientRelation.objects.filter(from_client=instance).exclude(id__in=keep_ids).delete()

#         return instance
    
#     def expand_passports(self, passport_dict):
#         if not passport_dict:
#             return []
#         max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#         results = []
#         for i in range(max_len):
#             record = {
#                 k: v[i] if isinstance(v, list) and i < len(v) else v
#                 for k, v in passport_dict.items()
#             }
#             results.append(record)
#         return results

#     # --- Create ---
#     @transaction.atomic
#     def create(self, validated_data):
#         def unwrap(value):
#             return value if value not in ["", "null"] else None

#         # Pop related data
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # Handle FKs
#         validated_data["country_code"] = self.safe_fk(Countries, validated_data.pop("country_code", None))
#         validated_data["residential_country"] = self.safe_fk(Countries, validated_data.pop("residential_country", None))
#         validated_data["residential_state"] = self.safe_fk(State, validated_data.pop("residential_state", None))
#         validated_data["residential_city"] = self.safe_fk(Cities, validated_data.pop("residential_city", None))
#         validated_data["ref_preferred_airline"] = self.safe_fk(Airlines, validated_data.pop("ref_preferred_airline", None))
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         # Handle files
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # Create related objects
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if any(pd.values()):
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             if any(vd.values()):
#                 vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#                 vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#                 country_value = vd.pop("ref_visa_country", None)
#                 if country_value:
#                     if isinstance(country_value, (str, int)):
#                         vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                     elif isinstance(country_value, dict):
#                         vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                     elif isinstance(country_value, Countries):
#                         vd["ref_visa_country"] = country_value
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if any(ins.values()):
#                 ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#                 ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if any(cd.values()):
#                 company_name = cd.get("ref_company")
#                 if company_name:
#                     try:
#                         company_instance = Company.objects.get(company_name=company_name)
#                         cd["ref_company_id"] = company_instance.id
#                         cd.pop("ref_company", None)
#                         AssocClientCompany.objects.create(ref_client=client, **cd)
#                     except Company.DoesNotExist:
#                         pass

#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if any(flyer_data.values()):
#                 airline_value = flyer_data.get("ref_airline")
#                 if airline_value:
#                     try:
#                         airline_instance = Airlines.objects.get(airline=airline_value)
#                         flyer_data["ref_airline_id"] = airline_instance.id
#                         flyer_data.pop("ref_airline", None)
#                         flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#                         ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)
#                     except Airlines.DoesNotExist:
#                         pass

#         # Family Members
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]
#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}
#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": self._normalize_code(fam.get("clientCode")),
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }
#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)
#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())
#             created_family_members[fam_index] = family_client

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue
#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)
#                 if f_passport_no or f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )
#             prev_family_client = family_client

#         # Relations with Others
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue
#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")
#             if from_index is None or to_index is None:
#                 continue
#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue
#             try:
#                 target_client = created_family_members.get(int(to_index)) or Client.objects.get(pk=int(to_index))
#                 ClientRelation.objects.create(
#                     from_client=from_client,
#                     to_client=target_client,
#                     relation=relation,
#                     cross_relation=cross_relation
#                 )
#             except Client.DoesNotExist:
#                 continue

#         return client

#     # --- Representation ---
#     def to_representation(self, instance):
#         data = super().to_representation(instance)
#         data["client_passport"] = ClientPassportSerializer(instance.client_passport.all(), many=True, context=self.context).data
#         data["client_visa"] = ClientVisaSerializer(instance.client_visa.all(), many=True, context=self.context).data
#         data["travel_insurance"] = ClientTravelInsuranceSerializer(instance.travel_insurance.all(), many=True, context=self.context).data
#         data["client_companies"] = AssocClientCompanySerializer(instance.client_companies.all(), many=True, context=self.context).data
#         data["client_documents"] = OtherDocumentSerializer(instance.client_documents.all(), many=True, context=self.context).data
#         data["client_frequent_flyers"] = FrequentflyerSerializer(instance.frequent_flyers.all(), many=True, context=self.context).data
#         data["familyMembers"] = self.get_familyMembers(instance)
#         return data

#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

# class FullClientSerializer(serializers.ModelSerializer):
#     country_code = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(queryset=Countries.objects.all(), required=False, allow_null=True)
#     residential_state = serializers.PrimaryKeyRelatedField(queryset=State.objects.all(), required=False, allow_null=True)
#     residential_city = serializers.PrimaryKeyRelatedField(queryset=Cities.objects.all(), required=False, allow_null=True)
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(queryset=Airlines.objects.all(), required=False, allow_null=True)

#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     client_salutation = serializers.ChoiceField(choices=Client.SALUTION, required=False, allow_blank=True, allow_null=True)
#     gender = serializers.ChoiceField(choices=Client.GENDER, required=False, allow_blank=True, allow_null=True)
#     marital_status = serializers.ChoiceField(choices=Client.MARITAL_STATUS, required=False, allow_blank=True, allow_null=True)
#     reference_from = serializers.ChoiceField(choices=Client.REFERENCE_FROM, required=False, allow_blank=True, allow_null=True)
#     relation = serializers.ChoiceField(choices=Client.RELATION, required=False, allow_blank=True, allow_null=True)
#     crossrelation = serializers.ChoiceField(choices=Client.CROSS_RELATION, required=False, allow_blank=True, allow_null=True)
#     client_type = serializers.ChoiceField(choices=Client.CLIENT_TYPE, required=False, allow_blank=True, allow_null=True)
#     seat_preference = serializers.ChoiceField(choices=Client.SEAT_PREFERED, required=False, allow_blank=True, allow_null=True)
#     meal_preference = serializers.ChoiceField(choices=Client.PREFERED_MEAL, required=False, allow_blank=True, allow_null=True)
#     fare_preference = serializers.ChoiceField(choices=Client.PREFERED_FARE_TYPE, required=False, allow_blank=True, allow_null=True)
#     star_rating = serializers.ChoiceField(choices=Client.STAR_RATING, required=False, allow_blank=True, allow_null=True)
#     stay_preference = serializers.ChoiceField(choices=Client.STAY_PREFERED, required=False, allow_blank=True, allow_null=True)
#     room_preference = serializers.ChoiceField(choices=Client.ROOM_PREFERED, required=False, allow_blank=True, allow_null=True)
#     extra_amenities = serializers.ChoiceField(choices=Client.EXTRA_AMENITIES, required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
#             "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         print(f"Normalizing client_code: {code} -> {code or None}")
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             print(f"Cleaning date: {value} -> None")
#             return None
#         if isinstance(value, str):
#             try:
#                 cleaned = datetime.strptime(value, "%Y-%m-%d").date()
#                 print(f"Cleaning date: {value} -> {cleaned}")
#                 return cleaned
#             except ValueError:
#                 print(f"Cleaning date: {value} -> None (invalid format)")
#                 return None
#         return value

#     def clean_str(self, value):
#         if value in ["", None, [], [""]]:
#             print(f"Cleaning string: {value} -> None")
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 value = " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         cleaned = str(value).strip() or None
#         print(f"Cleaning string: {value} -> {cleaned}")
#         return cleaned

#     def clean_row(self, row, file_map=None):
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         if "id" in cleaned:
#             try:
#                 cleaned["id"] = int(cleaned["id"]) if cleaned["id"] else None
#             except (ValueError, TypeError):
#                 cleaned["id"] = None

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]
#                     print(f"File found for {field}: {req_field}")
#                 elif field in cleaned and cleaned[field] in ["", "null", None]:
#                     cleaned[field] = None
#                     print(f"Clearing file for {field}: {cleaned[field]}")

#         print(f"Cleaned row: {cleaned}")
#         return cleaned

#     def safe_fk(self, model_class, value):
#         if not value:
#             print(f"Safe FK for {model_class.__name__}: {value} -> None")
#             return None
#         try:
#             if isinstance(value, int):
#                 obj = model_class.objects.get(id=value) if model_class.objects.filter(id=value).exists() else None
#                 print(f"Safe FK for {model_class.__name__}: {value} -> {obj}")
#                 return obj
#             if isinstance(value, dict):
#                 value_int = value.get("id")
#                 obj = model_class.objects.get(id=value_int) if value_int and model_class.objects.filter(id=value_int).exists() else None
#                 print(f"Safe FK for {model_class.__name__}: {value} -> {obj}")
#                 return obj
#             if isinstance(value, str):
#                 value_int = int(value)
#                 obj = model_class.objects.get(id=value_int) if model_class.objects.filter(id=value_int).exists() else None
#                 print(f"Safe FK for {model_class.__name__}: {value} -> {obj}")
#                 return obj
#             if isinstance(value, model_class):
#                 print(f"Safe FK for {model_class.__name__}: {value} -> {value}")
#                 return value
#             print(f"Safe FK for {model_class.__name__}: {value} -> None (invalid type)")
#             return None
#         except (ValueError, TypeError, model_class.DoesNotExist):
#             print(f"Safe FK for {model_class.__name__}: {value} -> None (exception)")
#             return None

#     def normalize_preferred_contact_method(self, value):
#         normalized = []
#         if not value:
#             print(f"Normalizing preferred_contact_method: {value} -> []")
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         print(f"Normalizing preferred_contact_method: {value} -> {normalized}")
#         return normalized

#     def validate(self, data):
#         print(f"Validating data: {data}")
#         def unwrap_scalars(data, skip_keys):
#             result = {}
#             for k, v in data.items():
#                 if k in skip_keys:
#                     result[k] = v
#                 elif isinstance(v, list) and len(v) == 1:
#                     result[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     result[k] = None
#                 else:
#                     result[k] = v
#             return result

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         char_dropdowns = [
#             "client_salutation", "gender", "marital_status", "reference_from", "relation",
#             "crossrelation", "client_type", "seat_preference", "meal_preference",
#             "fare_preference", "star_rating", "stay_preference", "room_preference", "extra_amenities"
#         ]
#         for field in char_dropdowns:
#             if field in data:
#                 data[field] = self.clean_str(data.get(field))

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     if "id" in item:
#                         try:
#                             item["id"] = int(item["id"]) if item["id"] else None
#                         except (ValueError, TypeError):
#                             item["id"] = None
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if "id" in p:
#                     try:
#                         p["id"] = int(p["id"]) if p["id"] else None
#                     except (ValueError, TypeError):
#                         p["id"] = None
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))
#                 file_key = f"client_passport[{len(expanded_passports)}][passport_file]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     p["passport_file"] = self.context["request"].FILES[file_key]
#                     print(f"Passport file found: {file_key}")
#                 elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                     p["passport_file"] = None
#                     print(f"Clearing passport_file for index {len(expanded_passports)}")
#                 expanded_passports.append(p)
#         data["client_passport"] = expanded_passports

#         visas = data.get("client_visa", [])
#         for i, v in enumerate(visas):
#             if isinstance(v, dict):
#                 if "id" in v:
#                     try:
#                         v["id"] = int(v["id"]) if v["id"] else None
#                     except (ValueError, TypeError):
#                         v["id"] = None
#                 v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 v["visa_type"] = self.clean_str(v.get("visa_type"))
#                 v["ref_visa_country"] = self.safe_fk(Countries, v.get("ref_visa_country"))
#                 file_key = f"client_visa[{i}][passport_size_photograph]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     v["passport_size_photograph"] = self.context["request"].FILES[file_key]
#                     print(f"Visa photograph found: {file_key}")
#                 else:
#                     # Explicitly check request.data for null/empty
#                     data_key = f"client_visa[{i}][passport_size_photograph]"
#                     if self.context.get("request") and data_key in self.context["request"].data and self.context["request"].data[data_key] in ["", "null", None]:
#                         v["passport_size_photograph"] = None
#                         print(f"Clearing passport_size_photograph for visa index {i} (explicit null in request.data)")
#                     elif "passport_size_photograph" in v and v["passport_size_photograph"] in ["", "null", None]:
#                         v["passport_size_photograph"] = None
#                         print(f"Clearing passport_size_photograph for visa index {i}")
#                 print(f"Processed visa {i}: {v}")

#         insurances = data.get("travel_insurance", [])
#         for i, t in enumerate(insurances):
#             if isinstance(t, dict):
#                 if "id" in t:
#                     try:
#                         t["id"] = int(t["id"]) if t["id"] else None
#                     except (ValueError, TypeError):
#                         t["id"] = None
#                 t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))
#                 file_key = f"travel_insurance[{i}][insurance_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     t["insurance_document"] = self.context["request"].FILES[file_key]
#                     print(f"Insurance document found: {file_key}")
#                 else:
#                     # Explicitly check request.data for null/empty
#                     data_key = f"travel_insurance[{i}][insurance_document]"
#                     if self.context.get("request") and data_key in self.context["request"].data and self.context["request"].data[data_key] in ["", "null", None]:
#                         t["insurance_document"] = None
#                         print(f"Clearing insurance_document for insurance index {i} (explicit null in request.data)")
#                     elif "insurance_document" in t and t["insurance_document"] in ["", "null", None]:
#                         t["insurance_document"] = None
#                         print(f"Clearing insurance_document for insurance index {i}")
#                 print(f"Processed travel insurance {i}: {t}")

#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 if "id" in d:
#                     try:
#                         d["id"] = int(d["id"]) if d["id"] else None
#                     except (ValueError, TypeError):
#                         d["id"] = None
#                 file_key = f"client_documents[{i}][other_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     d["other_document"] = self.context["request"].FILES[file_key]
#                     print(f"Other document found: {file_key}")
#                 elif "other_document" in d and d["other_document"] in ["", "null", None]:
#                     d["other_document"] = None
#                     print(f"Clearing other_document for document index {i}")
#                 d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "id" in c:
#                     try:
#                         c["id"] = int(c["id"]) if c["id"] else None
#                     except (ValueError, TypeError):
#                         c["id"] = None
#                 c["designation"] = self.clean_str(c.get("designation"))
#                 c["ref_company"] = self.safe_fk(Company, c.get("ref_company"))

#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "id" in f:
#                     try:
#                         f["id"] = int(f["id"]) if f["id"] else None
#                     except (ValueError, TypeError):
#                         f["id"] = None
#                 f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 f["ref_airline"] = self.safe_fk(Airlines, f.get("ref_airline"))

#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "id" in fam:
#                     try:
#                         fam["id"] = int(fam["id"]) if fam["id"] else None
#                     except (ValueError, TypeError):
#                         fam["id"] = None
#                 fam["dob"] = self.clean_date(fam.get("dob"))
#                 fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 fam["salutation"] = self.clean_str(fam.get("salutation"))
#                 fam["firstName"] = self.clean_str(fam.get("firstName"))
#                 fam["middleName"] = self.clean_str(fam.get("middleName"))
#                 fam["lastName"] = self.clean_str(fam.get("lastName"))
#                 fam["relation"] = self.clean_str(fam.get("relation"))
#                 fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#                 fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#                 fam["email"] = self.clean_str(fam.get("email"))
#                 fam["gender"] = self.clean_str(fam.get("gender"))
#                 fam["occupation"] = self.clean_str(fam.get("occupation"))
#                 fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#                 fam["panNo"] = self.clean_str(fam.get("panNo"))
#                 fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#                 fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#                 fam["residential_country"] = self.safe_fk(Countries, fam.get("residential_country"))
#                 fam["residential_state"] = self.safe_fk(State, fam.get("residential_state"))
#                 fam["residential_city"] = self.safe_fk(Cities, fam.get("residential_city"))

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for pi, p in enumerate(fam.get("fam_passport", [])):
#                         if isinstance(p, dict):
#                             if "id" in p:
#                                 try:
#                                     p["id"] = int(p["id"]) if p["id"] else None
#                                 except (ValueError, TypeError):
#                                     p["id"] = None
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))
#                             file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                             if self.context.get("request") and file_key in self.context["request"].FILES:
#                                 p["passport_file"] = self.context["request"].FILES[file_key]
#                                 print(f"Family passport file found: {file_key}")
#                             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                                 p["passport_file"] = None
#                                 print(f"Clearing passport_file for family passport index {pi}")
#                             expanded_fam_passports.append(p)
#                     fam["fam_passport"] = expanded_fam_passports

#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict):
#                 if "id" in r:
#                     try:
#                         r["id"] = int(r["id"]) if r["id"] else None
#                     except (ValueError, TypeError):
#                         r["id"] = None
#                 r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))
#                 r["relation"] = self.clean_str(r.get("relation"))
#                 r["crossRelation"] = self.clean_str(r.get("crossRelation"))
#                 if "fromIndex" in r and r["fromIndex"] in ["", "null", None]:
#                     r["fromIndex"] = None
#                 if "toIndex" in r and r["toIndex"] in ["", "null", None]:
#                     r["toIndex"] = None

#         print(f"Validated data: {data}")
#         return data

#     @transaction.atomic
#     def update(self, instance, validated_data):
#         print(f"Updating client {instance.client_id} with data: {validated_data}")
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 model_class = fk_models.get(fk_field)
#                 setattr(instance, fk_field, self.safe_fk(model_class, fk_value))
#                 print(f"Set {fk_field} to {getattr(instance, fk_field)}")

#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         char_dropdowns = [
#             "client_salutation", "gender", "marital_status", "reference_from", "relation",
#             "crossrelation", "client_type", "seat_preference", "meal_preference",
#             "fare_preference", "star_rating", "stay_preference", "room_preference", "extra_amenities"
#         ]
#         for field in char_dropdowns:
#             if field in validated_data:
#                 validated_data[field] = self.clean_str(validated_data.get(field))
#                 print(f"Cleaned {field}: {validated_data[field]}")

#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#                 print(f"Set {field} to {files[field]}")
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if file_val is None or file_val in ["", "null"]:
#                     setattr(instance, field, None)
#                     print(f"Cleared {field}")

#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#             "family_members", "fam_passport", "relationsWithOthers"
#         }

#         for attr, value in validated_data.items():
#             if attr in skip_keys or value is None:
#                 continue
#             setattr(instance, attr, value)
#             print(f"Set client field {attr} to {value}")

#         instance.save()

#         passports_data = validated_data.pop("client_passport", [])
#         keep_ids = []
#         for pd in passports_data:
#             obj_id = pd.pop("id", None)
#             if is_empty(pd):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             if obj_id:
#                 try:
#                     ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                     keep_ids.append(obj_id)
#                     print(f"Updated passport {obj_id}: {pd}")
#                 except ClientPassport.DoesNotExist:
#                     print(f"Passport {obj_id} does not exist, skipping")
#                     pass
#             else:
#                 obj, created = ClientPassport.objects.update_or_create(
#                     ref_client=instance,
#                     passport_no=pd.get("passport_no"),
#                     defaults=pd
#                 )
#                 keep_ids.append(obj.id)
#                 print(f"Created/Updated passport {obj.id}: {pd}")
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted passports not in {keep_ids}")

#         visas_data = validated_data.pop("client_visa", [])
#         keep_ids = []
#         for i, vd in enumerate(visas_data):
#             obj_id = vd.pop("id", None)
#             if is_empty(vd):
#                 print(f"Skipping empty visa data at index {i}")
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             vd["visa_type"] = self.clean_str(vd.get("visa_type"))
#             vd["ref_visa_country"] = self.safe_fk(Countries, vd.get("ref_visa_country"))
#             file_key = f"client_visa[{i}][passport_size_photograph]"
#             data_key = f"client_visa[{i}][passport_size_photograph]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 vd["passport_size_photograph"] = self.context["request"].FILES[file_key]
#                 print(f"Visa photograph found for index {i}: {file_key}")
#             elif self.context.get("request") and data_key in self.context["request"].data and self.context["request"].data[data_key] in ["", "null", None]:
#                 vd["passport_size_photograph"] = None
#                 print(f"Clearing passport_size_photograph for visa index {i} (explicit null in request.data)")
#             elif "passport_size_photograph" in vd and vd["passport_size_photograph"] in ["", "null", None]:
#                 vd["passport_size_photograph"] = None
#                 print(f"Clearing passport_size_photograph for visa index {i}")
#             if obj_id:
#                 try:
#                     ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                     keep_ids.append(obj_id)
#                     print(f"Updated visa {obj_id}: {vd}")
#                 except ClientVisa.DoesNotExist:
#                     print(f"Visa {obj_id} does not exist, skipping")
#                     pass
#             else:
#                 if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                     obj, created = ClientVisa.objects.update_or_create(
#                         ref_client=instance,
#                         visa_type=vd.get("visa_type"),
#                         ref_visa_country=vd.get("ref_visa_country"),
#                         defaults=vd
#                     )
#                     keep_ids.append(obj.id)
#                     print(f"Created/Updated visa {obj.id}: {vd}")
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted visas not in {keep_ids}")

#         insurances_data = validated_data.pop("travel_insurance", [])
#         keep_ids = []
#         for i, ins in enumerate(insurances_data):
#             obj_id = ins.pop("id", None)
#             if is_empty(ins):
#                 print(f"Skipping empty travel insurance data at index {i}")
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             file_key = f"travel_insurance[{i}][insurance_document]"
#             data_key = f"travel_insurance[{i}][insurance_document]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 ins["insurance_document"] = self.context["request"].FILES[file_key]
#                 print(f"Insurance document found for index {i}: {file_key}")
#             elif self.context.get("request") and data_key in self.context["request"].data and self.context["request"].data[data_key] in ["", "null", None]:
#                 ins["insurance_document"] = None
#                 print(f"Clearing insurance_document for insurance index {i} (explicit null in request.data)")
#             elif "insurance_document" in ins and ins["insurance_document"] in ["", "null", None]:
#                 ins["insurance_document"] = None
#                 print(f"Clearing insurance_document for insurance index {i}")
#             if obj_id:
#                 try:
#                     ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                     keep_ids.append(obj_id)
#                     print(f"Updated travel insurance {obj_id}: {ins}")
#                 except ClientTravelInsurance.DoesNotExist:
#                     print(f"Travel insurance {obj_id} does not exist, skipping")
#                     pass
#             else:
#                 if ins.get("insurance_from_date") or ins.get("insurance_to_date") or ins.get("insurance_document"):
#                     obj, created = ClientTravelInsurance.objects.update_or_create(
#                         ref_client=instance,
#                         defaults=ins
#                     )
#                     keep_ids.append(obj.id)
#                     print(f"Created/Updated travel insurance {obj.id}: {ins}")
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted travel insurances not in {keep_ids}")

#         docs_data = validated_data.pop("client_documents", [])
#         keep_ids = []
#         for i, doc in enumerate(docs_data):
#             obj_id = doc.pop("id", None)
#             if is_empty(doc):
#                 continue
#             doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#             file_key = f"client_documents[{i}][other_document]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 doc["other_document"] = self.context["request"].FILES[file_key]
#                 print(f"Other document found for index {i}: {file_key}")
#             elif "other_document" in doc and doc["other_document"] in ["", "null", None]:
#                 doc["other_document"] = None
#                 print(f"Clearing other_document for document index {i}")
#             if obj_id:
#                 try:
#                     ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                     keep_ids.append(obj_id)
#                     print(f"Updated document {obj_id}: {doc}")
#                 except ClientDocument.DoesNotExist:
#                     print(f"Document {obj_id} does not exist, skipping")
#                     pass
#             else:
#                 obj, created = ClientDocument.objects.update_or_create(
#                     ref_client=instance,
#                     other_document_name=doc.get("other_document_name"),
#                     defaults=doc
#                 )
#                 keep_ids.append(obj.id)
#                 print(f"Created/Updated document {obj.id}: {doc}")
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted documents not in {keep_ids}")

#         companies_data = validated_data.pop("client_companies", [])
#         keep_ids = []
#         for i, comp in enumerate(companies_data):
#             obj_id = comp.pop("id", None)
#             if is_empty(comp):
#                 print(f"Skipping empty company data at index {i}")
#                 continue
#             comp["designation"] = self.clean_str(comp.get("designation"))
#             comp["ref_company"] = self.safe_fk(Company, comp.get("ref_company"))
#             if obj_id:
#                 try:
#                     AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                     keep_ids.append(obj_id)
#                     print(f"Updated company {obj_id}: {comp}")
#                 except AssocClientCompany.DoesNotExist:
#                     print(f"Company {obj_id} does not exist, skipping")
#                     pass
#             else:
#                 if comp.get("ref_company") or comp.get("designation"):
#                     obj, created = AssocClientCompany.objects.update_or_create(
#                         ref_client=instance,
#                         ref_company=comp.get("ref_company"),
#                         defaults=comp
#                     )
#                     keep_ids.append(obj.id)
#                     print(f"Created/Updated company {obj.id}: {comp}")
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted companies not in {keep_ids}")

#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         keep_ids = []
#         for i, ff in enumerate(frequent_flyers_data):
#             obj_id = ff.pop("id", None)
#             if is_empty(ff):
#                 print(f"Skipping empty frequent flyer data at index {i}")
#                 continue
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             ff["ref_airline"] = self.safe_fk(Airlines, ff.get("ref_airline"))
#             if obj_id:
#                 try:
#                     ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                     keep_ids.append(obj_id)
#                     print(f"Updated frequent flyer {obj_id}: {ff}")
#                 except ClientFrequentFlyer.DoesNotExist:
#                     print(f"Frequent flyer {obj_id} does not exist, skipping")
#                     pass
#             else:
#                 if ff.get("ref_airline") or ff.get("ff_no"):
#                     obj, created = ClientFrequentFlyer.objects.update_or_create(
#                         ref_client=instance,
#                         ref_airline=ff.get("ref_airline"),
#                         defaults=ff
#                     )
#                     keep_ids.append(obj.id)
#                     print(f"Created/Updated frequent flyer {obj.id}: {ff}")
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted frequent flyers not in {keep_ids}")

#         family_members_data = validated_data.pop("family_members", [])
#         keep_ids = []
#         for fam_index, fam in enumerate(family_members_data):
#             obj_id = fam.pop("id", None)
#             if is_empty(fam):
#                 print(f"Skipping empty family member data at index {fam_index}")
#                 continue
#             fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#             fam["salutation"] = self.clean_str(fam.get("salutation"))
#             fam["firstName"] = self.clean_str(fam.get("firstName"))
#             fam["middleName"] = self.clean_str(fam.get("middleName"))
#             fam["lastName"] = self.clean_str(fam.get("lastName"))
#             fam["relation"] = self.clean_str(fam.get("relation"))
#             fam["crossrelation"] = self.clean_str(fam.get("crossrelation"))
#             fam["contactNo"] = self.clean_str(fam.get("contactNo"))
#             fam["email"] = self.clean_str(fam.get("email"))
#             fam["gender"] = self.clean_str(fam.get("gender"))
#             fam["occupation"] = self.clean_str(fam.get("occupation"))
#             fam["aadhaarNo"] = self.clean_str(fam.get("aadhaarNo"))
#             fam["panNo"] = self.clean_str(fam.get("panNo"))
#             fam["residential_address"] = self.clean_str(fam.get("residential_address"))
#             fam["residential_pincode"] = self.clean_str(fam.get("residential_pincode"))
#             fam["dob"] = self.clean_date(fam.get("dob"))
#             fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#             for fk_field in ["residential_country", "residential_state", "residential_city"]:
#                 if fk_field in fam:
#                     model_class = {
#                         "residential_country": Countries,
#                         "residential_state": State,
#                         "residential_city": Cities
#                     }[fk_field]
#                     fam[fk_field] = self.safe_fk(model_class, fam.get(fk_field))
#                     print(f"Set family {fk_field} to {fam[fk_field]}")

#             fam_passports = fam.pop("fam_passport", [])
#             fam_passport_ids = []
#             for pi, pd in enumerate(fam_passports):
#                 pd_id = pd.pop("id", None)
#                 if is_empty(pd):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     pd["passport_file"] = self.context["request"].FILES[file_key]
#                     print(f"Family passport file found for index {pi}: {file_key}")
#                 elif "passport_file" in pd and pd["passport_file"] in ["", "null", None]:
#                     pd["passport_file"] = None
#                     print(f"Clearing passport_file for family passport index {pi}")
#                 if obj_id:
#                     try:
#                         family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#                         if pd_id:
#                             try:
#                                 ClientPassport.objects.filter(id=pd_id, ref_client=family_client).update(**pd)
#                                 fam_passport_ids.append(pd_id)
#                                 print(f"Updated family passport {pd_id}: {pd}")
#                             except ClientPassport.DoesNotExist:
#                                 print(f"Family passport {pd_id} does not exist, skipping")
#                                 pass
#                         else:
#                             obj, created = ClientPassport.objects.update_or_create(
#                                 ref_client=family_client,
#                                 passport_no=pd.get("passport_no"),
#                                 defaults=pd
#                             )
#                             fam_passport_ids.append(obj.id)
#                             print(f"Created/Updated family passport {obj.id}: {pd}")
#                     except Client.DoesNotExist:
#                         print(f"Family client {obj_id} does not exist, skipping")
#                         continue
#                 else:
#                     continue
#             if obj_id:
#                 try:
#                     family_client = Client.objects.get(client_id=obj_id, ref_client=instance)
#                     ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=fam_passport_ids).delete()
#                     print(f"Deleted family passports not in {fam_passport_ids} for client {obj_id}")
#                 except Client.DoesNotExist:
#                     print(f"Family client {obj_id} does not exist, skipping")
#                     pass

#             if obj_id:
#                 try:
#                     Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam)
#                     keep_ids.append(obj_id)
#                     print(f"Updated family member {obj_id}: {fam}")
#                 except Client.DoesNotExist:
#                     print(f"Family member {obj_id} does not exist, skipping")
#                     pass
#             else:
#                 fam["ref_client"] = instance
#                 fam["client_type"] = "Family Member"
#                 fam["client_status"] = 1
#                 obj = Client.objects.create(**fam)
#                 keep_ids.append(obj.client_id)
#                 print(f"Created family member {obj.client_id}: {fam}")
#         Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()
#         print(f"Deleted family members not in {keep_ids}")

#         relations_data = validated_data.pop("relationsWithOthers", [])
#         keep_ids = []
#         for i, rel in enumerate(relations_data):
#             obj_id = rel.pop("id", None)
#             if is_empty(rel):
#                 print(f"Skipping empty relation data at index {i}")
#                 continue
#             rel["relation"] = self.clean_str(rel.get("relation"))
#             rel["crossRelation"] = self.clean_str(rel.get("crossRelation"))
#             from_index = rel.pop("fromIndex", None)
#             to_index = rel.pop("toIndex", None)
#             if from_index is None or to_index is None:
#                 print(f"Skipping relation at index {i}: fromIndex={from_index}, toIndex={to_index}")
#                 continue
#             try:
#                 from_client = Client.objects.get(id=from_index)
#                 to_client = Client.objects.get(id=to_index)
#                 rel["from_client"] = from_client
#                 rel["to_client"] = to_client
#                 if obj_id:
#                     try:
#                         ClientRelation.objects.filter(id=obj_id).update(**rel)
#                         keep_ids.append(obj_id)
#                         print(f"Updated relation {obj_id}: {rel}")
#                     except ClientRelation.DoesNotExist:
#                         print(f"Relation {obj_id} does not exist, skipping")
#                         pass
#                 else:
#                     obj, created = ClientRelation.objects.update_or_create(
#                         from_client=from_client,
#                         to_client=to_client,
#                         defaults=rel
#                     )
#                     keep_ids.append(obj.id)
#                     print(f"Created/Updated relation {obj.id}: {rel}")
#             except Client.DoesNotExist:
#                 print(f"Client not found for relation at index {i}: fromIndex={from_index}, toIndex={to_index}")
#                 continue
#         ClientRelation.objects.filter(from_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted relations not in {keep_ids}")

#         print(f"Updated client {instance.client_id}")
#         return instance

#     @transaction.atomic
#     def create(self, validated_data):
#         print(f"Creating client with data: {validated_data}")
#         def unwrap(value):
#             if isinstance(value, list):
#                 value = value[0] if value else None
#             return value if value not in ["", "null"] else None

#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         validated_data["country_code"] = self.safe_fk(Countries, validated_data.pop("country_code", None))
#         validated_data["residential_country"] = self.safe_fk(Countries, validated_data.pop("residential_country", None))
#         validated_data["residential_state"] = self.safe_fk(State, validated_data.pop("residential_state", None))
#         validated_data["residential_city"] = self.safe_fk(Cities, validated_data.pop("residential_city", None))
#         validated_data["ref_preferred_airline"] = self.safe_fk(Airlines, validated_data.pop("ref_preferred_airline", None))
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         char_dropdowns = [
#             "client_salutation", "gender", "marital_status", "reference_from", "relation",
#             "crossrelation", "client_type", "seat_preference", "meal_preference",
#             "fare_preference", "star_rating", "stay_preference", "room_preference", "extra_amenities"
#         ]
#         for field in char_dropdowns:
#             if field in validated_data:
#                 validated_data[field] = self.clean_str(validated_data.get(field))
#                 print(f"Cleaned {field}: {validated_data[field]}")

#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[file_field] = request_files.get(file_field)
#             print(f"Set {file_field} to {validated_data[file_field]}")

#         client = Client.objects.create(**validated_data)
#         print(f"Created client {client.client_id}")

#         for i, pd in enumerate(passports_data):
#             pd = self.clean_row(pd, file_map={"passport_file": f"client_passport[{i}][passport_file]"})
#             if not any(pd.values()):
#                 print(f"Skipping empty passport data at index {i}")
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"] or pd.get("passport_file"):
#                 ClientPassport.objects.create(ref_client=client, **pd)
#                 print(f"Created passport for client {client.client_id}: {pd}")

#         for i, vd in enumerate(visas_data):
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": f"client_visa[{i}][passport_size_photograph]"})
#             if not any(vd.values()):
#                 print(f"Skipping empty visa data at index {i}")
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             vd["ref_visa_country"] = self.safe_fk(Countries, vd.pop("ref_visa_country", None))
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)
#                 print(f"Created visa for client {client.client_id}: {vd}")

#         for i, ins in enumerate(insurances_data):
#             ins = self.clean_row(ins, file_map={"insurance_document": f"travel_insurance[{i}][insurance_document]"})
#             if not any(ins.values()):
#                 print(f"Skipping empty travel insurance data at index {i}")
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins.get("insurance_from_date") or ins.get("insurance_to_date") or ins.get("insurance_document"):
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)
#                 print(f"Created travel insurance for client {client.client_id}: {ins}")

#         for i, doc in enumerate(docs_data):
#             doc = self.clean_row(doc, file_map={"other_document": f"client_documents[{i}][other_document]"})
#             if not any(doc.values()):
#                 print(f"Skipping empty document data at index {i}")
#                 continue
#             doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#             ClientDocument.objects.create(ref_client=client, **doc)
#             print(f"Created document for client {client.client_id}: {doc}")

#         for i, cd in enumerate(companies_data):
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 print(f"Skipping empty company data at index {i}")
#                 continue
#             cd["ref_company"] = self.safe_fk(Company, cd.pop("ref_company", None))
#             if cd.get("ref_company") or cd.get("designation"):
#                 AssocClientCompany.objects.create(ref_client=client, **cd)
#                 print(f"Created company for client {client.client_id}: {cd}")

#         for i, ff in enumerate(frequent_flyers_data):
#             ff = self.clean_row(ff)
#             if not any(ff.values()):
#                 print(f"Skipping empty frequent flyer data at index {i}")
#                 continue
#             ff["ref_airline"] = self.safe_fk(Airlines, ff.pop("ref_airline", None))
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             if ff.get("ref_airline") or ff.get("ff_no"):
#                 ClientFrequentFlyer.objects.create(ref_client=client, **ff)
#                 print(f"Created frequent flyer for client {client.client_id}: {ff}")

#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     print(f"Skipping invalid family member data at index {fam_index}")
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 print(f"Skipping empty family member data at index {fam_index}")
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": self.clean_str(fam.get("salutation")),
#                 "client_first_name": self.clean_str(fam.get("firstName")),
#                 "client_middle_name": self.clean_str(fam.get("middleName")),
#                 "client_last_name": self.clean_str(fam.get("lastName")),
#                 "relation": self.clean_str(fam.get("relation")),
#                 "crossrelation": self.clean_str(fam.get("crossrelation")),
#                 "contact_no": self.clean_str(fam.get("contactNo")),
#                 "email": self.clean_str(fam.get("email")),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": self.clean_str(fam.get("gender")),
#                 "occupation": self.clean_str(fam.get("occupation")),
#                 "aadhaar_no": self.clean_str(fam.get("aadhaarNo")),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": self.clean_str(fam.get("panNo")),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": self.clean_str(fam.get("residential_address")) or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": self.clean_str(fam.get("residential_pincode")) or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#                 print(f"Set aadhaar_card_file for family member {fam_index}: {fam_data['aadhaar_card_file']}")
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)
#                 print(f"Set pan_card_file for family member {fam_index}: {fam_data['pan_card_file']}")

#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())
#             print(f"Created family member {family_client.client_id}: {fam_data}")

#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     print(f"Skipping invalid family passport data at index {pd_index}")
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no or f_passport_expiry_date or f_passport_file:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )
#                     print(f"Created family passport for client {family_client.client_id}: {pd}")

#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                     print(f"Created relation from {prev_family_client.client_id} to {family_client.client_id}")
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )
#                     print(f"Created cross-relation from {family_client.client_id} to {prev_family_client.client_id}")

#             prev_family_client = family_client
#             created_family_members[family_client.id] = family_client

#         for i, rel in enumerate(relationsWithOthers):
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     print(f"Skipping invalid relation data at index {i}")
#                     continue
#             if not isinstance(rel, dict):
#                 print(f"Skipping non-dict relation data at index {i}")
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = self.clean_str(rel.get("relation"))
#             cross_relation = self.clean_str(rel.get("crossRelation"))

#             if from_index is None or to_index is None:
#                 print(f"Skipping relation at index {i}: fromIndex={from_index}, toIndex={to_index}")
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 try:
#                     from_client = Client.objects.get(pk=int(from_index))
#                 except Client.DoesNotExist:
#                     print(f"Skipping relation at index {i}: from_client {from_index} not found")
#                     continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     print(f"Skipping relation at index {i}: target_client {to_index} not found")
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#             print(f"Created relation from {from_client.client_id} to {target_client.client_id}")

#         print(f"Created client {client.client_id}")
#         return client

#     def to_representation(self, instance):
#         data = super().to_representation(instance)

#         if hasattr(instance, "client_passport"):
#             data["client_passport"] = ClientPassportSerializer(
#                 instance.client_passport.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_visa"):
#             data["client_visa"] = ClientVisaSerializer(
#                 instance.client_visa.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "travel_insurance"):
#             data["travel_insurance"] = ClientTravelInsuranceSerializer(
#                 instance.travel_insurance.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_companies"):
#             data["client_companies"] = AssocClientCompanySerializer(
#                 instance.client_companies.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_documents"):
#             data["client_documents"] = OtherDocumentSerializer(
#                 instance.client_documents.all(), many=True, context=self.context
#             ).data
#         if hasattr(instance, "client_frequent_flyers"):
#             data["client_frequent_flyers"] = FrequentflyerSerializer(
#                 instance.frequent_flyers.all(), many=True, context=self.context
#             ).data
                
#         data["familyMembers"] = self.get_familyMembers(instance)
#         print(f"Representation for client {instance.client_id}: {data}")

#         return data

#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data
     
# def unwrap_scalars(data, skip_keys=None):
#     """Helper to unwrap single-item lists for scalar fields."""
#     skip_keys = skip_keys or []
#     cleaned = {}
#     for k, v in data.items():
#         if k in skip_keys:
#             cleaned[k] = v
#         elif isinstance(v, list) and len(v) == 1:
#             cleaned[k] = v[0] if v[0] not in ["", "null", None] else None
#         else:
#             cleaned[k] = v if v not in ["", "null", None] else None
#     return cleaned

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True
#     )
#     preferred_airline = AirlinesSerializer(read_only=True)
#     ref_visa_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )

#     # --- Nested serializers (all many=True) ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
#             "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_row(self, row, file_map=None):
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         # Preserve 'id' field unless explicitly None
#         if "id" in row and cleaned.get("id") in ["", "null", None]:
#             cleaned.pop("id", None)

#         # Handle file uploads only if explicitly provided
#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]
#                 # Do not set file field to None if not in request_files

#         return cleaned

#     def clean_str(self, value):
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and v.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def safe_fk(self, value, model_class):
#         if not value:
#             return None
#         try:
#             value_int = int(value) if isinstance(value, (str, int)) else value.id
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError, AttributeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         print(f"Validating data: {data}")  # Debugging
#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents", "client_frequent_flyers",
#             "family_members", "fam_passport", "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         # Normalize nested fields
#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]

#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         # Uniqueness checks
#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         # Clean top-level dates
#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # Nested: Passport (Primary client)
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue

#         for i, p in enumerate(expanded_passports):
#             print(f"Validating client_passport[{i}]: {p}")  # Debugging
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#                 print(f"Found passport_file for client_passport[{i}]: {file_key}")  # Debugging
#             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                 p["passport_file"] = None
#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))
#             # Ensure at least one meaningful field is present
#             if not (p.get("passport_no") or p.get("passport_expiry_date") or p.get("passport_file")):
#                 print(f"Skipping client_passport[{i}] due to no meaningful data")  # Debugging
#                 continue
#             expanded_passports[i] = p

#         data["client_passport"] = [p for p in expanded_passports if p is not None]

#         # Nested: Familiar Passports
#         for i, p in enumerate(data.get("fam_passport", [])):
#             if isinstance(p, dict):
#                 if "fam_passport_no" in p:
#                     p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
#                 if "fam_passport_expiry_date" in p:
#                     p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))
#                 file_key = f"fam_passport[{i}][fam_passport_file]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     p["passport_file"] = self.context["request"].FILES[file_key]
#                     print(f"Found passport_file for fam_passport[{i}]: {file_key}")  # Debugging
#                 elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                     p["passport_file"] = None

#         # Nested: Relations with Others
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict) and "relation_with_other_client_code" in r:
#                 r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

#         # Nested: Companies
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None

#         # Nested: Documents
#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 file_key = f"client_documents[{i}][other_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     d["other_document"] = self.context["request"].FILES[file_key]
#                     print(f"Found other_document for client_documents[{i}]: {file_key}")  # Debugging
#                 elif "other_document" in d and d["other_document"] in ["", "null", None]:
#                     d["other_document"] = None
#                 if "other_document_name" in d:
#                     d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         # Nested: Frequent Flyers
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # Nested: Visa
#         for i, v in enumerate(data.get("client_visa", [])):
#             print(f"Validating client_visa[{i}]: {v}")  # Debugging
#             if isinstance(v, dict):
#                 if "id" in v:
#                     v["id"] = int(v["id"]) if isinstance(v["id"], (str, int)) else None
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "visa_type" in v:
#                     v["visa_type"] = self.clean_str(v.get("visa_type"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None
#                 elif "ref_visa_country" in v:
#                     v["ref_visa_country"] = self.safe_fk(v["ref_visa_country"], Countries)
#                 file_key = f"client_visa[{i}][passport_size_photograph]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     v["passport_size_photograph"] = self.context["request"].FILES[file_key]
#                     print(f"Found passport_size_photograph for client_visa[{i}]: {file_key}")  # Debugging
#                 elif "passport_size_photograph" in v and v["passport_size_photograph"] in ["", "null", None]:
#                     v["passport_size_photograph"] = None
#                 # Ensure at least one meaningful field is present
#                 if not (v.get("id") or v.get("visa_from_date") or v.get("visa_to_date") or v.get("ref_visa_country") or v.get("visa_type") or v.get("passport_size_photograph")):
#                     print(f"Skipping client_visa[{i}] due to no meaningful data")  # Debugging
#                     continue
#                 data["client_visa"][i] = v

#         # Nested: Travel Insurance
#         for i, t in enumerate(data.get("travel_insurance", [])):
#             print(f"Validating travel_insurance[{i}]: {t}")  # Debugging
#             if isinstance(t, dict):
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))
#                 file_key = f"travel_insurance[{i}][insurance_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     t["insurance_document"] = self.context["request"].FILES[file_key]
#                     print(f"Found insurance_document for travel_insurance[{i}]: {file_key}")  # Debugging
#                 elif "insurance_document" in t and t["insurance_document"] in ["", "null", None]:
#                     t["insurance_document"] = None

#         # Nested: Family Members
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for p in fam.get("fam_passport", []):
#                         if isinstance(p, dict):
#                             if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                                 expanded_fam_passports.extend(expand_passports(p))
#                             else:
#                                 expanded_fam_passports.append(p)
#                         else:
#                             continue

#                     for pi, p in enumerate(expanded_fam_passports):
#                         if isinstance(p.get("passport_no"), list):
#                             p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                         if isinstance(p.get("passport_expiry_date"), list):
#                             p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         if isinstance(p.get("passport_file"), list):
#                             p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                             print(f"Found passport_file for family_members[{fam_index}][fam_passport][{pi}]: {file_key}")  # Debugging
#                         elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                             p["passport_file"] = None

#                         if "passport_no" in p:
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         if "passport_expiry_date" in p:
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                     fam["fam_passport"] = expanded_fam_passports

#         print(f"Validated data: {data}")  # Debugging
#         return data

#     # ---------------- Serializer Methods ----------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
#         def unwrap(value):
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # Pop related data
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # Pop FKs
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         # Normalize country_code
#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         validated_data["country_code"] = country_code_instance
#         validated_data["residential_country"] = self.safe_fk(unwrap(country), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(state), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(city), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(airline), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             if file_field in request_files:
#                 validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # Assign FK fields
#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = (
#                 airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#             )
#         if country:
#             client.residential_country = (
#                 country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#             )
#         if state:
#             client.residential_state = (
#                 state if isinstance(state, State) else self.safe_fk(state, State)
#             )
#         if city:
#             client.residential_city = (
#                 city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#             )
#         client.save()

#         # Related: Passports
#         for i, pd in enumerate(passports_data):
#             pd = self.clean_row(pd, file_map={"passport_file": f"client_passport[{i}][passport_file]"})
#             if not any(pd.values()):
#                 print(f"Skipping client_passport[{i}] due to no meaningful data")  # Debugging
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"] or pd.get("passport_file"):
#                 print(f"Creating client_passport[{i}]: {pd}")  # Debugging
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # Related: Visas
#         for i, vd in enumerate(visas_data):
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": f"client_visa[{i}][passport_size_photograph]"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             vd["visa_type"] = self.clean_str(vd.get("visa_type"))

#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value

#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("visa_type") or vd.get("passport_size_photograph"):
#                 print(f"Creating client_visa[{i}]: {vd}")  # Debugging
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # Related: Travel Insurance
#         for i, ins in enumerate(insurances_data):
#             ins = self.clean_row(ins, file_map={"insurance_document": f"travel_insurance[{i}][insurance_document]"})
#             if not any(ins.values()):
#                 print(f"Skipping travel_insurance[{i}] due to no meaningful data")  # Debugging
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"] or ins.get("insurance_document"):
#                 print(f"Creating travel_insurance[{i}]: {ins}")  # Debugging
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # Other Documents
#         for i, doc in enumerate(docs_data):
#             doc = self.clean_row(doc, file_map={"other_document": f"client_documents[{i}][other_document]"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 print(f"Creating client_documents[{i}]: {doc}")  # Debugging
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for i, cd in enumerate(companies_data):
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 print(f"Skipping client_companies[{i}] due to no meaningful data")  # Debugging
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 print(f"Company not found for client_companies[{i}]: {company_name}")  # Debugging
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             print(f"Creating client_companies[{i}]: {cd}")  # Debugging
#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         for i, flyer_data in enumerate(frequent_flyers_data):
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 print(f"Skipping client_frequent_flyers[{i}] due to no meaningful data")  # Debugging
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 print(f"Airline not found for client_frequent_flyers[{i}]: {airline_value}")  # Debugging
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             print(f"Creating client_frequent_flyers[{i}]: {flyer_data}")  # Debugging
#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # Family Members
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     print(f"Invalid family_members[{fam_index}]: {fam}")  # Debugging
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 print(f"Skipping family_members[{fam_index}] due to no meaningful data")  # Debugging
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(fam.get("residential_country"), Countries) or client.residential_country,
#                 "residential_state": self.safe_fk(fam.get("residential_state"), State) or client.residential_state,
#                 "residential_city": self.safe_fk(fam.get("residential_city"), Cities) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             print(f"Creating family_members[{fam_index}]: {fam_data}")  # Debugging
#             family_client = Client.objects.create(**fam_data, created_by=self.context["request"].user if self.context.get("request") else None, created_at=timezone.now())

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no or f_passport_expiry_date or f_passport_file:
#                     print(f"Creating fam_passport[{fam_index}][{pd_index}]: {pd}")  # Debugging
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client
#             created_family_members[fam_index] = family_client

#         # Extra Relations
#         for i, rel in enumerate(relationsWithOthers):
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     print(f"Invalid relationsWithOthers[{i}]: {rel}")  # Debugging
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 print(f"Skipping relationsWithOthers[{i}] due to missing fromIndex/toIndex")  # Debugging
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 print(f"Skipping relationsWithOthers[{i}] due to invalid from_client: {from_index}")  # Debugging
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     print(f"Skipping relationsWithOthers[{i}] due to invalid to_client: {to_index}")  # Debugging
#                     continue

#             print(f"Creating relationsWithOthers[{i}]: {rel}")  # Debugging
#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )
#         return client

#     @transaction.atomic
#     def update(self, instance, validated_data):
#         print(f"Updating client instance {instance.client_id} with data: {validated_data}")  # Debugging
#         # Pop nested data
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         validated_data.pop("family_members", None)
#         validated_data.pop("familyMembers", None)
#         fam_passports_data = validated_data.pop("fam_passport", [])
#         relations_data = validated_data.pop("relationsWithOthers", [])

#         # Define FK fields and their corresponding models
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         # Handle FK fields
#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 model_class = fk_models.get(fk_field)
#                 if fk_value is None:
#                     validated_data[f"{fk_field}_id"] = None
#                 else:
#                     if isinstance(fk_value, dict):
#                         fk_value = fk_value.get("id")
#                     if isinstance(fk_value, model_class):
#                         validated_data[f"{fk_field}_id"] = fk_value.id
#                     elif isinstance(fk_value, (int, str)):
#                         try:
#                             fk_instance = model_class.objects.get(id=int(fk_value))
#                             validated_data[f"{fk_field}_id"] = fk_instance.id
#                         except (ValueError, TypeError, model_class.DoesNotExist):
#                             print(f"Invalid FK {fk_field}: {fk_value}")  # Debugging
#                             validated_data[f"{fk_field}_id"] = None
#                     else:
#                         validated_data[f"{fk_field}_id"] = None

#         # Normalize fields
#         if "client_code" in validated_data:
#             validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         if "dob" in validated_data:
#             validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         if "anniversary_date" in validated_data:
#             validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # Handle uploaded files
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         print(f"Request files: {files.keys()}")  # Debugging
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#                 print(f"Updated {field} with new file")  # Debugging
#             elif field in validated_data and validated_data[field] in ["", "null", None]:
#                 setattr(instance, field, None)
#                 print(f"Cleared {field}")  # Debugging
#             # Do not touch file field if not in validated_data or files

#         # Update main client fields
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         instance.save()
#         print(f"Updated client instance {instance.client_id}: {validated_data}")  # Debugging

#         # Helper to check if a dict is empty
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # Helper to update or create nested objects
#         def update_nested(model_class, data_list, ref_client, file_field=None, file_key_template=None, fk_fields=None):
#             keep_ids = []
#             fk_fields = fk_fields or {}
#             for i, item in enumerate(data_list):
#                 print(f"Processing {model_class.__name__}[{i}]: {item}")  # Debugging
#                 if is_empty(item):
#                     print(f"Skipping empty {model_class.__name__}[{i}]")  # Debugging
#                     continue
#                 item = self.clean_row(item, file_map={file_field: file_key_template.format(i)} if file_field and file_key_template else {})
#                 obj_id = item.pop("id", None)
#                 if obj_id:
#                     try:
#                         obj_id = int(obj_id)
#                     except (ValueError, TypeError):
#                         print(f"Invalid ID for {model_class.__name__}[{i}]: {obj_id}, treating as new")  # Debugging
#                         obj_id = None

#                 # Handle date fields
#                 for date_field in ["visa_from_date", "visa_to_date", "insurance_from_date", "insurance_to_date", "passport_expiry_date"]:
#                     if date_field in item:
#                         item[date_field] = self.clean_date(item.get(date_field))

#                 # Handle FK fields
#                 for fk_field, fk_model in fk_fields.items():
#                     if fk_field in item:
#                         fk_value = item.pop(fk_field, None)
#                         if fk_value is None:
#                             item[f"{fk_field}_id"] = None
#                         else:
#                             if isinstance(fk_value, dict):
#                                 item[f"{fk_field}_id"] = fk_value.get("id")
#                             elif isinstance(fk_value, fk_model):
#                                 item[f"{fk_field}_id"] = fk_value.id
#                             else:
#                                 try:
#                                     item[f"{fk_field}_id"] = int(fk_value)
#                                     # Verify FK exists
#                                     if not fk_model.objects.filter(id=item[f"{fk_field}_id"]).exists():
#                                         print(f"Invalid FK {fk_field} ID {item[f'{fk_field}_id']} for {model_class.__name__}[{i}]")  # Debugging
#                                         item[f"{fk_field}_id"] = None
#                                 except (ValueError, TypeError):
#                                     print(f"Invalid FK {fk_field} value {fk_value} for {model_class.__name__}[{i}]")  # Debugging
#                                     item[f"{fk_field}_id"] = None

#                 # Handle file field explicitly
#                 if file_field and file_key_template:
#                     file_key = file_key_template.format(i)
#                     if self.context.get("request") and file_key in self.context["request"].FILES:
#                         item[file_field] = self.context["request"].FILES[file_key]
#                         print(f"Found {file_field} for {model_class.__name__}[{i}]: {file_key}")  # Debugging
#                     elif file_field in item and item[file_field] in ["", "null", None]:
#                         item[file_field] = None
#                         print(f"Cleared {file_field} for {model_class.__name__}[{i}]")  # Debugging
#                     # Do not touch file_field if not provided

#                 # Handle string fields
#                 for str_field in ["passport_no", "ff_no", "other_document_name", "visa_type"]:
#                     if str_field in item:
#                         item[str_field] = self.clean_str(item.get(str_field))

#                 # Skip if no meaningful data
#                 meaningful_fields = [file_field] + list(fk_fields.keys()) + ["passport_no", "ff_no", "other_document_name", "visa_type", "visa_from_date", "visa_to_date", "insurance_from_date", "insurance_to_date", "passport_expiry_date"]
#                 meaningful_fields = [f for f in meaningful_fields if f in item]
#                 if not any(item.get(f) for f in meaningful_fields):
#                     print(f"Skipping {model_class.__name__}[{i}] due to no meaningful data")  # Debugging
#                     continue

#                 if obj_id:
#                     try:
#                         obj = model_class.objects.get(id=obj_id, ref_client=ref_client)
#                         print(f"Updating {model_class.__name__} id={obj_id}: {item}")  # Debugging
#                         for k, v in item.items():
#                             if k != file_field or v is not None:  # Preserve file if not explicitly updated
#                                 setattr(obj, k, v)
#                         obj.save()
#                         keep_ids.append(obj_id)
#                     except model_class.DoesNotExist:
#                         print(f"{model_class.__name__} id={obj_id} not found or not associated with ref_client {ref_client.client_id}, creating new")  # Debugging
#                         try:
#                             item["ref_client"] = ref_client
#                             obj = model_class.objects.create(**item)
#                             keep_ids.append(obj.id)
#                             print(f"Created new {model_class.__name__} with id={obj.id}")  # Debugging
#                         except Exception as e:
#                             print(f"Failed to create {model_class.__name__}: {e}")  # Debugging
#                             continue
#                 else:
#                     try:
#                         print(f"Creating new {model_class.__name__}: {item}")  # Debugging
#                         item["ref_client"] = ref_client
#                         obj = model_class.objects.create(**item)
#                         keep_ids.append(obj.id)
#                         print(f"Created new {model_class.__name__} with id={obj.id}")  # Debugging
#                     except Exception as e:
#                         print(f"Failed to create {model_class.__name__}: {e}")  # Debugging
#                         continue

#             # Delete records not in keep_ids
#             deleted = model_class.objects.filter(ref_client=ref_client).exclude(id__in=keep_ids).delete()
#             print(f"Deleted {deleted[0]} {model_class.__name__} records not in {keep_ids}")  # Debugging

#         # Update Passports
#         update_nested(
#             ClientPassport,
#             passports_data,
#             instance,
#             file_field="passport_file",
#             file_key_template="client_passport[{}][passport_file]"
#         )

#         # Update Visas
#         update_nested(
#             ClientVisa,
#             visas_data,
#             instance,
#             file_field="passport_size_photograph",
#             file_key_template="client_visa[{}][passport_size_photograph]",
#             fk_fields={"ref_visa_country": Countries}
#         )

#         # Update Travel Insurance
#         update_nested(
#             ClientTravelInsurance,
#             insurances_data,
#             instance,
#             file_field="insurance_document",
#             file_key_template="travel_insurance[{}][insurance_document]"
#         )

#         # Update Documents
#         update_nested(
#             ClientDocument,
#             docs_data,
#             instance,
#             file_field="other_document",
#             file_key_template="client_documents[{}][other_document]"
#         )

#         # Update Company Associations
#         update_nested(
#             AssocClientCompany,
#             companies_data,
#             instance,
#             fk_fields={"ref_company": Company}
#         )

#         # Update Frequent Flyers
#         update_nested(
#             ClientFrequentFlyer,
#             frequent_flyers_data,
#             instance,
#             fk_fields={"ref_airline": Airlines}
#         )

#         # Update Family Passports (fam_passport)
#         keep_ids = []
#         for i, pd in enumerate(fam_passports_data):
#             print(f"Processing fam_passport[{i}]: {pd}")  # Debugging
#             if is_empty(pd):
#                 print(f"Skipping empty fam_passport[{i}]")  # Debugging
#                 continue
#             pd = self.clean_row(pd, file_map={"passport_file": f"fam_passport[{i}][fam_passport_file]"})
#             pd["passport_no"] = self.clean_str(pd.get("fam_passport_no") or pd.get("passport_no"))
#             pd["passport_expiry_date"] = self.clean_date(pd.get("fam_passport_expiry_date") or pd.get("passport_expiry_date"))
#             obj_id = pd.pop("id", None)
#             if obj_id:
#                 try:
#                     obj_id = int(obj_id)
#                 except (ValueError, TypeError):
#                     print(f"Invalid ID for fam_passport[{i}]: {obj_id}, treating as new")  # Debugging
#                     obj_id = None
#             # Handle file field
#             file_key = f"fam_passport[{i}][fam_passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 pd["passport_file"] = self.context["request"].FILES[file_key]
#                 print(f"Found passport_file for fam_passport[{i}]: {file_key}")  # Debugging
#             elif "passport_file" in pd and pd["passport_file"] in ["", "null", None]:
#                 pd["passport_file"] = None
#                 print(f"Cleared passport_file for fam_passport[{i}]")  # Debugging
#             # Skip if no meaningful data
#             if not (pd.get("passport_no") or pd.get("passport_expiry_date") or pd.get("passport_file")):
#                 print(f"Skipping fam_passport[{i}] due to no meaningful data")  # Debugging
#                 continue
#             if obj_id:
#                 try:
#                     obj = ClientPassport.objects.get(id=obj_id, ref_client=instance)
#                     print(f"Updating fam_passport id={obj_id}: {pd}")  # Debugging
#                     for k, v in pd.items():
#                         if k != "passport_file" or v is not None:
#                             setattr(obj, k, v)
#                     obj.save()
#                     keep_ids.append(obj_id)
#                 except ClientPassport.DoesNotExist:
#                     print(f"fam_passport id={obj_id} not found or not associated with ref_client {instance.client_id}, creating new")  # Debugging
#                     try:
#                         pd["ref_client"] = instance
#                         obj = ClientPassport.objects.create(**pd)
#                         keep_ids.append(obj.id)
#                         print(f"Created new fam_passport with id={obj.id}")  # Debugging
#                     except Exception as e:
#                         print(f"Failed to create fam_passport: {e}")  # Debugging
#                         continue
#             else:
#                 try:
#                     print(f"Creating new fam_passport: {pd}")  # Debugging
#                     pd["ref_client"] = instance
#                     obj = ClientPassport.objects.create(**pd)
#                     keep_ids.append(obj.id)
#                     print(f"Created new fam_passport with id={obj.id}")  # Debugging
#                 except Exception as e:
#                     print(f"Failed to create fam_passport: {e}")  # Debugging
#                     continue
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted fam_passport records not in {keep_ids}")  # Debugging

#         # Update Relations
#         keep_ids = []
#         for i, rel in enumerate(relations_data):
#             print(f"Processing relationsWithOthers[{i}]: {rel}")  # Debugging
#             if is_empty(rel):
#                 print(f"Skipping empty relationsWithOthers[{i}]")  # Debugging
#                 continue
#             rel = self.clean_row(rel)
#             obj_id = rel.pop("id", None)
#             if obj_id:
#                 try:
#                     obj_id = int(obj_id)
#                 except (ValueError, TypeError):
#                     print(f"Invalid ID for relationsWithOthers[{i}]: {obj_id}, treating as new")  # Debugging
#                     obj_id = None
#             from_client_id = rel.get("from_client")
#             to_client_id = rel.get("to_client")
#             if from_client_id and to_client_id:
#                 try:
#                     from_client = Client.objects.get(id=from_client_id)
#                     to_client = Client.objects.get(id=to_client_id)
#                     rel["from_client"] = from_client
#                     rel["to_client"] = to_client
#                     if obj_id:
#                         try:
#                             obj = ClientRelation.objects.get(id=obj_id, from_client=from_client)
#                             print(f"Updating ClientRelation id={obj_id}: {rel}")  # Debugging
#                             for k, v in rel.items():
#                                 setattr(obj, k, v)
#                             obj.save()
#                             keep_ids.append(obj_id)
#                         except ClientRelation.DoesNotExist:
#                             print(f"ClientRelation id={obj_id} not found, creating new")  # Debugging
#                             try:
#                                 obj = ClientRelation.objects.create(**rel)
#                                 keep_ids.append(obj.id)
#                                 print(f"Created new ClientRelation with id={obj.id}")  # Debugging
#                             except Exception as e:
#                                 print(f"Failed to create ClientRelation: {e}")  # Debugging
#                                 continue
#                     else:
#                         try:
#                             print(f"Creating new ClientRelation: {rel}")  # Debugging
#                             obj = ClientRelation.objects.create(**rel)
#                             keep_ids.append(obj.id)
#                             print(f"Created new ClientRelation with id={obj.id}")  # Debugging
#                         except Exception as e:
#                             print(f"Failed to create ClientRelation: {e}")  # Debugging
#                             continue
#                 except Client.DoesNotExist:
#                     print(f"Skipping ClientRelation due to invalid client IDs: {rel}")  # Debugging
#                     continue
#         ClientRelation.objects.filter(from_client=instance).exclude(id__in=keep_ids).delete()
#         print(f"Deleted ClientRelation records not in {keep_ids}")  # Debugging

#         return instance

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(),
#         required=False,
#         allow_null=True
#     )
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True
#     )
#     preferred_airline = AirlinesSerializer(read_only=True)
#     ref_visa_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )

#     # --- Nested serializers (all many=True) ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
#             "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_row(self, row, file_map=None):
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         if "id" in cleaned and (cleaned["id"] is None or str(cleaned["id"]).strip() == ""):
#             cleaned.pop("id")

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def clean_str(self, value):
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def safe_fk(self, model_class, value):
#         if not value:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             value_int = int(value)
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         # Protect file fields from unintentional clearing
#         file_fields = ["aadhaar_card_file", "pan_card_file"]
#         for field in file_fields:
#             if field in data and data[field] in ["", "null", None]:
#                 data.pop(field)  # Preserve existing file

#         # Unwrap single-item lists for scalar fields
#         def unwrap_scalars(data, skip_keys):
#             for k, v in data.items():
#                 if k in skip_keys:
#                     continue
#                 if isinstance(v, list) and len(v) == 1:
#                     data[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     data[k] = None
#             return data

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         # Normalize nested fields
#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]
#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         # --- Uniqueness checks ---
#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:  # Only at create
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         # --- Clean top-level dates ---
#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         # --- Helper: Expand passports with multiple values ---
#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # --- Nested: Passport (Primary client) ---
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         expanded_passports = []
#         for i, p in enumerate(data.get("client_passport", [])):
#             if isinstance(p, dict):
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     p = self.clean_row(p, file_map={"passport_file": f"client_passport[{i}][passport_file]"})
#                     if "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                         p.pop("passport_file")  # Preserve existing file
#                     expanded_passports.append(p)

#         for p in expanded_passports:
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         # --- Nested: Familiar Passports ---
#         for i, p in enumerate(data.get("fam_passport", [])):
#             if isinstance(p, dict):
#                 if "fam_passport_no" in p:
#                     p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
#                 if "fam_passport_expiry_date" in p:
#                     p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))
#                 file_key = f"fam_passport[{i}][fam_passport_file]"
#                 if file_key in files:
#                     p["fam_passport_file"] = files[file_key]
#                 elif "fam_passport_file" in p and p["fam_passport_file"] in ["", "null", None]:
#                     p.pop("fam_passport_file")  # Preserve existing file

#         # --- Nested: Relations with Others ---
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict) and "relation_with_other_client_code" in r:
#                 r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

#         # --- Nested: Companies ---
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None

#         # --- Nested: Documents ---
#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 file_key = f"client_documents[{i}][other_document]"
#                 if file_key in files:
#                     d["other_document"] = files[file_key]
#                 elif "other_document" in d and d["other_document"] in ["", "null", None]:
#                     d.pop("other_document")  # Preserve existing file
#                 if "other_document_name" in d:
#                     d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         # --- Nested: Frequent Flyers ---
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # --- Nested: Visa ---
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None

#         # --- Nested: Travel Insurance ---
#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))

#         # --- Nested: Family Members ---
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 # Handle family member passports
#                 expanded_fam_passports = []
#                 for pi, p in enumerate(fam.get("fam_passport", [])):
#                     if isinstance(p, dict):
#                         if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                             expanded_fam_passports.extend(expand_passports(p))
#                         else:
#                             p = self.clean_row(p, file_map={"passport_file": f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"})
#                             if "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                                 p.pop("passport_file")  # Preserve existing file
#                             expanded_fam_passports.append(p)

#                 for p in expanded_fam_passports:
#                     if isinstance(p.get("passport_no"), list):
#                         p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                     if isinstance(p.get("passport_expiry_date"), list):
#                         p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                     if "passport_no" in p:
#                         p["passport_no"] = self.clean_str(p.get("passport_no"))
#                     if "passport_expiry_date" in p:
#                         p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                 fam["fam_passport"] = expanded_fam_passports

#         return data

#     # ---------------- Serializer Methods ----------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
#         def unwrap(value):
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # --- Pop related data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # --- Pop FKs ---
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         # Normalize country_code
#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         validated_data["country_code"] = country_code_instance
#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             if file_field in request_files:
#                 validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # --- Assign FK fields after creation ---
#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#         if country:
#             client.residential_country = country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#         if state:
#             client.residential_state = state if isinstance(state, State) else self.safe_fk(state, State)
#         if city:
#             client.residential_city = city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#         client.save()

#         # --- Related: Passports ---
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"]:
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # --- Related: Visas ---
#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # --- Related: Travel Insurance ---
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"]:
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # --- Other Documents ---
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         # --- Companies ---
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         # --- Frequent Flyers ---
#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # --- Family Members ---
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(
#                 **fam_data,
#                 created_by=self.context["request"].user if self.context.get("request") else None,
#                 created_at=timezone.now()
#             )
#             created_family_members[fam_index] = family_client

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue
#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)
#                 if f_passport_no or f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         # --- Extra Relations ---
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue
#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")
#             if from_index is None or to_index is None:
#                 continue
#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue
#             try:
#                 target_client = created_family_members.get(int(to_index)) or Client.objects.get(pk=int(to_index))
#             except Client.DoesNotExist:
#                 continue
#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )

#         return client

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):

#         # --- Pop nested data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         validated_data.pop("family_members", None)  # Not processed here
#         validated_data.pop("familyMembers", None)
#         validated_data.pop("fam_passport", None)
#         validated_data.pop("relationsWithOthers", None)

#         # --- Handle FK fields ---
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }
#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 model_class = fk_models.get(fk_field)
#                 if fk_value is None:
#                     validated_data[f"{fk_field}_id"] = None
#                 else:
#                     if isinstance(fk_value, dict):
#                         validated_data[f"{fk_field}_id"] = fk_value.get("id")
#                     elif isinstance(fk_value, model_class):
#                         validated_data[f"{fk_field}_id"] = fk_value.id
#                     else:
#                         try:
#                             fk_instance = model_class.objects.get(id=int(fk_value))
#                             validated_data[f"{fk_field}_id"] = fk_instance.id
#                         except (ValueError, TypeError, model_class.DoesNotExist):
#                             validated_data[f"{fk_field}_id"] = None

#         # --- Normalize fields ---
#         if "client_code" in validated_data:
#             validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         if "dob" in validated_data:
#             validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         if "anniversary_date" in validated_data:
#             validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # --- Handle uploaded files ---
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data and validated_data[field] in ["", "null", None]:
#                 setattr(instance, field, None)
#                 validated_data.pop(field)  # Remove to prevent further processing
#             else:
#                 validated_data.pop(field, None)  # Preserve existing file

#         # --- Update main client fields ---
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         instance.save()

#         # --- Helper to skip empty dicts ---
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # --- Passports ---
#         keep_ids = []
#         for i, pd in enumerate(passports_data):
#             if is_empty(pd):
#                 continue
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             file_key = f"client_passport[{i}][passport_file]"
#             if file_key in files:
#                 pd["passport_file"] = files[file_key]
#             elif "passport_file" in pd and pd["passport_file"] in ["", "null", None]:
#                 pd["passport_file"] = None
#             else:
#                 pd.pop("passport_file", None)  # Preserve existing file
#             obj_id = pd.pop("id", None)
#             if obj_id:
#                 ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientPassport.objects.update_or_create(ref_client=instance, **pd)
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Visas ---
#         keep_ids = []
#         for i, vd in enumerate(visas_data):
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_val = vd.pop("ref_visa_country", None)
#             if country_val is None:
#                 vd["ref_visa_country_id"] = None
#             else:
#                 if isinstance(country_val, dict):
#                     vd["ref_visa_country_id"] = country_val.get("id")
#                 elif isinstance(country_val, Countries):
#                     vd["ref_visa_country_id"] = country_val.id
#                 else:
#                     try:
#                         vd["ref_visa_country_id"] = int(country_val)
#                     except (ValueError, TypeError):
#                         vd["ref_visa_country_id"] = None
#             file_key = f"client_visa[{i}][passport_size_photograph]"
#             if file_key in files:
#                 vd["passport_size_photograph"] = files[file_key]
#             elif "passport_size_photograph" in vd and vd["passport_size_photograph"] in ["", "null", None]:
#                 vd["passport_size_photograph"] = None
#             else:
#                 vd.pop("passport_size_photograph", None)
#             obj_id = vd.pop("id", None)
#             if obj_id:
#                 ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientVisa.objects.update_or_create(ref_client=instance, **vd)
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Travel Insurance ---
#         keep_ids = []
#         for i, ins in enumerate(insurances_data):
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             file_key = f"travel_insurance[{i}][insurance_document]"
#             if file_key in files:
#                 ins["insurance_document"] = files[file_key]
#             elif "insurance_document" in ins and ins["insurance_document"] in ["", "null", None]:
#                 ins["insurance_document"] = None
#             else:
#                 ins.pop("insurance_document", None)
#             obj_id = ins.pop("id", None)
#             if obj_id:
#                 ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientTravelInsurance.objects.update_or_create(ref_client=instance, **ins)
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Documents ---
#         keep_ids = []
#         for i, doc in enumerate(docs_data):
#             if is_empty(doc):
#                 continue
#             file_key = f"client_documents[{i}][other_document]"
#             if file_key in files:
#                 doc["other_document"] = files[file_key]
#             elif "other_document" in doc and doc["other_document"] in ["", "null", None]:
#                 doc["other_document"] = None
#             else:
#                 doc.pop("other_document", None)
#             obj_id = doc.pop("id", None)
#             if obj_id:
#                 ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientDocument.objects.update_or_create(ref_client=instance, **doc)
#                 keep_ids.append(obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Company Associations ---
#         keep_ids = []
#         for i, comp in enumerate(companies_data):
#             if is_empty(comp):
#                 continue
#             ref_company = comp.pop("ref_company", None)
#             if ref_company is None:
#                 comp["ref_company_id"] = None
#             else:
#                 if isinstance(ref_company, dict):
#                     comp["ref_company_id"] = ref_company.get("id")
#                 elif isinstance(ref_company, Company):
#                     comp["ref_company_id"] = ref_company.id
#                 else:
#                     try:
#                         comp["ref_company_id"] = int(ref_company)
#                     except (ValueError, TypeError):
#                         comp["ref_company_id"] = None
#             obj_id = comp.pop("id", None)
#             if obj_id:
#                 AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = AssocClientCompany.objects.update_or_create(ref_client=instance, **comp)
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Frequent Flyers ---
#         keep_ids = []
#         for i, ff in enumerate(frequent_flyers_data):
#             if is_empty(ff):
#                 continue
#             airline_val = ff.pop("ref_airline", None)
#             if airline_val is None:
#                 ff["ref_airline_id"] = None
#             else:
#                 if isinstance(airline_val, dict):
#                     ff["ref_airline_id"] = airline_val.get("id")
#                 elif isinstance(airline_val, Airlines):
#                     ff["ref_airline_id"] = airline_val.id
#                 else:
#                     try:
#                         ff["ref_airline_id"] = int(airline_val)
#                     except (ValueError, TypeError):
#                         ff["ref_airline_id"] = None
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             obj_id = ff.pop("id", None)
#             if obj_id:
#                 ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(ref_client=instance, **ff)
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(),
#         required=False,
#         allow_null=True
#     )
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True
#     )
#     preferred_airline = AirlinesSerializer(read_only=True)
#     ref_visa_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )

#     # --- Nested serializers (all many=True) ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
#             "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport", "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code or None

#     def clean_date(self, value):
#         if not value or str(value).strip() == "":
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_row(self, row, file_map=None):
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         if "id" in cleaned and (cleaned["id"] is None or str(cleaned["id"]).strip() == ""):
#             cleaned.pop("id")

#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]
#                 elif field in cleaned and cleaned[field] in ["", "null", None]:
#                     cleaned.pop(field)  # Prevent setting file to None

#         return cleaned

#     def clean_str(self, value):
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and v.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def safe_fk(self, model_class, value):
#         if not value:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             value_int = int(value)
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         # Protect top-level file fields from being cleared
#         file_fields = ["aadhaar_card_file", "pan_card_file"]
#         for field in file_fields:
#             if field in data and data[field] in ["", "null", None]:
#                 data.pop(field)  # Preserve existing file

#         # Unwrap single-item lists for scalar fields
#         def unwrap_scalars(data, skip_keys):
#             for k, v in data.items():
#                 if k in skip_keys:
#                     continue
#                 if isinstance(v, list) and len(v) == 1:
#                     data[k] = v[0]
#                 elif isinstance(v, list) and len(v) == 0:
#                     data[k] = None
#             return data

#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#                 # Protect file fields in nested dicts
#                 if k in ["passport_file", "other_document", "passport_size_photograph", "insurance_document", "fam_passport_file"]:
#                     if v in ["", "null", None]:
#                         d.pop(k)
#             return d

#         # Normalize nested fields and protect their file fields
#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]
#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         # --- Uniqueness checks ---
#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:  # Only at create
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         # --- Clean top-level dates ---
#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         # --- Helper: Expand passports with multiple values ---
#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # --- Nested: Passport (Primary client) ---
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         expanded_passports = []
#         for i, p in enumerate(data.get("client_passport", [])):
#             if isinstance(p, dict):
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     p = self.clean_row(p, file_map={"passport_file": f"client_passport[{i}][passport_file]"})
#                     expanded_passports.append(p)

#         for p in expanded_passports:
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         # --- Nested: Familiar Passports ---
#         for i, p in enumerate(data.get("fam_passport", [])):
#             if isinstance(p, dict):
#                 if "fam_passport_no" in p:
#                     p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
#                 if "fam_passport_expiry_date" in p:
#                     p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))

#         # --- Nested: Relations with Others ---
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict) and "relation_with_other_client_code" in r:
#                 r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

#         # --- Nested: Companies ---
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null"]:
#                     c["primary_company"] = None

#         # --- Nested: Documents ---
#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 if "other_document_name" in d:
#                     d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         # --- Nested: Frequent Flyers ---
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # --- Nested: Visa ---
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None

#         # --- Nested: Travel Insurance ---
#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))

#         # --- Nested: Family Members ---
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 # Handle family member passports
#                 expanded_fam_passports = []
#                 for pi, p in enumerate(fam.get("fam_passport", [])):
#                     if isinstance(p, dict):
#                         if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                             expanded_fam_passports.extend(expand_passports(p))
#                         else:
#                             p = self.clean_row(p, file_map={"passport_file": f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"})
#                             expanded_fam_passports.append(p)

#                 for p in expanded_fam_passports:
#                     if isinstance(p.get("passport_no"), list):
#                         p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                     if isinstance(p.get("passport_expiry_date"), list):
#                         p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                     if "passport_no" in p:
#                         p["passport_no"] = self.clean_str(p.get("passport_no"))
#                     if "passport_expiry_date" in p:
#                         p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                 fam["fam_passport"] = expanded_fam_passports

#         return data

#     # ---------------- Serializer Methods ----------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
#         def unwrap(value):
#             if isinstance(value, list):
#                 value = value if value else None
#             return value if value not in ["", "null"] else None

#         # --- Pop related data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # --- Pop FKs ---
#         airline = validated_data.pop("ref_preferred_airline", None)
#         country = validated_data.pop("residential_country", None)
#         state = validated_data.pop("residential_state", None)
#         city = validated_data.pop("residential_city", None)
#         country_code = validated_data.pop("country_code", None)

#         # Normalize country_code
#         if country_code:
#             if isinstance(country_code, dict):
#                 country_code_instance = Countries.objects.get(id=country_code["id"])
#             elif isinstance(country_code, int):
#                 country_code_instance = Countries.objects.get(id=country_code)
#             elif isinstance(country_code, Countries):
#                 country_code_instance = country_code
#             else:
#                 country_code_instance = None
#         else:
#             country_code_instance = None

#         validated_data["country_code"] = country_code_instance
#         validated_data["residential_country"] = self.safe_fk(unwrap(validated_data.get("residential_country")), Countries)
#         validated_data["residential_state"] = self.safe_fk(unwrap(validated_data.get("residential_state")), State)
#         validated_data["residential_city"] = self.safe_fk(unwrap(validated_data.get("residential_city")), Cities)
#         validated_data["ref_preferred_airline"] = self.safe_fk(unwrap(validated_data.get("ref_preferred_airline")), Airlines)
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             if file_field in request_files:
#                 validated_data[file_field] = request_files.get(file_field)

#         client = Client.objects.create(**validated_data)

#         # --- Assign FK fields after creation ---
#         if country_code_instance:
#             client.country_code = country_code_instance
#         if airline:
#             client.ref_preferred_airline = airline if isinstance(airline, Airlines) else self.safe_fk(airline, Airlines)
#         if country:
#             client.residential_country = country if isinstance(country, Countries) else self.safe_fk(country, Countries)
#         if state:
#             client.residential_state = state if isinstance(state, State) else self.safe_fk(state, State)
#         if city:
#             client.residential_city = city if isinstance(city, Cities) else self.safe_fk(city, Cities)
#         client.save()

#         # --- Related: Passports ---
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"]:
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # --- Related: Visas ---
#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value:
#                 if isinstance(country_value, (str, int)):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value)
#                 elif isinstance(country_value, dict):
#                     vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # --- Related: Travel Insurance ---
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"]:
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # --- Other Documents ---
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         # --- Companies ---
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.get("ref_company")
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#             except Company.DoesNotExist:
#                 continue
#             cd["ref_company_id"] = company_instance.id
#             cd.pop("ref_company", None)
#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         # --- Frequent Flyers ---
#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.get("ref_airline")
#             if not airline_value:
#                 continue
#             try:
#                 airline_instance = Airlines.objects.get(airline=airline_value)
#             except Airlines.DoesNotExist:
#                 continue
#             flyer_data["ref_airline_id"] = airline_instance.id
#             flyer_data.pop("ref_airline", None)
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # --- Family Members ---
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or client.residential_country,
#                 "residential_state": self.safe_fk(State, fam.get("residential_state")) or client.residential_state,
#                 "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(
#                 **fam_data,
#                 created_by=self.context["request"].user if self.context.get("request") else None,
#                 created_at=timezone.now()
#             )
#             created_family_members[fam_index] = family_client

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue
#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)
#                 if f_passport_no or f_passport_expiry_date:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client

#         # --- Extra Relations ---
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue
#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")
#             if from_index is None or to_index is None:
#                 continue
#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue
#             try:
#                 target_client = created_family_members.get(int(to_index)) or Client.objects.get(pk=int(to_index))
#             except Client.DoesNotExist:
#                 continue
#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )

#         return client

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):

#         # --- Pop nested data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         validated_data.pop("family_members", None)  # Not processed here
#         validated_data.pop("familyMembers", None)
#         validated_data.pop("fam_passport", None)
#         validated_data.pop("relationsWithOthers", None)

#         # --- Handle FK fields ---
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }
#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 model_class = fk_models.get(fk_field)
#                 if fk_value is None:
#                     validated_data[f"{fk_field}_id"] = None
#                 else:
#                     if isinstance(fk_value, dict):
#                         validated_data[f"{fk_field}_id"] = fk_value.get("id")
#                     elif isinstance(fk_value, model_class):
#                         validated_data[f"{fk_field}_id"] = fk_value.id
#                     else:
#                         try:
#                             fk_instance = model_class.objects.get(id=int(fk_value))
#                             validated_data[f"{fk_field}_id"] = fk_instance.id
#                         except (ValueError, TypeError, model_class.DoesNotExist):
#                             validated_data[f"{fk_field}_id"] = None

#         # --- Normalize fields ---
#         if "client_code" in validated_data:
#             validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         if "dob" in validated_data:
#             validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         if "anniversary_date" in validated_data:
#             validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # --- Handle uploaded files ---
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 if validated_data[field] is None:  # Only clear if explicitly null
#                     setattr(instance, field, None)
#                 validated_data.pop(field)  # Remove to prevent further processing

#         # --- Update main client fields ---
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         instance.save()

#         # --- Helper to skip empty dicts ---
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # --- Passports ---
#         keep_ids = []
#         for i, pd in enumerate(passports_data):
#             if is_empty(pd):
#                 continue
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             file_key = f"client_passport[{i}][passport_file]"
#             if file_key in files:
#                 pd["passport_file"] = files[file_key]
#             elif "passport_file" in pd and pd["passport_file"] is None:
#                 pd["passport_file"] = None  # Only clear if explicitly null
#             else:
#                 pd.pop("passport_file", None)  # Preserve existing file
#             obj_id = pd.pop("id", None)
#             if obj_id:
#                 ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientPassport.objects.update_or_create(ref_client=instance, **pd)
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Visas ---
#         keep_ids = []
#         for i, vd in enumerate(visas_data):
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_val = vd.pop("ref_visa_country", None)
#             if country_val is None:
#                 vd["ref_visa_country_id"] = None
#             else:
#                 if isinstance(country_val, dict):
#                     vd["ref_visa_country_id"] = country_val.get("id")
#                 elif isinstance(country_val, Countries):
#                     vd["ref_visa_country_id"] = country_val.id
#                 else:
#                     try:
#                         vd["ref_visa_country_id"] = int(country_val)
#                     except (ValueError, TypeError):
#                         vd["ref_visa_country_id"] = None
#             file_key = f"client_visa[{i}][passport_size_photograph]"
#             if file_key in files:
#                 vd["passport_size_photograph"] = files[file_key]
#             elif "passport_size_photograph" in vd and vd["passport_size_photograph"] is None:
#                 vd["passport_size_photograph"] = None
#             else:
#                 vd.pop("passport_size_photograph", None)
#             obj_id = vd.pop("id", None)
#             if obj_id:
#                 ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientVisa.objects.update_or_create(ref_client=instance, **vd)
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Travel Insurance ---
#         keep_ids = []
#         for i, ins in enumerate(insurances_data):
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             file_key = f"travel_insurance[{i}][insurance_document]"
#             if file_key in files:
#                 ins["insurance_document"] = files[file_key]
#             elif "insurance_document" in ins and ins["insurance_document"] is None:
#                 ins["insurance_document"] = None
#             else:
#                 ins.pop("insurance_document", None)
#             obj_id = ins.pop("id", None)
#             if obj_id:
#                 ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientTravelInsurance.objects.update_or_create(ref_client=instance, **ins)
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Documents ---
#         keep_ids = []
#         for i, doc in enumerate(docs_data):
#             if is_empty(doc):
#                 continue
#             file_key = f"client_documents[{i}][other_document]"
#             if file_key in files:
#                 doc["other_document"] = files[file_key]
#             elif "other_document" in doc and doc["other_document"] is None:
#                 doc["other_document"] = None
#             else:
#                 doc.pop("other_document", None)
#             obj_id = doc.pop("id", None)
#             if obj_id:
#                 ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientDocument.objects.update_or_create(ref_client=instance, **doc)
#                 keep_ids.append(obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Company Associations ---
#         keep_ids = []
#         for i, comp in enumerate(companies_data):
#             if is_empty(comp):
#                 continue
#             ref_company = comp.pop("ref_company", None)
#             if ref_company is None:
#                 comp["ref_company_id"] = None
#             else:
#                 if isinstance(ref_company, dict):
#                     comp["ref_company_id"] = ref_company.get("id")
#                 elif isinstance(ref_company, Company):
#                     comp["ref_company_id"] = ref_company.id
#                 else:
#                     try:
#                         comp["ref_company_id"] = int(ref_company)
#                     except (ValueError, TypeError):
#                         comp["ref_company_id"] = None
#             obj_id = comp.pop("id", None)
#             if obj_id:
#                 AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = AssocClientCompany.objects.update_or_create(ref_client=instance, **comp)
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # --- Frequent Flyers ---
#         keep_ids = []
#         for i, ff in enumerate(frequent_flyers_data):
#             if is_empty(ff):
#                 continue
#             airline_val = ff.pop("ref_airline", None)
#             if airline_val is None:
#                 ff["ref_airline_id"] = None
#             else:
#                 if isinstance(airline_val, dict):
#                     ff["ref_airline_id"] = airline_val.get("id")
#                 elif isinstance(airline_val, Airlines):
#                     ff["ref_airline_id"] = airline_val.id
#                 else:
#                     try:
#                         ff["ref_airline_id"] = int(airline_val)
#                     except (ValueError, TypeError):
#                         ff["ref_airline_id"] = None
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             obj_id = ff.pop("id", None)
#             if obj_id:
#                 ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(ref_client=instance, **ff)
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         return instance

# def unwrap_scalars(data, skip_keys=None):
#     """Unwrap single-item lists for scalar fields, preserving None."""
#     result = data.copy()
#     for key, value in data.items():
#         if skip_keys and key in skip_keys:
#             continue
#         if isinstance(value, list):
#             if len(value) == 1:
#                 result[key] = value[0] if value[0] not in ["", "null"] else None
#             elif len(value) == 0:
#                 result[key] = None
#         elif value in ["", "null"]:
#             result[key] = None
#     return result

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Foreign keys ---
#     country_code = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(),
#         required=False,
#         allow_null=True
#     )
#     country_code_data = CountrySerializer(source="country_code", read_only=True)

#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True
#     )
#     preferred_airline = AirlinesSerializer(read_only=True)

#     ref_visa_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), required=False, allow_null=True
#     )
#     ref_visa_country_data = CountrySerializer(source="ref_visa_country", read_only=True)

#     # --- Nested serializers (all many=True) ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "country_code_data", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark", "occupation",
#             "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "preferred_airline", "star_rating", "stay_preference", "room_preference",
#             "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference", "ref_visa_country",
#             "ref_visa_country_data", "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "fam_passport",
#             "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     def _normalize_code(self, code: str | None) -> str | None:
#         code = (code or "").strip()
#         return code.upper() if code else None

#     def clean_date(self, value):
#         if not value or str(value).strip() in ["", "null"]:
#             return None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value, "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_row(self, row, file_map=None):
#         cleaned = {}
#         for k, v in row.items():
#             if v in ["", [], [""]]:
#                 cleaned[k] = None
#             elif isinstance(v, list):
#                 cleaned[k] = v[0] if len(v) == 1 else v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     if isinstance(parsed, list) and len(parsed) == 1:
#                         cleaned[k] = parsed[0]
#                     else:
#                         cleaned[k] = parsed
#                 except Exception:
#                     cleaned[k] = v
#             else:
#                 cleaned[k] = v

#         # Remove blank 'id'
#         if "id" in cleaned and (cleaned["id"] is None or str(cleaned["id"]).strip() == ""):
#             cleaned.pop("id")

#         # Handle file uploads
#         if file_map and self.context.get("request"):
#             request_files = self.context["request"].FILES
#             for field, req_field in file_map.items():
#                 if req_field in request_files:
#                     cleaned[field] = request_files[req_field]

#         return cleaned

#     def clean_str(self, value):
#         if value in ["", None, [], [""]]:
#             return None
#         if isinstance(value, list):
#             if len(value) == 1:
#                 value = value[0]
#             else:
#                 return " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 if isinstance(parsed, list) and len(parsed) == 1:
#                     value = parsed[0]
#                 else:
#                     value = parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def safe_fk(self, value, model_class):
#         if value in ["", "null", None]:
#             return None
#         try:
#             if isinstance(value, int):
#                 return value
#             if isinstance(value, str):
#                 value_int = int(value)
#             elif isinstance(value, dict):
#                 value_int = value.get("id")
#             else:
#                 return None
#             if model_class.objects.filter(id=value_int).exists():
#                 return value_int
#             return None
#         except (ValueError, TypeError):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         normalized = []
#         if not value:
#             return []
#         if isinstance(value, str):
#             value = [value]
#         for v in value:
#             key = None
#             if isinstance(v, dict):
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 normalized.append(str(key).lower().strip())
#         return normalized

#     def extract_family_passports(self, fam):
#         for key in ["fam_passport", "client_passport", "passports"]:
#             value = fam.get(key)
#             if value:
#                 if isinstance(value, list):
#                     return value
#                 elif isinstance(value, dict):
#                     return [value]
#         return []

#     # ---------------- Validate ----------------
#     def validate(self, data):
#         data = unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])

#         def normalize_nested_dict(d):
#             for k, v in list(d.items()):
#                 if isinstance(v, list):
#                     if len(v) == 1:
#                         d[k] = v[0]
#                     elif len(v) == 0:
#                         d[k] = None
#                 if v is None:
#                     d[k] = None
#             return d

#         # Normalize nested fields
#         nested_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ]
#         for field in nested_fields:
#             val = data.get(field, [])
#             if val is None:
#                 data[field] = []
#                 continue
#             flat_list = []
#             for item in val:
#                 if isinstance(item, list):
#                     flat_list.extend(item)
#                 else:
#                     flat_list.append(item)
#             normalized_list = []
#             for item in flat_list:
#                 if isinstance(item, dict):
#                     normalized_list.append(normalize_nested_dict(item))
#                 elif item is None:
#                     normalized_list.append(None)
#             data[field] = normalized_list

#         # Uniqueness checks
#         main_code = self._normalize_code(data.get("client_code"))
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{main_code}' already exists."})

#         if not self.instance:  # Only at create
#             for fam in data.get("family_members", []):
#                 fam_code = self._normalize_code(fam.get("clientCode"))
#                 if fam_code:
#                     qs = Client.objects.filter(client_code=fam_code)
#                     if qs.exists():
#                         raise serializers.ValidationError({"family_member_client_code": f"Client code '{fam_code}' already exists."})

#         # Clean top-level dates, allowing None
#         if "dob" in data:
#             data["dob"] = self.clean_date(data.get("dob"))
#         if "anniversary_date" in data:
#             data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

#         # Helper: Expand passports with multiple values
#         def expand_passports(passport_dict):
#             if not passport_dict:
#                 return []
#             max_len = max(len(v) if isinstance(v, list) else 1 for v in passport_dict.values() if v is not None)
#             results = []
#             for i in range(max_len):
#                 record = {}
#                 for key, value in passport_dict.items():
#                     if isinstance(value, list):
#                         record[key] = value[i] if i < len(value) else None
#                     else:
#                         record[key] = value
#                 results.append(record)
#             return results

#         # Nested: Passport (Primary client)
#         expanded_passports = []
#         for p in data.get("client_passport", []):
#             if isinstance(p, dict):
#                 if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                     expanded_passports.extend(expand_passports(p))
#                 else:
#                     expanded_passports.append(p)
#             else:
#                 continue

#         for i, p in enumerate(expanded_passports):
#             if isinstance(p.get("passport_no"), list):
#                 p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#             if isinstance(p.get("passport_expiry_date"), list):
#                 p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None

#             file_key = f"client_passport[{i}][passport_file]"
#             if self.context.get("request") and file_key in self.context["request"].FILES:
#                 p["passport_file"] = self.context["request"].FILES[file_key]
#             elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                 p["passport_file"] = None

#             if "passport_no" in p:
#                 p["passport_no"] = self.clean_str(p.get("passport_no"))
#             if "passport_expiry_date" in p:
#                 p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#         data["client_passport"] = expanded_passports

#         # Nested: Familiar Passports
#         for i, p in enumerate(data.get("fam_passport", [])):
#             if isinstance(p, dict):
#                 if "fam_passport_no" in p:
#                     p["fam_passport_no"] = self.clean_str(p.get("fam_passport_no"))
#                 if "fam_passport_expiry_date" in p:
#                     p["fam_passport_expiry_date"] = self.clean_date(p.get("fam_passport_expiry_date"))
#                 file_key = f"fam_passport[{i}][fam_passport_file]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     p["fam_passport_passport_file"] = self.context["request"].FILES[file_key]
#                 elif "fam_passport_passport_file" in p and p["fam_passport_passport_file"] in ["", "null", None]:
#                     p["fam_passport_passport_file"] = None

#         # Nested: Relations with Others
#         for r in data.get("relationsWithOthers", []):
#             if isinstance(r, dict) and "relation_with_other_client_code" in r:
#                 r["relation_with_other_client_code"] = self.clean_str(r.get("relation_with_other_client_code"))

#         # Nested: Companies
#         for c in data.get("client_companies", []):
#             if isinstance(c, dict):
#                 if "designation" in c:
#                     c["designation"] = self.clean_str(c.get("designation"))
#                 if "primary_company" in c and c["primary_company"] in ["", "null", None]:
#                     c["primary_company"] = None

#         # Nested: Documents
#         for i, d in enumerate(data.get("client_documents", [])):
#             if isinstance(d, dict):
#                 file_key = f"client_documents[{i}][other_document]"
#                 if self.context.get("request") and file_key in self.context["request"].FILES:
#                     d["other_document"] = self.context["request"].FILES[file_key]
#                 elif "other_document" in d and d["other_document"] in ["", "null", None]:
#                     d["other_document"] = None
#                 if "other_document_name" in d:
#                     d["other_document_name"] = self.clean_str(d.get("other_document_name"))

#         # Nested: Frequent Flyers
#         for f in data.get("client_frequent_flyers", []):
#             if isinstance(f, dict):
#                 if "ff_no" in f:
#                     f["ff_no"] = self.clean_str(f.get("ff_no"))
#                 if "ref_airline" in f and f["ref_airline"] in ["", "null", None]:
#                     f["ref_airline"] = None

#         # Nested: Visa
#         for v in data.get("client_visa", []):
#             if isinstance(v, dict):
#                 if "visa_from_date" in v:
#                     v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
#                 if "visa_to_date" in v:
#                     v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))
#                 if "ref_visa_country" in v and v["ref_visa_country"] in ["", "null", None]:
#                     v["ref_visa_country"] = None

#         # Nested: Travel Insurance
#         for t in data.get("travel_insurance", []):
#             if isinstance(t, dict):
#                 if "insurance_from_date" in t:
#                     t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
#                 if "insurance_to_date" in t:
#                     t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))

#         # Nested: Family Members
#         for fam_index, fam in enumerate(data.get("family_members", [])):
#             if isinstance(fam, dict):
#                 if "dob" in fam:
#                     fam["dob"] = self.clean_date(fam.get("dob"))
#                 if "anniversary_date" in fam:
#                     fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
#                 if "clientCode" in fam:
#                     fam["clientCode"] = self._normalize_code(fam.get("clientCode"))
#                 if "residential_country" in fam and fam["residential_country"] in ["", "null", None]:
#                     fam["residential_country"] = None
#                 if "residential_state" in fam and fam["residential_state"] in ["", "null", None]:
#                     fam["residential_state"] = None
#                 if "residential_city" in fam and fam["residential_city"] in ["", "null", None]:
#                     fam["residential_city"] = None

#                 if "fam_passport" in fam:
#                     expanded_fam_passports = []
#                     for p in fam.get("fam_passport", []):
#                         if isinstance(p, dict):
#                             if any(isinstance(v, list) and len(v) > 1 for v in p.values()):
#                                 expanded_fam_passports.extend(expand_passports(p))
#                             else:
#                                 expanded_fam_passports.append(p)
#                         else:
#                             continue

#                     for pi, p in enumerate(expanded_fam_passports):
#                         if isinstance(p.get("passport_no"), list):
#                             p["passport_no"] = p["passport_no"][0] if p["passport_no"] else None
#                         if isinstance(p.get("passport_expiry_date"), list):
#                             p["passport_expiry_date"] = p["passport_expiry_date"][0] if p["passport_expiry_date"] else None
#                         if isinstance(p.get("passport_file"), list):
#                             p["passport_file"] = p["passport_file"][0] if p["passport_file"] else None

#                         file_key = f"family_members[{fam_index}][fam_passport][{pi}][passport_file]"
#                         if self.context.get("request") and file_key in self.context["request"].FILES:
#                             p["passport_file"] = self.context["request"].FILES[file_key]
#                         elif "passport_file" in p and p["passport_file"] in ["", "null", None]:
#                             p["passport_file"] = None

#                         if "passport_no" in p:
#                             p["passport_no"] = self.clean_str(p.get("passport_no"))
#                         if "passport_expiry_date" in p:
#                             p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

#                     fam["fam_passport"] = expanded_fam_passports

#         return data

#     # ---------------- Serializer Methods ----------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data

#     # ---------------- Create ----------------
#     @transaction.atomic
#     def create(self, validated_data):
#         def unwrap(value):
#             if isinstance(value, list):
#                 value = value[0] if value else None
#             return value if value not in ["", "null"] else None

#         # Pop related data
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])
#         relationsWithOthers = validated_data.pop("relationsWithOthers", [])
#         fam_passports = validated_data.pop("fam_passport", [])

#         # Pop FKs
#         fk_fields = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }
#         fk_values = {}
#         for fk_field, model_class in fk_fields.items():
#             fk_values[fk_field] = validated_data.pop(fk_field, None)

#         # Normalize fields
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(validated_data.get("preferred_contact_method"))
#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = 1

#         # Handle file uploads
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for file_field in ["aadhaar_card_file", "pan_card_file"]:
#             if file_field in request_files:
#                 validated_data[file_field] = request_files.get(file_field)
#             elif file_field in validated_data and validated_data[file_field] in ["", "null", None]:
#                 validated_data[file_field] = None

#         # Create main client
#         client = Client.objects.create(**validated_data)

#         # Assign FK fields after creation
#         for fk_field, model_class in fk_fields.items():
#             fk_value = fk_values[fk_field]
#             if fk_value is None:
#                 setattr(client, fk_field, None)
#             else:
#                 if isinstance(fk_value, dict):
#                     fk_value = fk_value.get("id")
#                 if isinstance(fk_value, model_class):
#                     setattr(client, fk_field, fk_value)
#                 elif isinstance(fk_value, (int, str)):
#                     try:
#                         fk_instance = model_class.objects.get(id=int(fk_value))
#                         setattr(client, fk_field, fk_instance)
#                     except (ValueError, TypeError, model_class.DoesNotExist):
#                         setattr(client, fk_field, None)
#                 else:
#                     setattr(client, fk_field, None)

#         client.save()

#         # Related: Passports
#         for pd in passports_data:
#             pd = self.clean_row(pd, file_map={"passport_file": "passport_file"})
#             if not any(pd.values()):
#                 continue
#             pd["passport_no"] = self.clean_str(pd.get("passport_no") or "")
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date") or "")
#             if pd["passport_no"] or pd["passport_expiry_date"] or pd.get("passport_file"):
#                 ClientPassport.objects.create(ref_client=client, **pd)

#         # Related: Visas
#         for vd in visas_data:
#             vd = self.clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_value = vd.pop("ref_visa_country", None)
#             if country_value is None:
#                 vd["ref_visa_country"] = None
#             else:
#                 if isinstance(country_value, (str, int)):
#                     try:
#                         vd["ref_visa_country"] = Countries.objects.get(pk=int(country_value))
#                     except (ValueError, TypeError, Countries.DoesNotExist):
#                         vd["ref_visa_country"] = None
#                 elif isinstance(country_value, dict):
#                     try:
#                         vd["ref_visa_country"] = Countries.objects.get(pk=country_value.get("id"))
#                     except (ValueError, TypeError, Countries.DoesNotExist):
#                         vd["ref_visa_country"] = None
#                 elif isinstance(country_value, Countries):
#                     vd["ref_visa_country"] = country_value
#                 else:
#                     vd["ref_visa_country"] = None
#             if vd.get("visa_from_date") or vd.get("visa_to_date") or vd.get("ref_visa_country") or vd.get("passport_size_photograph"):
#                 ClientVisa.objects.create(ref_client=client, **vd)

#         # Related: Travel Insurance
#         for ins in insurances_data:
#             ins = self.clean_row(ins, file_map={"insurance_document": "insurance_document"})
#             if not any(ins.values()):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             if ins["insurance_from_date"] or ins["insurance_to_date"] or ins.get("insurance_document"):
#                 ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         # Other Documents
#         for doc in docs_data:
#             doc = self.clean_row(doc, file_map={"other_document": "other_document"})
#             if any(doc.values()):
#                 doc["other_document_name"] = self.clean_str(doc.get("other_document_name"))
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         # Related: Companies
#         for cd in companies_data:
#             cd = self.clean_row(cd)
#             if not any(cd.values()):
#                 continue
#             company_name = cd.pop("ref_company", None)
#             if not company_name:
#                 continue
#             try:
#                 company_instance = Company.objects.get(company_name=company_name)
#                 cd["ref_company_id"] = company_instance.id
#                 AssocClientCompany.objects.create(ref_client=client, **cd)
#             except Company.DoesNotExist:
#                 continue

#         # Related: Frequent Flyers
#         for flyer_data in frequent_flyers_data:
#             flyer_data = self.clean_row(flyer_data)
#             if not any(flyer_data.values()):
#                 continue
#             airline_value = flyer_data.pop("ref_airline", None)
#             if not airline_value:
#                 flyer_data["ref_airline_id"] = None
#             else:
#                 try:
#                     if isinstance(airline_value, (str, int)):
#                         airline_instance = Airlines.objects.get(id=int(airline_value))
#                     elif isinstance(airline_value, dict):
#                         airline_instance = Airlines.objects.get(id=airline_value.get("id"))
#                     elif isinstance(airline_value, Airlines):
#                         airline_instance = airline_value
#                     else:
#                         airline_instance = None
#                     flyer_data["ref_airline_id"] = airline_instance.id if airline_instance else None
#                 except (ValueError, TypeError, Airlines.DoesNotExist):
#                     flyer_data["ref_airline_id"] = None
#             flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
#             if flyer_data.get("ff_no") or flyer_data.get("ref_airline_id"):
#                 ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

#         # Family Members
#         meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

#         def is_blank_field(value):
#             return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

#         prev_family_client = None
#         created_family_members = {}

#         for fam_index, fam in enumerate(family_members_data):
#             if not isinstance(fam, dict):
#                 try:
#                     fam = ast.literal_eval(fam)
#                 except Exception:
#                     continue
#             if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
#                 continue

#             fam_code = self._normalize_code(fam.get("clientCode"))
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": 1,
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation"),
#                 "client_first_name": fam.get("firstName"),
#                 "client_middle_name": fam.get("middleName"),
#                 "client_last_name": fam.get("lastName"),
#                 "relation": fam.get("relation"),
#                 "crossrelation": fam.get("crossrelation"),
#                 "contact_no": fam.get("contactNo"),
#                 "email": fam.get("email"),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#                 "gender": fam.get("gender"),
#                 "occupation": fam.get("occupation"),
#                 "aadhaar_no": fam.get("aadhaarNo"),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo"),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_country": self.safe_fk(fam.get("residential_country"), Countries) or client.residential_country,
#                 "residential_state": self.safe_fk(fam.get("residential_state"), State) or client.residential_state,
#                 "residential_city": self.safe_fk(fam.get("residential_city"), Cities) or client.residential_city,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }

#             fam_aadhaar_key = f"family_members[{fam_index}][aadhaarCard]"
#             fam_pan_key = f"family_members[{fam_index}][panCard]"
#             if fam_aadhaar_key in request_files:
#                 fam_data["aadhaar_card_file"] = request_files.get(fam_aadhaar_key)
#             if fam_pan_key in request_files:
#                 fam_data["pan_card_file"] = request_files.get(fam_pan_key)

#             family_client = Client.objects.create(
#                 **fam_data,
#                 created_by=self.context["request"].user if self.context.get("request") else None,
#                 created_at=timezone.now()
#             )

#             # Family passports
#             fam_passports = fam.pop("fam_passport", [])
#             for pd_index, pd in enumerate(fam_passports):
#                 if not isinstance(pd, dict):
#                     continue

#                 f_passport_no = self.clean_str(pd.get("passport_no") or pd.get("passportNo"))
#                 f_passport_expiry_date = self.clean_date(pd.get("passport_expiry_date") or pd.get("passportExpiryDate"))
#                 fam_passport_key = f"family_members[{fam_index}][fam_passport][{pd_index}][passport_file]"
#                 f_passport_file = request_files.get(fam_passport_key)

#                 if f_passport_no or f_passport_expiry_date or f_passport_file:
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=f_passport_no,
#                         passport_expiry_date=f_passport_expiry_date,
#                         passport_file=f_passport_file,
#                     )

#             # Relation with previous family member
#             if prev_family_client:
#                 if fam.get("relation"):
#                     ClientRelation.objects.create(
#                         from_client=prev_family_client,
#                         to_client=family_client,
#                         relation=fam.get("relation")
#                     )
#                 if fam.get("crossrelation") or fam.get("crossRelation"):
#                     cross_rel = fam.get("crossrelation") or fam.get("crossRelation")
#                     ClientRelation.objects.create(
#                         from_client=family_client,
#                         to_client=prev_family_client,
#                         cross_relation=cross_rel
#                     )

#             prev_family_client = family_client
#             created_family_members[fam_index] = family_client

#         # Extra Relations (relationsWithOthers)
#         for rel in relationsWithOthers:
#             if isinstance(rel, str):
#                 try:
#                     rel = ast.literal_eval(rel)
#                 except Exception:
#                     continue
#             if not isinstance(rel, dict):
#                 continue

#             from_index = rel.get("fromIndex")
#             to_index = rel.get("toIndex")
#             relation = rel.get("relation")
#             cross_relation = rel.get("crossRelation")

#             if from_index is None or to_index is None:
#                 continue

#             from_client = created_family_members.get(int(from_index))
#             if not from_client:
#                 continue

#             target_client = created_family_members.get(int(to_index))
#             if not target_client:
#                 try:
#                     target_client = Client.objects.get(pk=int(to_index))
#                 except Client.DoesNotExist:
#                     continue

#             ClientRelation.objects.create(
#                 from_client=from_client,
#                 to_client=target_client,
#                 relation=relation,
#                 cross_relation=cross_relation
#             )

#         return client

#     # ---------------- Update ----------------
#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # Pop nested data
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         validated_data.pop("family_members", None)
#         validated_data.pop("familyMembers", None)

#         # Define FK fields and their corresponding models
#         fk_fields = ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]
#         fk_models = {
#             "country_code": Countries,
#             "residential_country": Countries,
#             "residential_state": State,
#             "residential_city": Cities,
#             "ref_preferred_airline": Airlines,
#         }

#         # Handle FK fields, allowing None
#         for fk_field in fk_fields:
#             if fk_field in validated_data:
#                 fk_value = validated_data.pop(fk_field)
#                 model_class = fk_models.get(fk_field)
#                 if fk_value is None:
#                     validated_data[f"{fk_field}_id"] = None
#                 else:
#                     if isinstance(fk_value, dict):
#                         fk_value = fk_value.get("id")
#                     if isinstance(fk_value, model_class):
#                         validated_data[f"{fk_field}_id"] = fk_value.id
#                     elif isinstance(fk_value, (int, str)):
#                         try:
#                             fk_instance = model_class.objects.get(id=int(fk_value))
#                             validated_data[f"{fk_field}_id"] = fk_instance.id
#                         except (ValueError, TypeError, model_class.DoesNotExist):
#                             validated_data[f"{fk_field}_id"] = None
#                     else:
#                         validated_data[f"{fk_field}_id"] = None

#         # Normalize fields, allowing None
#         if "client_code" in validated_data:
#             validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         if "dob" in validated_data:
#             validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         if "anniversary_date" in validated_data:
#             validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#                 validated_data.get("preferred_contact_method")
#             )

#         # Handle uploaded files, allowing None
#         files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in files:
#                 setattr(instance, field, files[field])
#             elif field in validated_data:
#                 file_val = validated_data.pop(field)
#                 if file_val is None or file_val in ["", "null"]:
#                     setattr(instance, field, None)

#         # Update main client fields, preserving existing values
#         skip_keys = {
#             "client_passport", "client_visa", "client_documents",
#             "client_companies", "client_frequent_flyers", "travel_insurance",
#         }
#         for attr, value in validated_data.items():
#             if attr not in skip_keys:
#                 setattr(instance, attr, value)
        
#         instance.save()

#         # Helper to skip empty dicts
#         def is_empty(d):
#             return not any(v for v in d.values() if v not in [None, "", [], {}])

#         # Passports
#         keep_ids = []
#         for pd in passports_data:
#             if is_empty(pd):
#                 continue
#             pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#             obj_id = pd.pop("id", None)
#             if obj_id:
#                 ClientPassport.objects.filter(id=obj_id, ref_client=instance).update(**pd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientPassport.objects.update_or_create(ref_client=instance, **pd)
#                 keep_ids.append(obj.id)
#         ClientPassport.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Visas
#         keep_ids = []
#         for vd in visas_data:
#             if is_empty(vd):
#                 continue
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
#             country_val = vd.pop("ref_visa_country", None)
#             if country_val is None:
#                 vd["ref_visa_country_id"] = None
#             else:
#                 if isinstance(country_val, dict):
#                     vd["ref_visa_country_id"] = country_val.get("id")
#                 elif isinstance(country_val, Countries):
#                     vd["ref_visa_country_id"] = country_val.id
#                 else:
#                     try:
#                         vd["ref_visa_country_id"] = int(country_val)
#                     except (ValueError, TypeError):
#                         vd["ref_visa_country_id"] = None
#             obj_id = vd.pop("id", None)
#             if obj_id:
#                 ClientVisa.objects.filter(id=obj_id, ref_client=instance).update(**vd)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientVisa.objects.update_or_create(ref_client=instance, **vd)
#                 keep_ids.append(obj.id)
#         ClientVisa.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Travel Insurance
#         keep_ids = []
#         for ins in insurances_data:
#             if is_empty(ins):
#                 continue
#             ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
#             obj_id = ins.pop("id", None)
#             if obj_id:
#                 ClientTravelInsurance.objects.filter(id=obj_id, ref_client=instance).update(**ins)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientTravelInsurance.objects.update_or_create(ref_client=instance, **ins)
#                 keep_ids.append(obj.id)
#         ClientTravelInsurance.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Documents
#         keep_ids = []
#         for doc in docs_data:
#             if is_empty(doc):
#                 continue
#             obj_id = doc.pop("id", None)
#             if obj_id:
#                 ClientDocument.objects.filter(id=obj_id, ref_client=instance).update(**doc)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientDocument.objects.update_or_create(ref_client=instance, **doc)
#                 keep_ids.append(obj.id)
#         ClientDocument.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Company Associations
#         keep_ids = []
#         for comp in companies_data:
#             if is_empty(comp):
#                 continue
#             ref_company = comp.pop("ref_company", None)
#             if ref_company is None:
#                 comp["ref_company_id"] = None
#             else:
#                 if isinstance(ref_company, dict):
#                     comp["ref_company_id"] = ref_company.get("id")
#                 elif isinstance(ref_company, Company):
#                     comp["ref_company_id"] = ref_company.id
#                 else:
#                     try:
#                         comp["ref_company_id"] = int(ref_company)
#                     except (ValueError, TypeError):
#                         comp["ref_company_id"] = None
#             obj_id = comp.pop("id", None)
#             if obj_id:
#                 AssocClientCompany.objects.filter(id=obj_id, ref_client=instance).update(**comp)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = AssocClientCompany.objects.update_or_create(ref_client=instance, **comp)
#                 keep_ids.append(obj.id)
#         AssocClientCompany.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         # Frequent Flyers
#         keep_ids = []
#         for ff in frequent_flyers_data:
#             if is_empty(ff):
#                 continue
#             airline_val = ff.pop("ref_airline", None)
#             if airline_val is None:
#                 ff["ref_airline_id"] = None
#             else:
#                 if isinstance(airline_val, dict):
#                     ff["ref_airline_id"] = airline_val.get("id")
#                 elif isinstance(airline_val, Airlines):
#                     ff["ref_airline_id"] = airline_val.id
#                 else:
#                     try:
#                         ff["ref_airline_id"] = int(airline_val)
#                     except (ValueError, TypeError):
#                         ff["ref_airline_id"] = None
#             ff["ff_no"] = self.clean_str(ff.get("ff_no"))
#             obj_id = ff.pop("id", None)
#             if obj_id:
#                 ClientFrequentFlyer.objects.filter(id=obj_id, ref_client=instance).update(**ff)
#                 keep_ids.append(obj_id)
#             else:
#                 obj, created = ClientFrequentFlyer.objects.update_or_create(ref_client=instance, **ff)
#                 keep_ids.append(obj.id)
#         ClientFrequentFlyer.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#         return instance 

# class FullClientSerializer(serializers.ModelSerializer):
#     """Serializer for creating and updating Client objects with nested relationships and file uploads."""

#     # --- Foreign keys ---
#     country_code = CountrySerializer(required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), allow_null=True, required=False
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True, write_only=True
#     )
#     ref_visa_country = CountrySerializer(required=False, allow_null=True)
#     preferred_airline = AirlinesSerializer(read_only=True)

#     # --- Nested serializers ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     # --- Boolean field ---
#     is_prepayment = serializers.BooleanField(required=False, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark",
#             "occupation", "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file",
#             "pan_card_file", "ref_preferred_airline", "preferred_airline", "star_rating",
#             "stay_preference", "room_preference", "extra_amenities", "seat_preference",
#             "seat_preference_other", "meal_preference", "ref_visa_country", "fare_preference",
#             "created_at", "created_by", "updated_at", "updated_by", "client_passport",
#             "client_visa", "travel_insurance", "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "familyMembers", "fam_passport",
#             "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     VALID_CLIENT_TYPES = ['Primary Member', 'Family Member']

#     def _normalize_code(self, code: str | None) -> str | None:
#         return code.strip() or None if code else None

#     def clean_date(self, value):
#         if not value or str(value).strip() in ["", "[]", "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if value else None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value.strip(), "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_str(self, value):
#         if value in ["", None, [], [""], "[]", "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 return parsed[0] if isinstance(parsed, list) and len(parsed) == 1 else parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def clean_bool(self, value):
#         if value in ["", None, [], [""], "[]", "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else None
#         if isinstance(value, str):
#             value = value.lower().strip()
#             if value in ["true", "1", "yes"]:
#                 return True
#             if value in ["false", "0", "no"]:
#                 return False
#         return bool(value) if isinstance(value, (bool, int)) else None

#     def safe_fk(self, model_class, value, return_id=False):
#         if not value or value in ["", [], [""], "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else None
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 value = parsed[0] if isinstance(parsed, list) and len(parsed) == 1 else None
#             except Exception:
#                 return None
#         try:
#             lookup_field = 'client_id' if model_class == Client else model_class._meta.pk.name
#             value_int = int(value) if isinstance(value, (str, int)) else value.id
#             instance = model_class.objects.get(**{lookup_field: value_int}) if model_class.objects.filter(**{lookup_field: value_int}).exists() else None
#             if instance and return_id:
#                 return getattr(instance, lookup_field)
#             return instance
#         except (ValueError, TypeError, AttributeError, model_class.DoesNotExist):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         VALID_CONTACT_METHODS = ["mail", "call", "group message", "whatsapp"]
#         if not value or value in ["", [], [""], "null"]:
#             return []
#         if isinstance(value, str):
#             try:
#                 value = ast.literal_eval(value) if value.strip().startswith("[") else [value]
#             except Exception:
#                 value = [value]
#         normalized = []
#         for v in value:
#             key = v.get("id") or v.get("value") or v.get("label") if isinstance(v, dict) else str(v)
#             if key and key not in ["", "null"]:
#                 key = key.lower().strip()
#                 if key in VALID_CONTACT_METHODS:
#                     normalized.append(key)
#                 else:
#                     raise serializers.ValidationError({
#                         "preferred_contact_method": f"'{key}' is not a valid contact method. Valid options: {VALID_CONTACT_METHODS}"
#                     })
#         return normalized
    
#     def handle_file_upload_aadhar_pan(self, data, file_map, request_files):
#         for field, req_field in file_map.items():
#             if req_field in request_files:
#                 file = request_files.get(req_field)  # Use .get() for single file
#                 if file:
#                     data[field] = self.validate_file(file)
#                 else:
#                     data[field] = None
#             elif req_field in data and data[req_field] in ["", [], [""], "null"]:
#                 data[field] = None
#         return data

#     def handle_file_upload(self, data, file_map, request_files):
#         for field, req_field in file_map.items():
#             files = request_files.getlist(req_field)
#             if files:
#                 data[field] = [self.validate_file(f) for f in files if f]
#             elif req_field in data and data[req_field] in ["", [], [""], "null"]:
#                 data[field] = []
#         return data

#     def validate_file(self, file, max_size=100 * 1024 * 1024, allowed_types=['application/pdf', 'image/jpeg', 'image/png', 'image/webp']):
#         if not file or file in ["", [], [""], "null"]:
#             return None
#         if isinstance(file, bytes):
#             raise serializers.ValidationError(f"Invalid file data for {file}. Expected a file object, got bytes.")
#         if not hasattr(file, 'size') or not hasattr(file, 'content_type'):
#             raise serializers.ValidationError(f"Invalid file data for {file}. Ensure correct multipart/form-data encoding.")
#         if len(file.name) > 255:
#             raise serializers.ValidationError(f"File name {file.name} is too long. Maximum length is 255 characters.")
#         if file.size > max_size:
#             raise serializers.ValidationError(f"File {file.name} exceeds maximum size of {max_size / 1024 / 1024} MB.")
#         if file.content_type not in allowed_types:
#             raise serializers.ValidationError(f"File {file.name} has invalid type {file.content_type}. Allowed: {allowed_types}.")
#         return file

#     def validate(self, data):
#         data = self.unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])
#         for field in ["client_code", "client_first_name", "client_middle_name", "client_last_name",
#                     "contact_no", "email", "residential_address", "residential_pincode",
#                     "reference_remark", "occupation", "aadhaar_no", "pan_no", "seat_preference_other"]:
#             if field in data:
#                 data[field] = self.clean_str(data[field])
#         if 'client_type' in data:
#             data['client_type'] = self.clean_str(data['client_type'])
#             if data['client_type'] and data['client_type'] not in self.VALID_CLIENT_TYPES:
#                 raise serializers.ValidationError({
#                     'client_type': f"'{data['client_type']}' is not a valid choice. Valid options: {self.VALID_CLIENT_TYPES}"
#                 })
#         for field in ["client_salutation", "gender", "marital_status", "reference_from",
#                     "star_rating", "stay_preference", "room_preference", "extra_amenities",
#                     "seat_preference", "meal_preference", "fare_preference"]:
#             if field in data:
#                 data[field] = self.clean_str(data[field])
#                 try:
#                     choices = Client._meta.get_field(field).choices
#                     if choices and data[field] and data[field] not in [choice[0] for choice in choices]:
#                         raise serializers.ValidationError({
#                             field: f"'{data[field]}' is not a valid choice. Valid options: {[c[0] for c in choices]}"
#                         })
#                 except AttributeError:
#                     raise serializers.ValidationError({
#                         field: f"Field '{field}' does not have choices defined in the Client model."
#                     })
#         data["is_prepayment"] = self.clean_bool(data.get("is_prepayment"))
#         data["reference_id"] = self.safe_fk(Client, data.get("reference_id"), return_id=True)
#         data["dob"] = self.clean_date(data.get("dob"))
#         data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))
#         data["preferred_contact_method"] = self.normalize_preferred_contact_method(data.get("preferred_contact_method"))
#         for field in ["residential_country", "residential_state", "residential_city", "ref_preferred_airline"]:
#             if field in data:
#                 model = {
#                     "residential_country": Countries,
#                     "residential_state": State,
#                     "residential_city": Cities,
#                     "ref_preferred_airline": Airlines
#                 }[field]
#                 data[field] = self.safe_fk(model, data[field])
#         for field in ["client_passport", "client_visa", "travel_insurance", "client_companies",
#                     "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#                     "relationsWithOthers"]:
#             if field in data and isinstance(data[field], list):
#                 data[field] = [self.normalize_nested_item(item, field) for item in data[field] if item]
#         client_code = self._normalize_code(data.get("client_code"))
#         if client_code:
#             qs = Client.objects.filter(client_code=client_code)
#             if self.instance:
#                 qs = qs.exclude(client_id=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{client_code}' already exists."})
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in request_files:
#                 file = request_files.get(field)  # Use .get() for single file
#                 if file:
#                     if isinstance(file, bytes):
#                         raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#                     data[field] = self.validate_file(file)  # Validate single file
#                 else:
#                     data[field] = None
#             elif field in data and data[field] in ["", [], [""], "null"]:
#                 data[field] = None
#             elif field in data and isinstance(data[field], bytes):
#                 raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#         return data

#     def normalize_nested_item(self, item, field_name):
#         if not isinstance(item, dict):
#             return item
#         item = self.unwrap_scalars(item)
#         if field_name == "client_passport":
#             item["passport_no"] = self.clean_str(item.get("passport_no"))
#             item["passport_expiry_date"] = self.clean_date(item.get("passport_expiry_date"))
#             file_key = f"{field_name}[{item.get('index', 0)}][passport_file][]"
#             item = self.handle_file_upload(item, {"passport_file": file_key}, self.context.get("request").FILES)
#         elif field_name == "client_visa":
#             item["visa_from_date"] = self.clean_date(item.get("visa_from_date"))
#             item["visa_to_date"] = self.clean_date(item.get("visa_to_date"))
#             item["ref_visa_country"] = self.safe_fk(Countries, item.get("ref_visa_country"))
#             item["visa_type"] = self.clean_str(item.get("visa_type"))
#             if item.get("visa_type") and item["visa_type"] not in [choice[0] for choice in ClientVisa.VISA_TYPE]:
#                 raise serializers.ValidationError({
#                     field_name: {item.get("index", 0): {"visa_type": f"'{item['visa_type']}' is not a valid choice. Valid options: {[c[0] for c in ClientVisa.VISA_TYPE]}"}}})
#             file_key = f"{field_name}[{item.get('index', 0)}][passport_size_photograph][]"
#             item = self.handle_file_upload(item, {"passport_size_photograph": file_key}, self.context.get("request").FILES)
#         elif field_name == "travel_insurance":
#             item["insurance_from_date"] = self.clean_date(item.get("insurance_from_date"))
#             item["insurance_to_date"] = self.clean_date(item.get("insurance_to_date"))
#             file_key = f"{field_name}[{item.get('index', 0)}][insurance_document][]"
#             item = self.handle_file_upload(item, {"insurance_document": file_key}, self.context.get("request").FILES)
#         elif field_name == "client_documents":
#             item["other_document_name"] = self.clean_str(item.get("other_document_name"))
#             file_key = f"{field_name}[{item.get('index', 0)}][other_document][]"
#             item = self.handle_file_upload(item, {"other_document": file_key}, self.context.get("request").FILES)
#         elif field_name == "client_companies":
#             item["designation"] = self.clean_str(item.get("designation"))
#             item["ref_company"] = self.safe_fk(Company, item.get("ref_company"))
#         elif field_name == "client_frequent_flyers":
#             item["ff_no"] = self.clean_str(item.get("ff_no"))
#             item["ref_airline"] = self.safe_fk(Airlines, item.get("ref_airline"))
#         elif field_name == "family_members":
#             item["dob"] = self.clean_date(item.get("dob"))
#             item["anniversary_date"] = self.clean_date(item.get("anniversary_date"))
#             item["clientCode"] = self._normalize_code(item.get("clientCode"))
#             if 'client_type' in item:
#                 item['client_type'] = self.clean_str(item['client_type'])
#                 if item['client_type'] and item['client_type'] not in self.VALID_CLIENT_TYPES:
#                     raise serializers.ValidationError({
#                         field_name: {item.get("index", 0): {
#                             'client_type': f"'{item['client_type']}' is not a valid choice. Valid options: {self.VALID_CLIENT_TYPES}"
#                         }}
#                     })
#             for field in ["client_salutation", "gender", "marital_status", "reference_from",
#                         "star_rating", "stay_preference", "room_preference", "extra_amenities",
#                         "seat_preference", "meal_preference", "fare_preference"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#                     try:
#                         choices = Client._meta.get_field(field).choices
#                         if choices and item[field] and item[field] not in [choice[0] for choice in choices]:
#                             raise serializers.ValidationError({
#                                 field_name: {item.get("index", 0): {
#                                     field: f"'{item[field]}' is not a valid choice. Valid options: {[c[0] for c in choices]}"
#                                 }}
#                             })
#                     except AttributeError:
#                         raise serializers.ValidationError({
#                             field_name: {item.get("index", 0): {
#                                 field: f"Field '{field}' does not have choices defined in the Client model."
#                             }}
#                         })
#             for field in ["client_first_name", "client_middle_name", "client_last_name",
#                         "contact_no", "email", "residential_address", "residential_pincode",
#                         "reference_remark", "occupation", "aadhaar_no", "pan_no", "seat_preference_other"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#             for field in ["residential_country", "residential_state", "residential_city"]:
#                 if field in item:
#                     model = {"residential_country": Countries, "residential_state": State, "residential_city": Cities}[field]
#                     item[field] = self.safe_fk(model, item[field])
#             # Handle single files for aadhaar_card_file and pan_card_file
#             request_files = self.context.get("request").FILES if self.context.get("request") else {}
#             for field, req_field in [
#                 ("aadhaar_card_file", f"family_members[{item.get('index', 0)}][aadhaarCard]"),
#                 ("pan_card_file", f"family_members[{item.get('index', 0)}][panCard]")
#             ]:
#                 if req_field in request_files:
#                     file = request_files.get(req_field)  # Single file
#                     if file:
#                         if isinstance(file, bytes):
#                             raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#                         item[field] = self.validate_file(file)
#                     else:
#                         item[field] = None
#                 elif field in item and item[field] in ["", [], [""], "null"]:
#                     item[field] = None
#                 elif field in item and isinstance(item[field], bytes):
#                     raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#             for passport in item.get("fam_passport", []):
#                 passport["passport_no"] = self.clean_str(passport.get("passport_no"))
#                 passport["passport_expiry_date"] = self.clean_date(passport.get("passport_expiry_date"))
#                 file_key = f"family_members[{item.get('index', 0)}][fam_passport][{passport.get('index', 0)}][passport_file][]"
#                 passport = self.handle_file_upload(passport, {"passport_file": file_key}, self.context.get("request").FILES)
#         elif field_name == "relationsWithOthers":
#             item["relation_with_other_client_code"] = self.clean_str(item.get("relation_with_other_client_code"))
#         return item

#     def unwrap_scalars(self, data, skip_keys=None):
#         skip_keys = skip_keys or []
#         if not isinstance(data, dict):
#             if isinstance(data, list) and len(data) == 1 and not isinstance(data[0], (dict, list)) and data[0] not in ["", "null", "[]"]:
#                 return data[0]
#             return None if data in ["", [], [""], "null"] else data
#         result = {}
#         for k, v in data.items():
#             if k in skip_keys or isinstance(v, (dict, list)):
#                 result[k] = v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     result[k] = parsed[0] if isinstance(parsed, list) and len(parsed) == 1 and not isinstance(parsed[0], (dict, list)) else parsed
#                 except Exception:
#                     result[k] = v if v not in ["", "null", "[]"] else None
#             else:
#                 result[k] = None if v in ["", [], [""], "null"] else v
#         return result

#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj).select_related(
#             'country_code', 'residential_country', 'residential_state', 'residential_city', 'ref_preferred_airline'
#         ).prefetch_related(
#             'client_passport', 'client_visa', 'travel_insurance', 'client_companies', 'client_documents',
#             'client_frequent_flyers'
#         )
#         return FullClientSerializer(members, many=True, context=self.context).data

#     @transaction.atomic
#     def create(self, validated_data):
#         related_data = self.pop_related_data(validated_data)
#         client = self.create_client(validated_data)
#         self.create_related_objects(client, related_data)
#         return client

#     def pop_related_data(self, validated_data):
#         return {
#             "passports": validated_data.pop("client_passport", []),
#             "visas": validated_data.pop("client_visa", []),
#             "insurances": validated_data.pop("travel_insurance", []),
#             "documents": validated_data.pop("client_documents", []),
#             "companies": validated_data.pop("client_companies", []),
#             "frequent_flyers": validated_data.pop("client_frequent_flyers", []),
#             "family_members": validated_data.pop("family_members", []),
#             "fam_passports": validated_data.pop("fam_passport", []),
#             "relations": validated_data.pop("relationsWithOthers", []),
#             "fks": {
#                 "country_code": validated_data.pop("country_code", None),
#                 "residential_country": validated_data.pop("residential_country", None),
#                 "residential_state": validated_data.pop("residential_state", None),
#                 "residential_city": validated_data.pop("residential_city", None),
#                 "ref_preferred_airline": validated_data.pop("ref_preferred_airline", None),
#             }
#         }

#     def create_client(self, validated_data):
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = validated_data.get("client_type", "Primary Member")
#         validated_data["client_status"] = 1
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#             validated_data.get("preferred_contact_method")
#         )
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             validated_data["created_by"] = user
#         # Assign aadhaar_card_file and pan_card_file directly (single file or None)
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in validated_data and validated_data[field] is not None:
#                 validated_data[field] = validated_data[field]  # Already a single file
#             else:
#                 validated_data[field] = None
#         client = Client.objects.create(**validated_data)
#         return client

#     def create_related_objects(self, client, related_data):
#         fks = related_data["fks"]
#         if fks["country_code"]:
#             client.country_code = Countries.objects.get(id=fks["country_code"]["id"] if isinstance(fks["country_code"], dict) else fks["country_code"])
#         for fk_field, model in [
#             ("residential_country", Countries), ("residential_state", State),
#             ("residential_city", Cities), ("ref_preferred_airline", Airlines)
#         ]:
#             if fks[fk_field]:
#                 setattr(client, fk_field, self.safe_fk(model, fks[fk_field]))
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             client.updated_by = user
#         client.save()
#         self.create_nested_objects(client, related_data["passports"], ClientPassport, {"passport_file": "passport_file"})
#         self.create_nested_objects(client, related_data["visas"], ClientVisa, {"passport_size_photograph": "passport_size_photograph"})
#         self.create_nested_objects(client, related_data["insurances"], ClientTravelInsurance, {"insurance_document": "insurance_document"})
#         self.create_nested_objects(client, related_data["documents"], ClientDocument, {"other_document": "other_document"})
#         self.create_nested_objects(client, related_data["companies"], AssocClientCompany, {}, ref_field="ref_company")
#         self.create_nested_objects(client, related_data["frequent_flyers"], ClientFrequentFlyer, {}, ref_field="ref_airline")
#         prev_family_client = None
#         for fam_index, fam in enumerate(related_data["family_members"]):
#             if not any(fam.get(field) for field in ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]):
#                 continue
#             fam_data = self.prepare_family_member_data(fam, client, fam_index)
#             if user and user.is_authenticated:
#                 fam_data["created_by"] = user
#             # Ensure aadhaar_card_file and pan_card_file are single files or None
#             for field in ["aadhaar_card_file", "pan_card_file"]:
#                 if field in fam_data and isinstance(fam_data[field], bytes):
#                     raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#                 fam_data[field] = fam_data.get(field, None)
#             family_client = Client.objects.create(**fam_data)
#             if fam.get("relation"):
#                 ClientRelation.objects.create(from_client=client, to_client=family_client, relation=fam["relation"])
#             if fam.get("crossrelation"):
#                 ClientRelation.objects.create(from_client=family_client, to_client=client, relation=fam["crossrelation"])
#             if prev_family_client and fam.get("relation"):
#                 ClientRelation.objects.create(from_client=prev_family_client, to_client=family_client, relation=fam["relation"])
#                 if fam.get("crossrelation"):
#                     ClientRelation.objects.create(from_client=family_client, to_client=prev_family_client, relation=fam["crossrelation"])
#             prev_family_client = family_client
#             for pd_index, pd in enumerate(fam.get("fam_passport", [])):
#                 if not pd.get("passport_no") or not pd.get("passport_expiry_date"):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 for file in pd.get("passport_file", []) or [None]:
#                     if isinstance(file, bytes):
#                         raise serializers.ValidationError(f"Invalid data for passport_file: Received bytes, expected a file object.")
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=pd["passport_no"],
#                         passport_expiry_date=pd["passport_expiry_date"],
#                         passport_file=file
#                     )
#         for rel in related_data["relations"]:
#             if not rel.get("toIndex"):
#                 continue
#             try:
#                 target_client = Client.objects.get(client_id=int(rel["toIndex"]))
#                 ClientRelation.objects.create(
#                     from_client=client,
#                     to_client=target_client,
#                     relation=rel.get("relation"),
#                     cross_relation=rel.get("crossRelation")
#                 )
#             except Client.DoesNotExist:
#                 continue

#     def prepare_family_member_data(self, fam, parent_client, fam_index):
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         fam_data = {
#             "ref_client": parent_client,
#             "client_type": "Family Member",
#             "client_status": 1,
#             "client_code": self._normalize_code(fam.get("clientCode")),
#             "client_salutation": self.clean_str(fam.get("salutation")),
#             "client_first_name": self.clean_str(fam.get("firstName")),
#             "client_middle_name": self.clean_str(fam.get("middleName")),
#             "client_last_name": self.clean_str(fam.get("lastName")),
#             "relation": self.clean_str(fam.get("relation")),
#             "crossrelation": self.clean_str(fam.get("crossrelation")),
#             "contact_no": self.clean_str(fam.get("contactNo")),
#             "email": self.clean_str(fam.get("email")),
#             "dob": self.clean_date(fam.get("dob")),
#             "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#             "gender": self.clean_str(fam.get("gender")),
#             "occupation": self.clean_str(fam.get("occupation")),
#             "aadhaar_no": self.clean_str(fam.get("aadhaarNo")),
#             "pan_no": self.clean_str(fam.get("panNo")),
#             "residential_address": self.clean_str(fam.get("residential_address")) or parent_client.residential_address,
#             "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or parent_client.residential_country,
#             "residential_state": self.safe_fk(State, fam.get("residential_state")) or parent_client.residential_state,
#             "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or parent_client.residential_city,
#             "residential_pincode": self.clean_str(fam.get("residential_pincode")) or parent_client.residential_pincode,
#         }
#         return fam_data

#     def create_nested_objects(self, client, data, model, file_map, ref_field=None):
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for item in data:
#             if not any(item.values()):
#                 continue
#             if ref_field:
#                 item[ref_field] = self.safe_fk(globals()[ref_field.capitalize()], item.get(ref_field))
#             file_field = list(file_map.keys())[0]
#             files = item.pop(file_field, [])
#             item = self.handle_file_upload(item, file_map, request_files)
#             # Create an instance for each file
#             for file in files or [None]:
#                 item_copy = item.copy()
#                 item_copy[file_field] = file
#                 model.objects.create(ref_client=client, **item_copy)

#     @transaction.atomic
#     def update(self, instance, validated_data):
#         related_data = self.pop_related_data(validated_data)
#         self.update_client(instance, validated_data)
#         self.update_related_objects(instance, related_data)
#         return instance

#     def update_client(self, instance, validated_data):
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in validated_data and validated_data[field] is not None:
#                 validated_data[field] = validated_data[field]  # Already a single file
#             else:
#                 validated_data[field] = None
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             instance.updated_by = user
#         instance.save()
#         return instance

#     def update_related_objects(self, instance, related_data):
#         fks = related_data["fks"]
#         if fks["country_code"]:
#             instance.country_code = Countries.objects.get(id=fks["country_code"]["id"] if isinstance(fks["country_code"], dict) else fks["country_code"])
#         for fk_field, model in [
#             ("residential_country", Countries), ("residential_state", State),
#             ("residential_city", Cities), ("ref_preferred_airline", Airlines)
#         ]:
#             if fks[fk_field]:
#                 setattr(instance, fk_field, self.safe_fk(model, fks[fk_field]))
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             instance.updated_by = user
#         instance.save()
#         self.update_nested_objects(instance, related_data["passports"], ClientPassport, {"passport_file": "passport_file"})
#         self.update_nested_objects(instance, related_data["visas"], ClientVisa, {"passport_size_photograph": "passport_size_photograph"})
#         self.update_nested_objects(instance, related_data["insurances"], ClientTravelInsurance, {"insurance_document": "insurance_document"})
#         self.update_nested_objects(instance, related_data["documents"], ClientDocument, {"other_document": "other_document"})
#         self.update_nested_objects(instance, related_data["companies"], AssocClientCompany, {}, ref_field="ref_company")
#         self.update_nested_objects(instance, related_data["frequent_flyers"], ClientFrequentFlyer, {}, ref_field="ref_airline")
#         self.update_family_members(instance, related_data["family_members"], related_data["fam_passports"])
#         self.update_relations(instance, related_data["relations"])

#     def update_nested_objects(self, instance, data, model, file_map, ref_field=None):
#         keep_ids = []
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         file_field = list(file_map.keys())[0]
#         for item in data:
#             if not any(item.values()):
#                 continue
#             if ref_field:
#                 item[ref_field] = self.safe_fk(globals()[ref_field.capitalize()], item.get(ref_field))
#             files = item.pop(file_field, [])
#             item = self.handle_file_upload(item, file_map, request_files)
#             obj_id = item.pop("id", None)
#             if obj_id:
#                 model.objects.filter(id=obj_id, ref_client=instance).update(**item)
#                 keep_ids.append(obj_id)
#                 # Update file only if provided
#                 if files:
#                     model.objects.filter(id=obj_id, ref_client=instance).update(**{file_field: files[0]})
#             else:
#                 # Create an instance for each file
#                 for file in files or [None]:
#                     item_copy = item.copy()
#                     item_copy[file_field] = file
#                     obj = model.objects.create(ref_client=instance, **item_copy)
#                     keep_ids.append(obj.id)
#         model.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#     def update_family_members(self, instance, family_data, fam_passports):
#         keep_ids = []
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         user = self.context.get("request").user if self.context.get("request") else None
#         for fam_index, fam in enumerate(family_data):
#             if not any(fam.get(field) for field in ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]):
#                 continue
#             fam_data = self.prepare_family_member_data(fam, instance, fam_index)
#             obj_id = fam.get("id")
#             # Ensure aadhaar_card_file and pan_card_file are single files or None
#             for field in ["aadhaar_card_file", "pan_card_file"]:
#                 if field in fam_data and isinstance(fam_data[field], bytes):
#                     raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#                 fam_data[field] = fam_data.get(field, None)
#             if obj_id:
#                 Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam_data)
#                 family_client = Client.objects.get(client_id=obj_id)
#                 if user and user.is_authenticated:
#                     family_client.updated_by = user
#                     family_client.save()
#                 keep_ids.append(obj_id)
#             else:
#                 if user and user.is_authenticated:
#                     fam_data["created_by"] = user
#                 family_client = Client.objects.create(**fam_data)
#                 keep_ids.append(family_client.client_id)
#             fam_passport_data = fam.get("fam_passport", [])
#             keep_passport_ids = []
#             for pd_index, pd in enumerate(fam_passport_data):
#                 if not pd.get("passport_no") or not pd.get("passport_expiry_date"):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 files = pd.get("passport_file", []) or [None]
#                 obj_id = pd.pop("id", None)
#                 if obj_id:
#                     ClientPassport.objects.filter(id=obj_id, ref_client=family_client).update(**pd)
#                     keep_passport_ids.append(obj_id)
#                     if files:
#                         if isinstance(files[0], bytes):
#                             raise serializers.ValidationError(f"Invalid data for passport_file: Received bytes, expected a file object.")
#                         ClientPassport.objects.filter(id=obj_id, ref_client=family_client).update(passport_file=files[0])
#                 else:
#                     for file in files:
#                         if isinstance(file, bytes):
#                             raise serializers.ValidationError(f"Invalid data for passport_file: Received bytes, expected a file object.")
#                         pd_copy = pd.copy()
#                         pd_copy["passport_file"] = file
#                         obj = ClientPassport.objects.create(ref_client=family_client, **pd_copy)
#                         keep_passport_ids.append(obj.id)
#             ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=keep_passport_ids).delete()
#         Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()

#     def to_representation(self, instance):
#         data = super().to_representation(instance)
#         related_fields = {
#             "client_passport": ClientPassportSerializer,
#             "client_visa": ClientVisaSerializer,
#             "travel_insurance": ClientTravelInsuranceSerializer,
#             "client_companies": AssocClientCompanySerializer,
#             "client_documents": OtherDocumentSerializer,
#             "client_frequent_flyers": FrequentflyerSerializer
#         }
#         for field, serializer_class in related_fields.items():
#             if hasattr(instance, field):
#                 data[field] = serializer_class(getattr(instance, field).all(), many=True, context=self.context).data
#         return data


# # class FullClientSerializer(serializers.ModelSerializer):
#     """Serializer for creating and updating Client objects with nested relationships and file uploads."""

#     # --- Foreign keys ---
#     country_code = CountrySerializer(required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), allow_null=True, required=False
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), required=False, allow_null=True
#     )
#     ref_preferred_airline = serializers.PrimaryKeyRelatedField(
#         queryset=Airlines.objects.all(), required=False, allow_null=True, write_only=True
#     )
#     ref_visa_country = CountrySerializer(required=False, allow_null=True)
#     preferred_airline = AirlinesSerializer(read_only=True)

#     # --- Nested serializers ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
#     fam_passport = PassportInSerializer(many=True, required=False, allow_null=True)
#     relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
#     anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

#     # --- Boolean field ---
#     is_prepayment = serializers.BooleanField(required=False, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
#             "relation", "crossrelation", "client_middle_name", "client_last_name", "dob", "is_prepayment",
#             "country_code", "contact_no", "email", "gender", "residential_address",
#             "residential_city", "residential_state", "residential_country", "residential_pincode",
#             "marital_status", "anniversary_date", "reference_from", "reference_id", "reference_remark",
#             "occupation", "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file",
#             "pan_card_file", "ref_preferred_airline", "preferred_airline", "star_rating",
#             "stay_preference", "room_preference", "extra_amenities", "seat_preference",
#             "seat_preference_other", "meal_preference", "ref_visa_country", "fare_preference",
#             "created_at", "created_by", "updated_at", "updated_by", "client_passport",
#             "client_visa", "travel_insurance", "client_companies", "client_documents",
#             "client_frequent_flyers", "family_members", "familyMembers", "fam_passport",
#             "relationsWithOthers",
#         ]
#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     # ---------------- Helper Methods ----------------
#     VALID_CLIENT_TYPES = ['Primary Member', 'Family Member']

#     def _normalize_code(self, code: str | None) -> str | None:
#         return code.strip() or None if code else None

#     def clean_date(self, value):
#         if not value or str(value).strip() in ["", "[]", "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if value else None
#         if isinstance(value, str):
#             try:
#                 return datetime.strptime(value.strip(), "%Y-%m-%d").date()
#             except ValueError:
#                 return None
#         return value

#     def clean_str(self, value):
#         if value in ["", None, [], [""], "[]", "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else " ".join(map(str, value))
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 return parsed[0] if isinstance(parsed, list) and len(parsed) == 1 else parsed
#             except Exception:
#                 pass
#         return str(value).strip() or None

#     def clean_bool(self, value):
#         if value in ["", None, [], [""], "[]", "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else None
#         if isinstance(value, str):
#             value = value.lower().strip()
#             if value in ["true", "1", "yes"]:
#                 return True
#             if value in ["false", "0", "no"]:
#                 return False
#         return bool(value) if isinstance(value, (bool, int)) else None

#     def safe_fk(self, model_class, value, return_id=False):
#         if not value or value in ["", [], [""], "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else None
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 value = parsed[0] if isinstance(parsed, list) and len(parsed) == 1 else None
#             except Exception:
#                 return None
#         try:
#             lookup_field = 'client_id' if model_class == Client else model_class._meta.pk.name
#             value_int = int(value) if isinstance(value, (str, int)) else value.id
#             instance = model_class.objects.get(**{lookup_field: value_int}) if model_class.objects.filter(**{lookup_field: value_int}).exists() else None
#             if instance and return_id:
#                 return getattr(instance, lookup_field)
#             return instance
#         except (ValueError, TypeError, AttributeError, model_class.DoesNotExist):
#             return None

#     def normalize_preferred_contact_method(self, value):
#         VALID_CONTACT_METHODS = ["mail", "call", "group message", "whatsapp"]
#         if not value or value in ["", [], [""], "null"]:
#             return []
#         if isinstance(value, str):
#             try:
#                 value = ast.literal_eval(value) if value.strip().startswith("[") else [value]
#             except Exception:
#                 value = [value]
#         normalized = []
#         for v in value:
#             key = v.get("id") or v.get("value") or v.get("label") if isinstance(v, dict) else str(v)
#             if key and key not in ["", "null"]:
#                 key = key.lower().strip()
#                 if key in VALID_CONTACT_METHODS:
#                     normalized.append(key)
#                 else:
#                     raise serializers.ValidationError({
#                         "preferred_contact_method": f"'{key}' is not a valid contact method. Valid options: {VALID_CONTACT_METHODS}"
#                     })
#         return normalized

#     def validate_file(self, file, max_size=100 * 1024 * 1024, allowed_types=['application/pdf', 'image/jpeg', 'image/png', 'image/webp']):
#         if not file or file in ["", [], [""], "null"]:
#             return None

#         # Handle bytes object (e.g., base64 or raw binary)
#         if isinstance(file, bytes):
#             try:
#                 # Attempt to decode as base64 if that's the expected format
#                 decoded_file = base64.b64decode(file)
#                 file_name = "uploaded_file.pdf"  # Default name, adjust as needed
#                 content_type = 'application/pdf'  # Adjust based on expected type or detection
#                 file = InMemoryUploadedFile(
#                     file=BytesIO(decoded_file),
#                     field_name=None,
#                     name=file_name,
#                     content_type=content_type,
#                     size=len(decoded_file),
#                     charset=None
#                 )
#             except Exception as e:
#                 raise serializers.ValidationError(f"Failed to process bytes data for file: {str(e)}")

#         # Handle base64 string (e.g., "data:application/pdf;base64,...")
#         if isinstance(file, str) and file.startswith("data:"):
#             try:
#                 header, encoded = file.split(",", 1)
#                 decoded_file = base64.b64decode(encoded)
#                 content_type = header.split(";")[0].replace("data:", "")
#                 file_name = f"uploaded_file.{content_type.split('/')[-1]}"  # Derive extension from content type
#                 file = InMemoryUploadedFile(
#                     file=BytesIO(decoded_file),
#                     field_name=None,
#                     name=file_name,
#                     content_type=content_type,
#                     size=len(decoded_file),
#                     charset=None
#                 )
#             except Exception as e:
#                 raise serializers.ValidationError(f"Invalid base64 data for file: {str(e)}")

#         # Standard validation for file objects
#         if not hasattr(file, 'size') or not hasattr(file, 'content_type'):
#             raise serializers.ValidationError(f"Invalid file data for {file}. Ensure correct multipart/form-data encoding.")
#         if len(file.name) > 255:
#             raise serializers.ValidationError(f"File name {file.name} is too long. Maximum length is 255 characters.")
#         if file.size > max_size:
#             raise serializers.ValidationError(f"File {file.name} exceeds maximum size of {max_size / 1024 / 1024} MB.")
#         if file.content_type not in allowed_types:
#             raise serializers.ValidationError(f"File {file.name} has invalid type {file.content_type}. Allowed: {allowed_types}.")
#         return file

#     def handle_file_upload_aadhar_pan(self, data, file_map, request_files):
#         for field, req_field in file_map.items():
#             if req_field in request_files:
#                 file = request_files.get(req_field)
#                 if file:
#                     data[field] = self.validate_file(file)
#                 else:
#                     data[field] = None
#             elif req_field in data:
#                 file_data = data.get(req_field)
#                 if file_data in ["", [], [""], "null"]:
#                     data[field] = None
#                 elif isinstance(file_data, (bytes, str)):
#                     data[field] = self.validate_file(file_data)
#                 else:
#                     data[field] = None
#             else:
#                 data[field] = None
#         return data

#     def handle_file_upload(self, data, file_map, request_files):
#         for field, req_field in file_map.items():
#             files = request_files.getlist(req_field)
#             if files:
#                 data[field] = [self.validate_file(f) for f in files if f]
#             elif req_field in data:
#                 file_data = data.get(req_field)
#                 if file_data in ["", [], [""], "null"]:
#                     data[field] = []
#                 elif isinstance(file_data, bytes):
#                     data[field] = [self.validate_file(file_data)]
#                 elif isinstance(file_data, str) and file_data.startswith("data:"):
#                     data[field] = [self.validate_file(file_data)]
#                 elif isinstance(file_data, list) and file_data and isinstance(file_data[0], (bytes, str)):
#                     data[field] = [self.validate_file(f) for f in file_data if f]
#                 else:
#                     data[field] = []
#             else:
#                 data[field] = []
#         return data

#     def validate(self, data):
#         data = self.unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])
#         for field in ["client_code", "client_first_name", "client_middle_name", "client_last_name",
#                       "contact_no", "email", "residential_address", "residential_pincode",
#                       "reference_remark", "occupation", "aadhaar_no", "pan_no", "seat_preference_other"]:
#             if field in data:
#                 data[field] = self.clean_str(data[field])
#         if 'client_type' in data:
#             data['client_type'] = self.clean_str(data['client_type'])
#             if data['client_type'] and data['client_type'] not in self.VALID_CLIENT_TYPES:
#                 raise serializers.ValidationError({
#                     'client_type': f"'{data['client_type']}' is not a valid choice. Valid options: {self.VALID_CLIENT_TYPES}"
#                 })
#         for field in ["client_salutation", "gender", "marital_status", "reference_from",
#                       "star_rating", "stay_preference", "room_preference", "extra_amenities",
#                       "seat_preference", "meal_preference", "fare_preference"]:
#             if field in data:
#                 data[field] = self.clean_str(data[field])
#                 try:
#                     choices = Client._meta.get_field(field).choices
#                     if choices and data[field] and data[field] not in [choice[0] for choice in choices]:
#                         raise serializers.ValidationError({
#                             field: f"'{data[field]}' is not a valid choice. Valid options: {[c[0] for c in choices]}"
#                         })
#                 except AttributeError:
#                     raise serializers.ValidationError({
#                         field: f"Field '{field}' does not have choices defined in the Client model."
#                     })
#         data["is_prepayment"] = self.clean_bool(data.get("is_prepayment"))
#         data["reference_id"] = self.safe_fk(Client, data.get("reference_id"), return_id=True)
#         data["dob"] = self.clean_date(data.get("dob"))
#         data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))
#         data["preferred_contact_method"] = self.normalize_preferred_contact_method(data.get("preferred_contact_method"))
#         for field in ["residential_country", "residential_state", "residential_city", "ref_preferred_airline"]:
#             if field in data:
#                 model = {
#                     "residential_country": Countries,
#                     "residential_state": State,
#                     "residential_city": Cities,
#                     "ref_preferred_airline": Airlines
#                 }[field]
#                 data[field] = self.safe_fk(model, data[field])
#         for field in ["client_passport", "client_visa", "travel_insurance", "client_companies",
#                       "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#                       "relationsWithOthers"]:
#             if field in data and isinstance(data[field], list):
#                 data[field] = [self.normalize_nested_item(item, field) for item in data[field] if item]
#         client_code = self._normalize_code(data.get("client_code"))
#         if client_code:
#             qs = Client.objects.filter(client_code=client_code)
#             if self.instance:
#                 qs = qs.exclude(client_id=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{client_code}' already exists."})
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in request_files:
#                 file = request_files.get(field)
#                 if file:
#                     data[field] = self.validate_file(file)
#                 else:
#                     data[field] = None
#             elif field in data:
#                 file_data = data.get(field)
#                 if file_data in ["", [], [""], "null"]:
#                     data[field] = None
#                 elif isinstance(file_data, (bytes, str)):
#                     data[field] = self.validate_file(file_data)
#                 else:
#                     data[field] = None
#             else:
#                 data[field] = None
#         return data

#     def normalize_nested_item(self, item, field_name):
#         if not isinstance(item, dict):
#             return item
#         item = self.unwrap_scalars(item)
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         if field_name == "client_passport":
#             item["passport_no"] = self.clean_str(item.get("passport_no"))
#             item["passport_expiry_date"] = self.clean_date(item.get("passport_expiry_date"))
#             file_key = f"{field_name}[{item.get('index', 0)}][passport_file][]"
#             item = self.handle_file_upload(item, {"passport_file": file_key}, request_files)
#         elif field_name == "client_visa":
#             item["visa_from_date"] = self.clean_date(item.get("visa_from_date"))
#             item["visa_to_date"] = self.clean_date(item.get("visa_to_date"))
#             item["ref_visa_country"] = self.safe_fk(Countries, item.get("ref_visa_country"))
#             item["visa_type"] = self.clean_str(item.get("visa_type"))
#             if item.get("visa_type") and item["visa_type"] not in [choice[0] for choice in ClientVisa.VISA_TYPE]:
#                 raise serializers.ValidationError({
#                     field_name: {item.get("index", 0): {"visa_type": f"'{item['visa_type']}' is not a valid choice. Valid options: {[c[0] for c in ClientVisa.VISA_TYPE]}"}}})
#             file_key = f"{field_name}[{item.get('index', 0)}][passport_size_photograph][]"
#             item = self.handle_file_upload(item, {"passport_size_photograph": file_key}, request_files)
#         elif field_name == "travel_insurance":
#             item["insurance_from_date"] = self.clean_date(item.get("insurance_from_date"))
#             item["insurance_to_date"] = self.clean_date(item.get("insurance_to_date"))
#             file_key = f"{field_name}[{item.get('index', 0)}][insurance_document][]"
#             item = self.handle_file_upload(item, {"insurance_document": file_key}, request_files)
#         elif field_name == "client_documents":
#             item["other_document_name"] = self.clean_str(item.get("other_document_name"))
#             file_key = f"{field_name}[{item.get('index', 0)}][other_document][]"
#             item = self.handle_file_upload(item, {"other_document": file_key}, request_files)
#         elif field_name == "client_companies":
#             item["designation"] = self.clean_str(item.get("designation"))
#             item["ref_company"] = self.safe_fk(Company, item.get("ref_company"))
#         elif field_name == "client_frequent_flyers":
#             item["ff_no"] = self.clean_str(item.get("ff_no"))
#             item["ref_airline"] = self.safe_fk(Airlines, item.get("ref_airline"))
#         elif field_name == "family_members":
#             item["dob"] = self.clean_date(item.get("dob"))
#             item["anniversary_date"] = self.clean_date(item.get("anniversary_date"))
#             item["clientCode"] = self._normalize_code(item.get("clientCode"))
#             if 'client_type' in item:
#                 item['client_type'] = self.clean_str(item['client_type'])
#                 if item['client_type'] and item['client_type'] not in self.VALID_CLIENT_TYPES:
#                     raise serializers.ValidationError({
#                         field_name: {item.get("index", 0): {
#                             'client_type': f"'{item['client_type']}' is not a valid choice. Valid options: {self.VALID_CLIENT_TYPES}"
#                         }}
#                     })
#             for field in ["client_salutation", "gender", "marital_status", "reference_from",
#                           "star_rating", "stay_preference", "room_preference", "extra_amenities",
#                           "seat_preference", "meal_preference", "fare_preference"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#                     try:
#                         choices = Client._meta.get_field(field).choices
#                         if choices and item[field] and item[field] not in [choice[0] for choice in choices]:
#                             raise serializers.ValidationError({
#                                 field_name: {item.get("index", 0): {
#                                     field: f"'{item[field]}' is not a valid choice. Valid options: {[c[0] for c in choices]}"
#                                 }}
#                             })
#                     except AttributeError:
#                         raise serializers.ValidationError({
#                             field_name: {item.get("index", 0): {
#                                 field: f"Field '{field}' does not have choices defined in the Client model."
#                             }}
#                         })
#             for field in ["client_first_name", "client_middle_name", "client_last_name",
#                           "contact_no", "email", "residential_address", "residential_pincode",
#                           "reference_remark", "occupation", "aadhaar_no", "pan_no", "seat_preference_other"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#             for field in ["residential_country", "residential_state", "residential_city"]:
#                 if field in item:
#                     model = {"residential_country": Countries, "residential_state": State, "residential_city": Cities}[field]
#                     item[field] = self.safe_fk(model, item[field])
#             # Handle single files for aadhaar_card_file and pan_card_file
#             file_map = {
#                 "aadhaar_card_file": f"family_members[{item.get('index', 0)}][aadhaarCard]",
#                 "pan_card_file": f"family_members[{item.get('index', 0)}][panCard]"
#             }
#             item = self.handle_file_upload_aadhar_pan(item, file_map, request_files)
#             for passport in item.get("fam_passport", []):
#                 passport["passport_no"] = self.clean_str(passport.get("passport_no"))
#                 passport["passport_expiry_date"] = self.clean_date(passport.get("passport_expiry_date"))
#                 file_key = f"family_members[{item.get('index', 0)}][fam_passport][{passport.get('index', 0)}][passport_file][]"
#                 passport = self.handle_file_upload(passport, {"passport_file": file_key}, request_files)
#         elif field_name == "relationsWithOthers":
#             item["relation_with_other_client_code"] = self.clean_str(item.get("relation_with_other_client_code"))
#         return item

#     def unwrap_scalars(self, data, skip_keys=None):
#         skip_keys = skip_keys or []
#         if not isinstance(data, dict):
#             if isinstance(data, list) and len(data) == 1 and not isinstance(data[0], (dict, list)) and data[0] not in ["", "null", "[]"]:
#                 return data[0]
#             return None if data in ["", [], [""], "null"] else data
#         result = {}
#         for k, v in data.items():
#             if k in skip_keys or isinstance(v, (dict, list)):
#                 result[k] = v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     result[k] = parsed[0] if isinstance(parsed, list) and len(parsed) == 1 and not isinstance(parsed[0], (dict, list)) else parsed
#                 except Exception:
#                     result[k] = v if v not in ["", "null", "[]"] else None
#             else:
#                 result[k] = None if v in ["", [], [""], "null"] else v
#         return result

#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj).select_related(
#             'country_code', 'residential_country', 'residential_state', 'residential_city', 'ref_preferred_airline'
#         ).prefetch_related(
#             'client_passport', 'client_visa', 'travel_insurance', 'client_companies', 'client_documents',
#             'client_frequent_flyers'
#         )
#         return FullClientSerializer(members, many=True, context=self.context).data

#     @transaction.atomic
#     def create(self, validated_data):
#         related_data = self.pop_related_data(validated_data)
#         client = self.create_client(validated_data)
#         self.create_related_objects(client, related_data)
#         return client

#     def pop_related_data(self, validated_data):
#         return {
#             "passports": validated_data.pop("client_passport", []),
#             "visas": validated_data.pop("client_visa", []),
#             "insurances": validated_data.pop("travel_insurance", []),
#             "documents": validated_data.pop("client_documents", []),
#             "companies": validated_data.pop("client_companies", []),
#             "frequent_flyers": validated_data.pop("client_frequent_flyers", []),
#             "family_members": validated_data.pop("family_members", []),
#             "fam_passports": validated_data.pop("fam_passport", []),
#             "relations": validated_data.pop("relationsWithOthers", []),
#             "fks": {
#                 "country_code": validated_data.pop("country_code", None),
#                 "residential_country": validated_data.pop("residential_country", None),
#                 "residential_state": validated_data.pop("residential_state", None),
#                 "residential_city": validated_data.pop("residential_city", None),
#                 "ref_preferred_airline": validated_data.pop("ref_preferred_airline", None),
#             }
#         }

#     def create_client(self, validated_data):
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = validated_data.get("client_type", "Primary Member")
#         validated_data["client_status"] = 1
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#             validated_data.get("preferred_contact_method")
#         )
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             validated_data["created_by"] = user
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in validated_data and validated_data[field] is not None:
#                 validated_data[field] = validated_data[field]
#             else:
#                 validated_data[field] = None
#         client = Client.objects.create(**validated_data)
#         return client

#     def create_related_objects(self, client, related_data):
#         fks = related_data["fks"]
#         if fks["country_code"]:
#             client.country_code = Countries.objects.get(id=fks["country_code"]["id"] if isinstance(fks["country_code"], dict) else fks["country_code"])
#         for fk_field, model in [
#             ("residential_country", Countries), ("residential_state", State),
#             ("residential_city", Cities), ("ref_preferred_airline", Airlines)
#         ]:
#             if fks[fk_field]:
#                 setattr(client, fk_field, self.safe_fk(model, fks[fk_field]))
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             client.updated_by = user
#         client.save()
#         self.create_nested_objects(client, related_data["passports"], ClientPassport, {"passport_file": "passport_file"})
#         self.create_nested_objects(client, related_data["visas"], ClientVisa, {"passport_size_photograph": "passport_size_photograph"})
#         self.create_nested_objects(client, related_data["insurances"], ClientTravelInsurance, {"insurance_document": "insurance_document"})
#         self.create_nested_objects(client, related_data["documents"], ClientDocument, {"other_document": "other_document"})
#         self.create_nested_objects(client, related_data["companies"], AssocClientCompany, {}, ref_field="ref_company")
#         self.create_nested_objects(client, related_data["frequent_flyers"], ClientFrequentFlyer, {}, ref_field="ref_airline")
#         prev_family_client = None
#         for fam_index, fam in enumerate(related_data["family_members"]):
#             if not any(fam.get(field) for field in ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]):
#                 continue
#             fam_data = self.prepare_family_member_data(fam, client, fam_index)
#             if user and user.is_authenticated:
#                 fam_data["created_by"] = user
#             for field in ["aadhaar_card_file", "pan_card_file"]:
#                 if field in fam_data and isinstance(fam_data[field], bytes):
#                     raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#                 fam_data[field] = fam_data.get(field, None)
#             family_client = Client.objects.create(**fam_data)
#             if fam.get("relation"):
#                 ClientRelation.objects.create(from_client=client, to_client=family_client, relation=fam["relation"])
#             if fam.get("crossrelation"):
#                 ClientRelation.objects.create(from_client=family_client, to_client=client, relation=fam["crossrelation"])
#             if prev_family_client and fam.get("relation"):
#                 ClientRelation.objects.create(from_client=prev_family_client, to_client=family_client, relation=fam["relation"])
#                 if fam.get("crossrelation"):
#                     ClientRelation.objects.create(from_client=family_client, to_client=prev_family_client, relation=fam["crossrelation"])
#             prev_family_client = family_client
#             for pd_index, pd in enumerate(fam.get("fam_passport", [])):
#                 if not pd.get("passport_no") or not pd.get("passport_expiry_date"):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 for file in pd.get("passport_file", []) or [None]:
#                     if isinstance(file, bytes):
#                         raise serializers.ValidationError(f"Invalid data for passport_file: Received bytes, expected a file object.")
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=pd["passport_no"],
#                         passport_expiry_date=pd["passport_expiry_date"],
#                         passport_file=file
#                     )
#         for rel in related_data["relations"]:
#             if not rel.get("toIndex"):
#                 continue
#             try:
#                 target_client = Client.objects.get(client_id=int(rel["toIndex"]))
#                 ClientRelation.objects.create(
#                     from_client=client,
#                     to_client=target_client,
#                     relation=rel.get("relation"),
#                     cross_relation=rel.get("crossRelation")
#                 )
#             except Client.DoesNotExist:
#                 continue

#     def prepare_family_member_data(self, fam, parent_client, fam_index):
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         fam_data = {
#             "ref_client": parent_client,
#             "client_type": "Family Member",
#             "client_status": 1,
#             "client_code": self._normalize_code(fam.get("clientCode")),
#             "client_salutation": self.clean_str(fam.get("salutation")),
#             "client_first_name": self.clean_str(fam.get("firstName")),
#             "client_middle_name": self.clean_str(fam.get("middleName")),
#             "client_last_name": self.clean_str(fam.get("lastName")),
#             "relation": self.clean_str(fam.get("relation")),
#             "crossrelation": self.clean_str(fam.get("crossrelation")),
#             "contact_no": self.clean_str(fam.get("contactNo")),
#             "email": self.clean_str(fam.get("email")),
#             "dob": self.clean_date(fam.get("dob")),
#             "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#             "gender": self.clean_str(fam.get("gender")),
#             "occupation": self.clean_str(fam.get("occupation")),
#             "aadhaar_no": self.clean_str(fam.get("aadhaarNo")),
#             "pan_no": self.clean_str(fam.get("panNo")),
#             "residential_address": self.clean_str(fam.get("residential_address")) or parent_client.residential_address,
#             "residential_country": self.safe_fk(Countries, fam.get("residential_country")) or parent_client.residential_country,
#             "residential_state": self.safe_fk(State, fam.get("residential_state")) or parent_client.residential_state,
#             "residential_city": self.safe_fk(Cities, fam.get("residential_city")) or parent_client.residential_city,
#             "residential_pincode": self.clean_str(fam.get("residential_pincode")) or parent_client.residential_pincode,
#         }
#         file_map = {
#             "aadhaar_card_file": f"family_members[{fam_index}][aadhaarCard]",
#             "pan_card_file": f"family_members[{fam_index}][panCard]"
#         }
#         fam_data = self.handle_file_upload_aadhar_pan(fam_data, file_map, request_files)
#         return fam_data

#     def create_nested_objects(self, client, data, model, file_map, ref_field=None):
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for item in data:
#             if not any(item.values()):
#                 continue
#             if ref_field:
#                 item[ref_field] = self.safe_fk(globals()[ref_field.capitalize()], item.get(ref_field))
#             file_field = list(file_map.keys())[0]
#             files = item.pop(file_field, [])
#             item = self.handle_file_upload(item, file_map, request_files)
#             for file in files or [None]:
#                 item_copy = item.copy()
#                 item_copy[file_field] = file
#                 model.objects.create(ref_client=client, **item_copy)

#     @transaction.atomic
#     def update(self, instance, validated_data):
#         related_data = self.pop_related_data(validated_data)
#         self.update_client(instance, validated_data)
#         self.update_related_objects(instance, related_data)
#         return instance

#     def update_client(self, instance, validated_data):
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in validated_data and validated_data[field] is not None:
#                 validated_data[field] = validated_data[field]
#             else:
#                 validated_data[field] = None
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             instance.updated_by = user
#         instance.save()
#         return instance

#     def update_related_objects(self, instance, related_data):
#         fks = related_data["fks"]
#         if fks["country_code"]:
#             instance.country_code = Countries.objects.get(id=fks["country_code"]["id"] if isinstance(fks["country_code"], dict) else fks["country_code"])
#         for fk_field, model in [
#             ("residential_country", Countries), ("residential_state", State),
#             ("residential_city", Cities), ("ref_preferred_airline", Airlines)
#         ]:
#             if fks[fk_field]:
#                 setattr(instance, fk_field, self.safe_fk(model, fks[fk_field]))
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             instance.updated_by = user
#         instance.save()
#         self.update_nested_objects(instance, related_data["passports"], ClientPassport, {"passport_file": "passport_file"})
#         self.update_nested_objects(instance, related_data["visas"], ClientVisa, {"passport_size_photograph": "passport_size_photograph"})
#         self.update_nested_objects(instance, related_data["insurances"], ClientTravelInsurance, {"insurance_document": "insurance_document"})
#         self.update_nested_objects(instance, related_data["documents"], ClientDocument, {"other_document": "other_document"})
#         self.update_nested_objects(instance, related_data["companies"], AssocClientCompany, {}, ref_field="ref_company")
#         self.update_nested_objects(instance, related_data["frequent_flyers"], ClientFrequentFlyer, {}, ref_field="ref_airline")
#         self.update_family_members(instance, related_data["family_members"], related_data["fam_passports"])
#         self.update_relations(instance, related_data["relations"])

#     def update_nested_objects(self, instance, data, model, file_map, ref_field=None):
#         keep_ids = []
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         file_field = list(file_map.keys())[0]
#         for item in data:
#             if not any(item.values()):
#                 continue
#             if ref_field:
#                 item[ref_field] = self.safe_fk(globals()[ref_field.capitalize()], item.get(ref_field))
#             files = item.pop(file_field, [])
#             item = self.handle_file_upload(item, file_map, request_files)
#             obj_id = item.pop("id", None)
#             if obj_id:
#                 model.objects.filter(id=obj_id, ref_client=instance).update(**item)
#                 keep_ids.append(obj_id)
#                 if files:
#                     model.objects.filter(id=obj_id, ref_client=instance).update(**{file_field: files[0]})
#             else:
#                 for file in files or [None]:
#                     item_copy = item.copy()
#                     item_copy[file_field] = file
#                     obj = model.objects.create(ref_client=instance, **item_copy)
#                     keep_ids.append(obj.id)
#         model.objects.filter(ref_client=instance).exclude(id__in=keep_ids).delete()

#     def update_family_members(self, instance, family_data, fam_passports):
#         keep_ids = []
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         user = self.context.get("request").user if self.context.get("request") else None
#         for fam_index, fam in enumerate(family_data):
#             if not any(fam.get(field) for field in ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]):
#                 continue
#             fam_data = self.prepare_family_member_data(fam, instance, fam_index)
#             obj_id = fam.get("id")
#             for field in ["aadhaar_card_file", "pan_card_file"]:
#                 if field in fam_data and isinstance(fam_data[field], bytes):
#                     raise serializers.ValidationError(f"Invalid data for {field}: Received bytes, expected a file object.")
#                 fam_data[field] = fam_data.get(field, None)
#             if obj_id:
#                 Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam_data)
#                 family_client = Client.objects.get(client_id=obj_id)
#                 if user and user.is_authenticated:
#                     family_client.updated_by = user
#                     family_client.save()
#                 keep_ids.append(obj_id)
#             else:
#                 if user and user.is_authenticated:
#                     fam_data["created_by"] = user
#                 family_client = Client.objects.create(**fam_data)
#                 keep_ids.append(family_client.client_id)
#             fam_passport_data = fam.get("fam_passport", [])
#             keep_passport_ids = []
#             for pd_index, pd in enumerate(fam_passport_data):
#                 if not pd.get("passport_no") or not pd.get("passport_expiry_date"):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 files = pd.get("passport_file", []) or [None]
#                 obj_id = pd.pop("id", None)
#                 if obj_id:
#                     ClientPassport.objects.filter(id=obj_id, ref_client=family_client).update(**pd)
#                     keep_passport_ids.append(obj_id)
#                     if files:
#                         if isinstance(files[0], bytes):
#                             raise serializers.ValidationError(f"Invalid data for passport_file: Received bytes, expected a file object.")
#                         ClientPassport.objects.filter(id=obj_id, ref_client=family_client).update(passport_file=files[0])
#                 else:
#                     for file in files:
#                         if isinstance(file, bytes):
#                             raise serializers.ValidationError(f"Invalid data for passport_file: Received bytes, expected a file object.")
#                         pd_copy = pd.copy()
#                         pd_copy["passport_file"] = file
#                         obj = ClientPassport.objects.create(ref_client=family_client, **pd_copy)
#                         keep_passport_ids.append(obj.id)
#             ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=keep_passport_ids).delete()
#         Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()

#     def update_relations(self, instance, relations):
#         keep_ids = []
#         for rel in relations:
#             if not rel.get("toIndex"):
#                 continue
#             try:
#                 target_client = Client.objects.get(client_id=int(rel["toIndex"]))
#                 obj, created = ClientRelation.objects.update_or_create(
#                     from_client=instance,
#                     to_client=target_client,
#                     defaults={
#                         "relation": rel.get("relation"),
#                         "cross_relation": rel.get("crossRelation")
#                     }
#                 )
#                 keep_ids.append(obj.id)
#             except Client.DoesNotExist:
#                 continue
#         ClientRelation.objects.filter(from_client=instance).exclude(id__in=keep_ids).delete()

#     def to_representation(self, instance):
#         data = super().to_representation(instance)
#         related_fields = {
#             "client_passport": ClientPassportSerializer,
#             "client_visa": ClientVisaSerializer,
#             "travel_insurance": ClientTravelInsuranceSerializer,
#             "client_companies": AssocClientCompanySerializer,
#             "client_documents": OtherDocumentSerializer,
#             "client_frequent_flyers": FrequentflyerSerializer
#         }
#         for field, serializer_class in related_fields.items():
#             if hasattr(instance, field):
#                 data[field] = serializer_class(getattr(instance, field).all(), many=True, context=self.context).data
#         return data
    
# class FullClientSerializer(serializers.ModelSerializer):
#     client_passport = serializers.ListField(child=serializers.DictField(), required=False)
#     client_visa = serializers.ListField(child=serializers.DictField(), required=False)
#     travel_insurance = serializers.ListField(child=serializers.DictField(), required=False)
#     client_companies = serializers.ListField(child=serializers.DictField(), required=False)
#     client_documents = serializers.ListField(child=serializers.DictField(), required=False)
#     client_frequent_flyers = serializers.ListField(child=serializers.DictField(), required=False)
#     family_members = serializers.ListField(child=serializers.DictField(), required=False)
#     relationsWithOthers = serializers.ListField(child=serializers.DictField(), required=False)
#     fam_passport = serializers.ListField(child=serializers.DictField(), required=False)
#     country_code = serializers.CharField(required=False, allow_null=True)
#     residential_country = serializers.CharField(required=False, allow_null=True)
#     residential_state = serializers.CharField(required=False, allow_null=True)
#     residential_city = serializers.CharField(required=False, allow_null=True)
#     ref_preferred_airline = serializers.CharField(required=False, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             'client_id', 'client_code', 'client_type', 'client_salutation', 'client_first_name',
#             'client_middle_name', 'client_last_name', 'country_code', 'contact_no', 'email',
#             'residential_country', 'residential_state', 'residential_city', 'residential_address',
#             'residential_pincode', 'reference_id', 'reference_from', 'reference_remark',
#             'occupation', 'aadhaar_no', 'pan_no', 'dob', 'gender', 'marital_status',
#             'anniversary_date', 'star_rating', 'stay_preference', 'room_preference',
#             'extra_amenities', 'seat_preference', 'seat_preference_other', 'meal_preference',
#             'fare_preference', 'is_prepayment', 'preferred_contact_method', 'client_passport',
#             'client_visa', 'travel_insurance', 'client_companies', 'client_documents',
#             'client_frequent_flyers', 'family_members', 'relationsWithOthers', 'fam_passport',
#             'residential_country', 'residential_state', 'residential_city', 'ref_preferred_airline',
#             'aadhaar_card_file', 'pan_card_file', 'created_at', 'updated_at', 'created_by', 'updated_by'
#         ]

#     VALID_CLIENT_TYPES = ["Primary Member", "Family Member"]

#     def _normalize_code(self, code):
#         """Normalize client code by removing spaces and converting to uppercase."""
#         return code.strip().upper() if code else None

#     def clean_str(self, value):
#         """Clean string values by stripping and handling null/empty cases."""
#         if value in ["", [], [""], "null"]:
#             return None
#         return str(value).strip()

#     def clean_date(self, value):
#         """Clean date values, ensuring valid format."""
#         if not value or value in ["", [], [""], "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if value else None
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 value = ast.literal_eval(value)
#                 value = value[0] if isinstance(value, list) and value else None
#             except Exception:
#                 pass
#         return value

#     def clean_bool(self, value):
#         """Clean boolean values."""
#         if isinstance(value, (list, str)) and value in ["", [], [""], "null"]:
#             return False
#         return bool(value)

#     def normalize_preferred_contact_method(self, value):
#         """Normalize preferred_contact_method to a list."""
#         if not value or value in ["", [], [""], "null"]:
#             return []
#         if isinstance(value, str):
#             try:
#                 value = ast.literal_eval(value) if value.strip().startswith("[") and value.strip().endswith("]") else [value]
#             except Exception:
#                 value = [value]
#         if isinstance(value, list):
#             return [str(v).strip() for v in value if v]
#         return [str(value).strip()]

#     def safe_fk(self, model_class, value, return_id=False):
#         """Safely resolve foreign key values from strings, dictionaries, or IDs."""
#         if not value or value in ["", [], [""], "null"]:
#             return None
#         if isinstance(value, list):
#             value = value[0] if len(value) == 1 else None
#         if isinstance(value, str) and value.strip().startswith("[") and value.strip().endswith("]"):
#             try:
#                 parsed = ast.literal_eval(value)
#                 value = parsed[0] if isinstance(parsed, list) and len(parsed) == 1 else None
#             except Exception:
#                 pass
#         try:
#             lookup_field = 'client_id' if model_class == Client else model_class._meta.pk.name
#             if isinstance(value, dict):
#                 value = value.get('id') or value.get('code') or value.get(lookup_field)
#             if isinstance(value, str):
#                 # Try to convert to int for ID-based lookups
#                 try:
#                     value = int(value)
#                 except ValueError:
#                     # Handle code-based lookups for Countries
#                     if model_class == Countries and lookup_field != 'code':
#                         lookup_field = 'code'
#             instance = model_class.objects.get(**{lookup_field: value}) if model_class.objects.filter(**{lookup_field: value}).exists() else None
#             if instance and return_id:
#                 return getattr(instance, lookup_field)
#             return instance
#         except (ValueError, TypeError, AttributeError, model_class.DoesNotExist):
#             raise serializers.ValidationError(f"Invalid {lookup_field} for {model_class.__name__}: {value}")

#     def unwrap_scalars(self, data, skip_keys=None):
#         """Unwrap scalar values, skipping file fields and nested structures."""
#         skip_keys = skip_keys or []
#         skip_keys += ["aadhaar_card_file", "pan_card_file"]  # Skip file fields
#         if not isinstance(data, dict):
#             if isinstance(data, list) and len(data) == 1 and not isinstance(data[0], (dict, list)) and data[0] not in ["", "null", "[]"]:
#                 return data[0]
#             return None if data in ["", [], [""], "null"] else data
#         result = {}
#         for k, v in data.items():
#             if k in skip_keys or isinstance(v, (dict, list)):
#                 result[k] = v
#             elif isinstance(v, str) and v.strip().startswith("[") and v.strip().endswith("]"):
#                 try:
#                     parsed = ast.literal_eval(v)
#                     result[k] = parsed[0] if isinstance(parsed, list) and len(parsed) == 1 and not isinstance(parsed[0], (dict, list)) else parsed
#                 except Exception:
#                     result[k] = v if v not in ["", "null", "[]"] else None
#             else:
#                 result[k] = None if v in ["", [], [""], "null"] else v
#         return result

#     def validate_file(self, file, max_size=100 * 1024 * 1024, allowed_types=['application/pdf', 'image/jpeg', 'image/png', 'image/webp']):
#         """Validate file objects for size and type."""
#         if not file or file in ["", [], [""], "null"]:
#             return None
#         if isinstance(file, bytes):
#             raise serializers.ValidationError(f"Invalid file data for {file}. Expected a file object, got bytes. Use convert_binary_to_file first.")
#         if not hasattr(file, 'size') or not hasattr(file, 'content_type'):
#             raise serializers.ValidationError(f"Invalid file data for {file}. Ensure correct file object.")
#         if len(file.name) > 255:
#             raise serializers.ValidationError(f"File name {file.name} is too long. Maximum length is 255 characters.")
#         if file.size > max_size:
#             raise serializers.ValidationError(f"File {file.name} exceeds maximum size of {max_size / 1024 / 1024} MB.")
#         if file.content_type not in allowed_types:
#             raise serializers.ValidationError(f"File {file.name} has invalid type {file.content_type}. Allowed: {allowed_types}.")
#         return file

#     def convert_binary_to_file(self, data, field_name, content_type=None):
#         """Convert binary or base64-encoded data to an InMemoryUploadedFile."""
#         if isinstance(data, bytes):
#             # Raw binary data
#             file_name = f"{field_name}_{uuid.uuid4()}.bin"
#             content_type = content_type or mimetypes.guess_type(file_name)[0] or "application/octet-stream"
#             file_data = BytesIO(data)
#             file = InMemoryUploadedFile(
#                 file=file_data,
#                 field_name=field_name,
#                 name=file_name,
#                 content_type=content_type,
#                 size=len(data),
#                 charset=None
#             )
#             return file
#         elif isinstance(data, str) and data.startswith("data:"):
#             # Base64-encoded data
#             try:
#                 header, encoded = data.split(",", 1)
#                 mime_type = header.split(";")[0].replace("data:", "")
#                 file_data = base64.b64decode(encoded)
#                 file_name = f"{field_name}_{uuid.uuid4()}.{mime_type.split('/')[-1]}"
#                 file = InMemoryUploadedFile(
#                     file=BytesIO(file_data),
#                     field_name=field_name,
#                     name=file_name,
#                     content_type=mime_type,
#                     size=len(file_data),
#                     charset=None
#                 )
#                 return file
#             except Exception as e:
#                 raise serializers.ValidationError(f"Invalid base64 data for {field_name}: {str(e)}")
#         return data

#     def handle_file_upload(self, data, file_map, request_files):
#         """Handle file uploads for fields that support multiple files."""
#         for field, req_field in file_map.items():
#             if req_field in request_files:
#                 files = request_files.getlist(req_field)
#                 data[field] = [self.validate_file(f) for f in files if f] if files else []
#             elif field in data and data[field] in ["", [], [""], "null"]:
#                 data[field] = []
#         return data

#     def validate(self, data):
#         """Validate and clean input data, handling binary files and string-based foreign keys."""
#         data = self.unwrap_scalars(data, skip_keys=[
#             "client_passport", "client_visa", "travel_insurance", "client_companies",
#             "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#             "relationsWithOthers"
#         ])
#         for field in ["client_code", "client_first_name", "client_middle_name", "client_last_name",
#                     "contact_no", "email", "residential_address", "residential_pincode",
#                     "reference_remark", "occupation", "aadhaar_no", "pan_no", "seat_preference_other"]:
#             if field in data:
#                 data[field] = self.clean_str(data[field])
#         if 'client_type' in data:
#             data['client_type'] = self.clean_str(data['client_type'])
#             if data['client_type'] and data['client_type'] not in self.VALID_CLIENT_TYPES:
#                 raise serializers.ValidationError({
#                     'client_type': f"'{data['client_type']}' is not a valid choice. Valid options: {self.VALID_CLIENT_TYPES}"
#                 })
#         for field in ["client_salutation", "gender", "marital_status", "reference_from",
#                     "star_rating", "stay_preference", "room_preference", "extra_amenities",
#                     "seat_preference", "meal_preference", "fare_preference"]:
#             if field in data:
#                 data[field] = self.clean_str(data[field])
#                 try:
#                     choices = Client._meta.get_field(field).choices
#                     if choices and data[field] and data[field] not in [choice[0] for choice in choices]:
#                         raise serializers.ValidationError({
#                             field: f"'{data[field]}' is not a valid choice. Valid options: {[c[0] for c in choices]}"
#                         })
#                 except AttributeError:
#                     raise serializers.ValidationError({
#                         field: f"Field '{field}' does not have choices defined in the Client model."
#                     })
#         data["is_prepayment"] = self.clean_bool(data.get("is_prepayment"))
#         data["reference_id"] = self.safe_fk(Client, data.get("reference_id"), return_id=True)
#         data["dob"] = self.clean_date(data.get("dob"))
#         data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))
#         data["preferred_contact_method"] = self.normalize_preferred_contact_method(data.get("preferred_contact_method"))
#         for field in ["country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline"]:
#             if field in data:
#                 model = {
#                     "country_code": Countries,
#                     "residential_country": Countries,
#                     "residential_state": State,
#                     "residential_city": Cities,
#                     "ref_preferred_airline": Airlines
#                 }[field]
#                 data[field] = self.safe_fk(model, data[field])
#         for field in ["client_passport", "client_visa", "travel_insurance", "client_companies",
#                     "client_documents", "client_frequent_flyers", "family_members", "fam_passport",
#                     "relationsWithOthers"]:
#             if field in data and isinstance(data[field], list):
#                 data[field] = [self.normalize_nested_item(item, field) for item in data[field] if item]
#         client_code = self._normalize_code(data.get("client_code"))
#         if client_code:
#             qs = Client.objects.filter(client_code=client_code)
#             if self.instance:
#                 qs = qs.exclude(client_id=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({"client_code": f"Client code '{client_code}' already exists."})
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             if field in request_files:
#                 file = request_files.get(field)
#                 if file:
#                     data[field] = self.validate_file(file)
#                 else:
#                     data[field] = None
#             elif field in data:
#                 data[field] = self.convert_binary_to_file(data[field], field, content_type="application/pdf")
#                 if data[field] is not None:
#                     data[field] = self.validate_file(data[field])
#             else:
#                 data[field] = None
#         return data

#     def normalize_nested_item(self, item, field_name):
#         """Normalize nested items, handling binary files and string-based foreign keys."""
#         if not isinstance(item, dict):
#             return item
#         item = self.unwrap_scalars(item)
#         if field_name == "client_passport":
#             item["passport_no"] = self.clean_str(item.get("passport_no"))
#             item["passport_expiry_date"] = self.clean_date(item.get("passport_expiry_date"))
#             file_key = f"{field_name}[{item.get('index', 0)}][passport_file][]"
#             item = self.handle_file_upload(item, {"passport_file": file_key}, self.context.get("request").FILES)
#         elif field_name == "client_visa":
#             item["visa_from_date"] = self.clean_date(item.get("visa_from_date"))
#             item["visa_to_date"] = self.clean_date(item.get("visa_to_date"))
#             item["ref_visa_country"] = self.safe_fk(Countries, item.get("ref_visa_country"))
#             item["visa_type"] = self.clean_str(item.get("visa_type"))
#             if item.get("visa_type") and item["visa_type"] not in [choice[0] for choice in ClientVisa.VISA_TYPE]:
#                 raise serializers.ValidationError({
#                     field_name: {item.get("index", 0): {"visa_type": f"'{item['visa_type']}' is not a valid choice. Valid options: {[c[0] for c in ClientVisa.VISA_TYPE]}"}}})
#             file_key = f"{field_name}[{item.get('index', 0)}][passport_size_photograph][]"
#             item = self.handle_file_upload(item, {"passport_size_photograph": file_key}, self.context.get("request").FILES)
#         elif field_name == "travel_insurance":
#             item["insurance_from_date"] = self.clean_date(item.get("insurance_from_date"))
#             item["insurance_to_date"] = self.clean_date(item.get("insurance_to_date"))
#             file_key = f"{field_name}[{item.get('index', 0)}][insurance_document][]"
#             item = self.handle_file_upload(item, {"insurance_document": file_key}, self.context.get("request").FILES)
#         elif field_name == "client_documents":
#             item["other_document_name"] = self.clean_str(item.get("other_document_name"))
#             file_key = f"{field_name}[{item.get('index', 0)}][other_document][]"
#             item = self.handle_file_upload(item, {"other_document": file_key}, self.context.get("request").FILES)
#         elif field_name == "client_companies":
#             item["designation"] = self.clean_str(item.get("designation"))
#             item["ref_company"] = self.safe_fk(Company, item.get("ref_company"))
#         elif field_name == "client_frequent_flyers":
#             item["ff_no"] = self.clean_str(item.get("ff_no"))
#             item["ref_airline"] = self.safe_fk(Airlines, item.get("ref_airline"))
#         elif field_name == "family_members":
#             item["dob"] = self.clean_date(item.get("dob"))
#             item["anniversary_date"] = self.clean_date(item.get("anniversary_date"))
#             item["clientCode"] = self._normalize_code(item.get("clientCode"))
#             if 'client_type' in item:
#                 item['client_type'] = self.clean_str(item['client_type'])
#                 if item['client_type'] and item['client_type'] not in self.VALID_CLIENT_TYPES:
#                     raise serializers.ValidationError({
#                         field_name: {item.get("index", 0): {
#                             'client_type': f"'{item['client_type']}' is not a valid choice. Valid options: {self.VALID_CLIENT_TYPES}"
#                         }}
#                     })
#             for field in ["client_salutation", "gender", "marital_status", "reference_from",
#                         "star_rating", "stay_preference", "room_preference", "extra_amenities",
#                         "seat_preference", "meal_preference", "fare_preference"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#                     try:
#                         choices = Client._meta.get_field(field).choices
#                         if choices and item[field] and item[field] not in [choice[0] for choice in choices]:
#                             raise serializers.ValidationError({
#                                 field_name: {item.get("index", 0): {
#                                     field: f"'{item[field]}' is not a valid choice. Valid options: {[c[0] for c in choices]}"
#                                 }}
#                             })
#                     except AttributeError:
#                         raise serializers.ValidationError({
#                             field_name: {item.get("index", 0): {
#                                 field: f"Field '{field}' does not have choices defined in the Client model."
#                             }}
#                         })
#             for field in ["client_first_name", "client_middle_name", "client_last_name",
#                         "contact_no", "email", "residential_address", "residential_pincode",
#                         "reference_remark", "occupation", "aadhaar_no", "pan_no", "seat_preference_other"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#             for field in ["country_code", "residential_country", "residential_state", "residential_city"]:
#                 if field in item:
#                     model = {
#                         "country_code": Countries,
#                         "residential_country": Countries,
#                         "residential_state": State,
#                         "residential_city": Cities
#                     }[field]
#                     item[field] = self.safe_fk(model, item[field])
#             request_files = self.context.get("request").FILES if self.context.get("request") else {}
#             for field, req_field in [
#                 ("aadhaar_card_file", f"family_members[{item.get('index', 0)}][aadhaarCard]"),
#                 ("pan_card_file", f"family_members[{item.get('index', 0)}][panCard]")
#             ]:
#                 if req_field in request_files:
#                     file = request_files.get(req_field)
#                     item[field] = self.validate_file(file) if file else None
#                 elif field in item:
#                     item[field] = self.convert_binary_to_file(item[field], field, content_type="application/pdf")
#                     if item[field] is not None:
#                         item[field] = self.validate_file(item[field])
#                 else:
#                     item[field] = None
#             for passport in item.get("fam_passport", []):
#                 passport["passport_no"] = self.clean_str(passport.get("passport_no"))
#                 passport["passport_expiry_date"] = self.clean_date(passport.get("passport_expiry_date"))
#                 file_key = f"family_members[{item.get('index', 0)}][fam_passport][{passport.get('index', 0)}][passport_file][]"
#                 passport = self.handle_file_upload(passport, {"passport_file": file_key}, self.context.get("request").FILES)
#         elif field_name == "relationsWithOthers":
#             item["relation_with_other_client_code"] = self.clean_str(item.get("relation_with_other_client_code"))
#         return item
    
#     def create_client(self, validated_data):
#         """Create a new Client instance."""
#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
#         validated_data["client_type"] = validated_data.get("client_type", "Primary Member")
#         validated_data["client_status"] = 1
#         validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
#             validated_data.get("preferred_contact_method")
#         )
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             validated_data["created_by"] = user
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[field] = validated_data.get(field, None)
#         client = Client.objects.create(**validated_data)
#         return client

#     def update_client(self, instance, validated_data):
#         """Update an existing Client instance."""
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             validated_data[field] = validated_data.get(field, None)
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             instance.updated_by = user
#         instance.save()
#         return instance

#     def create_nested_objects(self, client, data, model_class, file_map, ref_field="ref_client"):
#         """Create nested objects for related models."""
#         for index, item in enumerate(data):
#             if not item:
#                 continue
#             for field in file_map.values():
#                 item[field] = item.get(field, []) or []
#             for field in ["passport_no", "other_document_name", "designation", "ff_no", "visa_type"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#             for field in ["passport_expiry_date", "visa_from_date", "visa_to_date",
#                           "insurance_from_date", "insurance_to_date"]:
#                 if field in item:
#                     item[field] = self.clean_date(item[field])
#             if "ref_visa_country" in item:
#                 item["ref_visa_country"] = self.safe_fk(Countries, item.get("ref_visa_country"))
#             if "ref_company" in item:
#                 item["ref_company"] = self.safe_fk(Company, item.get("ref_company"))
#             if "ref_airline" in item:
#                 item["ref_airline"] = self.safe_fk(Airlines, item.get("ref_airline"))
#             item[ref_field] = client
#             for file_field, req_field in file_map.items():
#                 files = item.get(file_field, [])
#                 for file in files or [None]:
#                     if file is not None:
#                         file = self.validate_file(file)
#                     item_copy = item.copy()
#                     item_copy[file_field] = file
#                     model_class.objects.create(**item_copy)

#     def update_nested_objects(self, instance, data, model_class, file_map, ref_field="ref_client"):
#         """Update nested objects for related models."""
#         keep_ids = []
#         for index, item in enumerate(data):
#             if not item:
#                 continue
#             obj_id = item.pop("id", None)
#             for field in file_map.values():
#                 item[field] = item.get(field, []) or []
#             for field in ["passport_no", "other_document_name", "designation", "ff_no", "visa_type"]:
#                 if field in item:
#                     item[field] = self.clean_str(item[field])
#             for field in ["passport_expiry_date", "visa_from_date", "visa_to_date",
#                           "insurance_from_date", "insurance_to_date"]:
#                 if field in item:
#                     item[field] = self.clean_date(item[field])
#             if "ref_visa_country" in item:
#                 item["ref_visa_country"] = self.safe_fk(Countries, item.get("ref_visa_country"))
#             if "ref_company" in item:
#                 item["ref_company"] = self.safe_fk(Company, item.get("ref_company"))
#             if "ref_airline" in item:
#                 item["ref_airline"] = self.safe_fk(Airlines, item.get("ref_airline"))
#             if obj_id:
#                 model_class.objects.filter(id=obj_id, **{ref_field: instance}).update(**item)
#                 keep_ids.append(obj_id)
#                 for file_field, req_field in file_map.items():
#                     files = item.get(file_field, [])
#                     if files and files[0] is not None:
#                         model_class.objects.filter(id=obj_id, **{ref_field: instance}).update(**{file_field: self.validate_file(files[0])})
#             else:
#                 item[ref_field] = instance
#                 for file_field, req_field in file_map.items():
#                     files = item.get(file_field, [])
#                     for file in files or [None]:
#                         if file is not None:
#                             file = self.validate_file(file)
#                         item_copy = item.copy()
#                         item_copy[file_field] = file
#                         obj = model_class.objects.create(**item_copy)
#                         keep_ids.append(obj.id)
#         model_class.objects.filter(**{ref_field: instance}).exclude(id__in=keep_ids).delete()

#     def prepare_family_member_data(self, fam, client, index):
#         """Prepare data for family member creation."""
#         fam_data = {
#             "client_code": self._normalize_code(fam.get("clientCode", f"{client.client_code}_{index + 1}")),
#             "client_type": fam.get("client_type", "Family Member"),
#             "client_salutation": self.clean_str(fam.get("client_salutation")),
#             "client_first_name": self.clean_str(fam.get("firstName")),
#             "client_middle_name": self.clean_str(fam.get("client_middle_name")),
#             "client_last_name": self.clean_str(fam.get("lastName")),
#             "country_code": self.safe_fk(Countries, fam.get("country_code")),
#             "contact_no": self.clean_str(fam.get("contact_no")),
#             "email": self.clean_str(fam.get("email")),
#             "residential_country": self.safe_fk(Countries, fam.get("residential_country")),
#             "residential_state": self.safe_fk(State, fam.get("residential_state")),
#             "residential_city": self.safe_fk(Cities, fam.get("residential_city")),
#             "residential_address": self.clean_str(fam.get("residential_address")),
#             "residential_pincode": self.clean_str(fam.get("residential_pincode")),
#             "reference_id": self.safe_fk(Client, fam.get("reference_id"), return_id=True),
#             "reference_from": self.clean_str(fam.get("reference_from")),
#             "reference_remark": self.clean_str(fam.get("reference_remark")),
#             "occupation": self.clean_str(fam.get("occupation")),
#             "aadhaar_no": self.clean_str(fam.get("aadhaar_no")),
#             "pan_no": self.clean_str(fam.get("pan_no")),
#             "dob": self.clean_date(fam.get("dob")),
#             "gender": self.clean_str(fam.get("gender")),
#             "marital_status": self.clean_str(fam.get("marital_status")),
#             "anniversary_date": self.clean_date(fam.get("anniversary_date")),
#             "star_rating": self.clean_str(fam.get("star_rating")),
#             "stay_preference": self.clean_str(fam.get("stay_preference")),
#             "room_preference": self.clean_str(fam.get("room_preference")),
#             "extra_amenities": self.clean_str(fam.get("extra_amenities")),
#             "seat_preference": self.clean_str(fam.get("seat_preference")),
#             "seat_preference_other": self.clean_str(fam.get("seat_preference_other")),
#             "meal_preference": self.clean_str(fam.get("meal_preference")),
#             "fare_preference": self.clean_str(fam.get("fare_preference")),
#             "is_prepayment": self.clean_bool(fam.get("is_prepayment")),
#             "preferred_contact_method": self.normalize_preferred_contact_method(fam.get("preferred_contact_method")),
#             "ref_client": client,
#             "aadhaar_card_file": fam.get("aadhaar_card_file"),
#             "pan_card_file": fam.get("pan_card_file")
#         }
#         return {k: v for k, v in fam_data.items() if v is not None}

#     def create_related_objects(self, client, related_data):
#         """Create related objects for the client."""
#         fks = related_data["fks"]
#         if fks["country_code"]:
#             client.country_code = self.safe_fk(Countries, fks["country_code"])
#         for fk_field, model in [
#             ("residential_country", Countries), ("residential_state", State),
#             ("residential_city", Cities), ("ref_preferred_airline", Airlines)
#         ]:
#             if fks[fk_field]:
#                 setattr(client, fk_field, self.safe_fk(model, fks[fk_field]))
#         user = self.context.get("request").user if self.context.get("request") else None
#         if user and user.is_authenticated:
#             client.updated_by = user
#         client.save()
#         self.create_nested_objects(client, related_data["passports"], ClientPassport, {"passport_file": "passport_file"})
#         self.create_nested_objects(client, related_data["visas"], ClientVisa, {"passport_size_photograph": "passport_size_photograph"})
#         self.create_nested_objects(client, related_data["insurances"], ClientTravelInsurance, {"insurance_document": "insurance_document"})
#         self.create_nested_objects(client, related_data["documents"], ClientDocument, {"other_document": "other_document"})
#         self.create_nested_objects(client, related_data["companies"], AssocClientCompany, {}, ref_field="ref_company")
#         self.create_nested_objects(client, related_data["frequent_flyers"], ClientFrequentFlyer, {}, ref_field="ref_airline")
#         prev_family_client = None
#         for fam_index, fam in enumerate(related_data["family_members"]):
#             if not any(fam.get(field) for field in ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]):
#                 continue
#             fam_data = self.prepare_family_member_data(fam, client, fam_index)
#             if user and user.is_authenticated:
#                 fam_data["created_by"] = user
#             for field in ["aadhaar_card_file", "pan_card_file"]:
#                 if field in fam_data and fam_data[field] is not None:
#                     fam_data[field] = self.validate_file(fam_data[field])
#                 else:
#                     fam_data[field] = None
#             family_client = Client.objects.create(**fam_data)
#             if fam.get("relation"):
#                 ClientRelation.objects.create(from_client=client, to_client=family_client, relation=fam["relation"])
#             if fam.get("crossrelation"):
#                 ClientRelation.objects.create(from_client=family_client, to_client=client, relation=fam["crossrelation"])
#             if prev_family_client and fam.get("relation"):
#                 ClientRelation.objects.create(from_client=prev_family_client, to_client=family_client, relation=fam["relation"])
#                 if fam.get("crossrelation"):
#                     ClientRelation.objects.create(from_client=family_client, to_client=prev_family_client, relation=fam["crossrelation"])
#             prev_family_client = family_client
#             for pd_index, pd in enumerate(fam.get("fam_passport", [])):
#                 if not pd.get("passport_no") or not pd.get("passport_expiry_date"):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 for file in pd.get("passport_file", []) or [None]:
#                     if file is not None:
#                         file = self.validate_file(file)
#                     ClientPassport.objects.create(
#                         ref_client=family_client,
#                         passport_no=pd["passport_no"],
#                         passport_expiry_date=pd["passport_expiry_date"],
#                         passport_file=file
#                     )
#         for rel in related_data["relations"]:
#             if not rel.get("toIndex"):
#                 continue
#             try:
#                 target_client = Client.objects.get(client_id=int(rel["toIndex"]))
#                 ClientRelation.objects.create(
#                     from_client=client,
#                     to_client=target_client,
#                     relation=rel.get("relation"),
#                     cross_relation=rel.get("crossRelation")
#                 )
#             except Client.DoesNotExist:
#                 continue

#     def update_family_members(self, instance, family_data, fam_passports):
#         """Update family members."""
#         keep_ids = []
#         request_files = self.context.get("request").FILES if self.context.get("request") else {}
#         user = self.context.get("request").user if self.context.get("request") else None
#         for fam_index, fam in enumerate(family_data):
#             if not any(fam.get(field) for field in ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]):
#                 continue
#             fam_data = self.prepare_family_member_data(fam, instance, fam_index)
#             obj_id = fam.get("id")
#             for field in ["aadhaar_card_file", "pan_card_file"]:
#                 if field in fam_data and fam_data[field] is not None:
#                     fam_data[field] = self.validate_file(fam_data[field])
#                 else:
#                     fam_data[field] = None
#             if obj_id:
#                 Client.objects.filter(client_id=obj_id, ref_client=instance).update(**fam_data)
#                 family_client = Client.objects.get(client_id=obj_id)
#                 if user and user.is_authenticated:
#                     family_client.updated_by = user
#                     family_client.save()
#                 keep_ids.append(obj_id)
#             else:
#                 if user and user.is_authenticated:
#                     fam_data["created_by"] = user
#                 family_client = Client.objects.create(**fam_data)
#                 keep_ids.append(family_client.client_id)
#             fam_passport_data = fam.get("fam_passport", [])
#             keep_passport_ids = []
#             for pd_index, pd in enumerate(fam_passport_data):
#                 if not pd.get("passport_no") or not pd.get("passport_expiry_date"):
#                     continue
#                 pd["passport_no"] = self.clean_str(pd.get("passport_no"))
#                 pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
#                 files = pd.get("passport_file", []) or [None]
#                 obj_id = pd.pop("id", None)
#                 if obj_id:
#                     ClientPassport.objects.filter(id=obj_id, ref_client=family_client).update(**pd)
#                     keep_passport_ids.append(obj_id)
#                     if files and files[0] is not None:
#                         ClientPassport.objects.filter(id=obj_id, ref_client=family_client).update(passport_file=self.validate_file(files[0]))
#                 else:
#                     for file in files:
#                         if file is not None:
#                             file = self.validate_file(file)
#                         pd_copy = pd.copy()
#                         pd_copy["passport_file"] = file
#                         obj = ClientPassport.objects.create(ref_client=family_client, **pd_copy)
#                         keep_passport_ids.append(obj.id)
#             ClientPassport.objects.filter(ref_client=family_client).exclude(id__in=keep_passport_ids).delete()
#         Client.objects.filter(ref_client=instance).exclude(client_id__in=keep_ids).delete()

#     @transaction.atomic
#     def create(self, validated_data):
#         """Create a new client with related objects."""
#         related_data = {
#             "passports": validated_data.pop("client_passport", []),
#             "visas": validated_data.pop("client_visa", []),
#             "insurances": validated_data.pop("travel_insurance", []),
#             "companies": validated_data.pop("client_companies", []),
#             "documents": validated_data.pop("client_documents", []),
#             "frequent_flyers": validated_data.pop("client_frequent_flyers", []),
#             "family_members": validated_data.pop("family_members", []),
#             "relations": validated_data.pop("relationsWithOthers", []),
#             "fks": {
#                 "country_code": validated_data.pop("country_code", None),
#                 "residential_country": validated_data.pop("residential_country", None),
#                 "residential_state": validated_data.pop("residential_state", None),
#                 "residential_city": validated_data.pop("residential_city", None),
#                 "ref_preferred_airline": validated_data.pop("ref_preferred_airline", None)
#             }
#         }
#         client = self.create_client(validated_data)
#         self.create_related_objects(client, related_data)
#         return client

#     @transaction.atomic
#     def update(self, instance, validated_data):
#         """Update an existing client with related objects."""
#         related_data = {
#             "passports": validated_data.pop("client_passport", []),
#             "visas": validated_data.pop("client_visa", []),
#             "insurances": validated_data.pop("travel_insurance", []),
#             "companies": validated_data.pop("client_companies", []),
#             "documents": validated_data.pop("client_documents", []),
#             "frequent_flyers": validated_data.pop("client_frequent_flyers", []),
#             "family_members": validated_data.pop("family_members", []),
#             "relations": validated_data.pop("relationsWithOthers", []),
#             "fks": {
#                 "country_code": validated_data.pop("country_code", None),
#                 "residential_country": validated_data.pop("residential_country", None),
#                 "residential_state": validated_data.pop("residential_state", None),
#                 "residential_city": validated_data.pop("residential_city", None),
#                 "ref_preferred_airline": validated_data.pop("ref_preferred_airline", None)
#             }
#         }
#         client = self.update_client(instance, validated_data)
#         self.create_related_objects(client, related_data)
#         self.update_nested_objects(client, related_data["passports"], ClientPassport, {"passport_file": "passport_file"})
#         self.update_nested_objects(client, related_data["visas"], ClientVisa, {"passport_size_photograph": "passport_size_photograph"})
#         self.update_nested_objects(client, related_data["insurances"], ClientTravelInsurance, {"insurance_document": "insurance_document"})
#         self.update_nested_objects(client, related_data["documents"], ClientDocument, {"other_document": "other_document"})
#         self.update_nested_objects(client, related_data["companies"], AssocClientCompany, {}, ref_field="ref_company")
#         self.update_nested_objects(client, related_data["frequent_flyers"], ClientFrequentFlyer, {}, ref_field="ref_airline")
#         self.update_family_members(client, related_data["family_members"], related_data.get("fam_passport", []))
#         ClientRelation.objects.filter(Q(from_client=client) | Q(to_client=client)).exclude(to_client__client_id__in=[fam.get("id") for fam in related_data["family_members"] if fam.get("id")]).delete()
#         for rel in related_data["relations"]:
#             if not rel.get("toIndex"):
#                 continue
#             try:
#                 target_client = Client.objects.get(client_id=int(rel["toIndex"]))
#                 ClientRelation.objects.update_or_create(
#                     from_client=client,
#                     to_client=target_client,
#                     defaults={"relation": rel.get("relation"), "cross_relation": rel.get("crossRelation")}
#                 )
#             except Client.DoesNotExist:
#                 continue
#         return client

#     def get_familyMembers(self, obj):
#         """Retrieve family members with related data."""
#         members = Client.objects.filter(ref_client=obj).select_related(
#             'country_code', 'residential_country', 'residential_state', 'residential_city', 'ref_preferred_airline'
#         ).prefetch_related(
#             'client_passport', 'client_visa', 'travel_insurance', 'client_companies', 'client_documents',
#             'client_frequent_flyers'
#         )[:100]  # Limit to 100 for performance
#         return FullClientSerializer(members, many=True, context=self.context).data
    
  
class ClientDataSerializer(serializers.ModelSerializer):
    # Human-readable names instead of IDs
    residential_country = serializers.CharField(
        source="residential_country.country_name", read_only=True
    )
    residential_state = serializers.CharField(
        source="residential_state.state_name", read_only=True
    )
    residential_city = serializers.CharField(
        source="residential_city.city_name", read_only=True
    )

    class Meta:
        model = Client
        fields = "__all__"


'''
class FullClientSerializer(serializers.ModelSerializer):
    # --- Foreign keys ---
    country_code = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), required=False, allow_null=True
    )
    residential_country = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), 
        allow_null=True,  # if optional
        required=False
    )
    residential_state = serializers.PrimaryKeyRelatedField(
        queryset=State.objects.all(), required=False, allow_null=True
    )
    residential_city = serializers.PrimaryKeyRelatedField(
        queryset=Cities.objects.all(), required=False, allow_null=True
    )
    ref_preferred_airline = serializers.PrimaryKeyRelatedField(
        queryset=Airlines.objects.all(), required=False, allow_null=True
    )

    # --- Nested serializers ---
    client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
    client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
    travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
    client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
    client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
    client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_nul=True)
    relationsWithOthers = RelationsWithOthersInSerializer(many=True, required=False, allow_null=True)
    family_members = FamilyMemberInSerializer(many=True, required=False, allow_null=True)
    familyMembers = serializers.SerializerMethodField(read_only=True)

    # --- File uploads ---
    aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
    pan_card_file = serializers.FileField(required=False, allow_null=True)

    # --- Flexible date fields (use CharField to avoid DRF parsing errors) ---
    dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    anniversary_date = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    class Meta:
        model = Client
        fields = [
            "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
            "relation", "crossrelation", "client_middle_name", "client_last_name", "dob",
            "country_code", "contact_no", "email", "gender", "residential_address",
            "residential_city", "residential_state", "residential_country", "residential_pincode",
            "marital_status", "anniversary_date", "reference_from", "reference_remark", "occupation",
            "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
            "ref_preferred_airline", "star_rating", "stay_preference", "room_preference",
            "extra_amenities", "seat_preference", "seat_preference_other", "meal_preference",
            "fare_preference", "created_at", "created_by", "updated_at", "updated_by",
            "client_passport", "client_visa", "travel_insurance", "client_companies",
            "client_documents", "client_frequent_flyers", "family_members", "familyMembers", "relationsWithOthers",
        ]
        read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

    # ---------------- Helper Methods ----------------
    def _normalize_code(self, code):
        if isinstance(code, list):
            code = code[0] if code else ""
        return (code or "").strip()

    def clean_date(self, value):
        """Convert string -> date or None, unwrap lists if needed"""
        if isinstance(value, list):
            value = value[0] if value else None
        if not value or str(value).strip() == "":
            return None
        if isinstance(value, str):
            try:
                return datetime.strptime(value, "%Y-%m-%d").date()
            except ValueError:
                return None
        return value

    def clean_str(self, value):
        return value if value and str(value).strip() != "" else None
    
    def safe_fk(self, value, model_class=None):
        if not value:
            return None

        if model_class is None and hasattr(value, "_meta"):  # already a model
            return value

        if isinstance(value, (str, int)) and model_class:
            try:
                return model_class.objects.get(pk=value)
            except model_class.DoesNotExist:
                raise serializers.ValidationError(f"Invalid {model_class.__name__} ID.")
        return value
        
    def normalize_foreign_keys(self, data, fk_fields):
        """
        Normalize foreign key fields in validated_data:
        - If field is dict → take its 'id'
        - If field is blank/None → set None
        - If field is str/int → resolve via safe_fk
        """
        for field in fk_fields:
            value = data.get(field)
            if not value or value == "":
                data[field] = None
                continue

            # Handle dicts (coming from nested serializers like CountrySerializer)
            if isinstance(value, dict):
                value = value.get("id")

            # Map field -> model
            model_map = {
                "residential_country": Countries,
                "residential_state": State,
                "residential_city": Cities,
            }

            model = model_map.get(field)
            if model:
                data[field] = self.safe_fk(model, value)

        return data
    
    def normalize_preferred_contact_method(self, value):
        """
        Always normalize preferred_contact_method into a list of keys.
        Accepts:
        - ["whatsapp", "group_message"]
        - [{"id": "whatsapp"}, {"id": "group_message"}]
        - [{"": "WhatsApp"}]   <-- fix from frontend bug
        """
        normalized = []
        if not value:
            return []

        for v in value:
            key = None
            if isinstance(v, dict):
                key = v.get("id") or v.get("value") or v.get("label") or v.get("")
            else:
                key = str(v)
            if key:
                normalized.append(str(key).lower().strip())
        return value

    # def validate(self, data):
    #     code = data.get("client_code")
    #     if isinstance(code, list):
    #         data["client_code"] = code[0] if code else ""
    #     return data

    # ---------------- Validate ----------------
    def validate(self, data):
        # --- Uniqueness checks (same as before) ---
        main_code = self._normalize_code(data.get("client_code"))
        if main_code:
            qs = Client.objects.filter(client_code=main_code)
            if self.instance:  # update
                qs = qs.exclude(pk=self.instance.client_id)
            if qs.exists():
                raise serializers.ValidationError({
                    "client_code": f"Client code '{main_code}' already exists."
                })

        # Only check family members at create
        if not self.instance:  
            for fam in data.get("family_members", []):
                fam_code = self._normalize_code(fam.get("clientCode"))
                if fam_code:
                    qs = Client.objects.filter(client_code=fam_code)
                    if qs.exists():
                        raise serializers.ValidationError({
                            "family_member_client_code": f"Client code '{fam_code}' already exists."
                        })

        # --- Clean dates at top level ---
        data["dob"] = self.clean_date(data.get("dob"))
        data["anniversary_date"] = self.clean_date(data.get("anniversary_date"))

        # --- Nested: Passport ---
        for p in data.get("client_passport", []):
            p["passport_no"] = self.clean_str(p.get("passport_no"))
            p["passport_expiry_date"] = self.clean_date(p.get("passport_expiry_date"))

        # --- Nested: Companies --- 
        for c in data.get("client_companies", []):
            c["ref_company"] = self.safe_fk(c.get("ref_company"), Company)
            c["designation"] = self.clean_str(c.get("designation"))
            c["primary_company"] = self.clean_str(c.get("primary_company"))

        # --- Nested: Frequent Flyers ---
        for ff in data.get("client_frequent_flyer", []):
            ff["ff_no"] = self.clean_str(ff.get("ff_no"))

        # --- Nested: Visa ---
        for v in data.get("client_visa", []):
            v["visa_from_date"] = self.clean_date(v.get("visa_from_date"))
            v["visa_to_date"] = self.clean_date(v.get("visa_to_date"))

        # --- Nested: Travel Insurance ---
        for t in data.get("travel_insurance", []):
            t["insurance_from_date"] = self.clean_date(t.get("insurance_from_date"))
            t["insurance_to_date"] = self.clean_date(t.get("insurance_to_date"))

        # --- New: Family members ---
        for fam in data.get("family_members", []):
            fam["dob"] = self.clean_date(fam.get("dob"))
            fam["anniversary_date"] = self.clean_date(fam.get("anniversary_date"))
            for fp in fam.get("client_passport", []):
                fp["passport_no"] = self.clean_str(fp.get("passport_no"))
                fp["passport_expiry_date"] = self.clean_date(fp.get("passport_expiry_date"))

        return data
    
    def to_internal_value(self, data):
        # normalize client_documents
        docs = data.get("client_documents")
        if isinstance(docs, dict):
            data["client_documents"] = [docs]   # wrap dict into a list
        return data

    def unwrap_value(self, value):
        if isinstance(value, list):
            return value if value else None
        return value

    # ---------------- Serializer Methods ----------------
    def get_familyMembers(self, obj):
        members = Client.objects.filter(ref_client=obj)
        return FullClientSerializer(members, many=True, context=self.context).data
    
    # ---------------- Create ----------------
    @transaction.atomic
    def create(self, validated_data):
        request = self.context.get("request")
        request_files = request.FILES if request else {}

        # --- Pop related data ---
        passports_data = validated_data.pop("client_passport", [])
        visas_data = validated_data.pop("client_visa", [])
        insurances_data = validated_data.pop("travel_insurance", [])
        docs_data = validated_data.pop("client_documents", [])
        companies_data = validated_data.pop("client_companies", [])
        frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
        family_members_data = validated_data.pop("family_members", [])
        validated_data.pop("familyMembers", None)  # read-only field

        # --- Helper: unwrap list & empty string ---
        def unwrap(value):
            if isinstance(value, list):
                value = value[0] if value else None
            if value == "":
                return None
            return value

        # --- Normalize top-level ForeignKeys ---
        validated_data["country_code"] = self.safe_fk(Countries, unwrap(validated_data.get("country_code")))
        validated_data["residential_country"] = self.safe_fk(Countries, unwrap(validated_data.get("residential_country")))
        validated_data["residential_state"] = self.safe_fk(State, unwrap(validated_data.get("residential_state")))
        validated_data["residential_city"] = self.safe_fk(Cities, unwrap(validated_data.get("residential_city")))
        validated_data["ref_preferred_airline"] = self.safe_fk(Airlines, unwrap(validated_data.get("ref_preferred_airline")))

        # --- Normalize Dates ---
        validated_data["dob"] = self.clean_date(unwrap(validated_data.get("dob")))
        validated_data["anniversary_date"] = self.clean_date(unwrap(validated_data.get("anniversary_date")))
        validated_data["marital_status"] = validated_data.get("marital_status") or None

        # --- Normalize client_code and defaults ---
        validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
        validated_data["client_type"] = "Primary Member"
        validated_data["client_status"] = "Active"
        validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
            validated_data.get("preferred_contact_method")
        )

        # --- Handle file uploads ---
        for file_field in ["aadhaar_card_file", "pan_card_file"]:
            if file_field in request_files:
                validated_data[file_field] = request_files.get(file_field)

        # --- Create main client ---
        client = Client.objects.create(**validated_data)

        # --- Helper: clean dict ---
        def clean_row(row, file_map=None):
            # unwrap all values
            row = {k: unwrap(v) for k, v in row.items()}
            if "id" in row and (row["id"] is None or str(row["id"]).strip() == ""):
                row.pop("id")
            if file_map:
                for field, req_field in file_map.items():
                    if req_field in request_files:
                        files = request_files.getlist(req_field)
                        row[field] = files[0] if len(files) == 1 else files
            return row

        # --- Related: Passports ---
        for pd in passports_data:
            pd = clean_row(pd, file_map={"passport_document": "passport_document"})
            pd["country"] = self.safe_fk(Countries, unwrap(pd.get("country")))
            pd["issued_by"] = self.safe_fk(Countries, unwrap(pd.get("issued_by")))
            
            pd.pop("country", None)
            pd.pop("issued_by", None)

            if not any(pd.values()):
                continue
            ClientPassport.objects.create(ref_client=client, **pd)

        # --- Related: Visas ---
        for vd in visas_data:
            vd = clean_row(vd, file_map={"passport_size_photograph": "passport_size_photograph"})
            vd["ref_visa_country"] = self.safe_fk(Countries, unwrap(vd.get("ref_visa_country")))
            vd["visa_from_date"] = self.clean_date(unwrap(vd.get("visa_from_date")))
            vd["visa_to_date"] = self.clean_date(unwrap(vd.get("visa_to_date")))
            if not any(vd.values()):
                continue
            ClientVisa.objects.create(ref_client=client, **vd)

        # --- Related: Travel Insurance ---
        for ins in insurances_data:
            ins = clean_row(ins, file_map={"insurance_document": "insurance_document"})
            ins["insurance_from_date"] = self.clean_date(unwrap(ins.get("insurance_from_date")))
            ins["insurance_to_date"] = self.clean_date(unwrap(ins.get("insurance_to_date")))
            if not any(ins.values()):
                continue
            ClientTravelInsurance.objects.create(ref_client=client, **ins)

        # --- Related: Other Documents ---
        for doc in docs_data:
            doc = clean_row(doc, file_map={"other_document": "other_document"})
            if not any(doc.values()):
                continue
            ClientDocument.objects.create(ref_client=client, **doc)

        # --- Related: Companies ---
        for cd in companies_data:
            cd = clean_row(cd)
            cd["ref_company"] = self.safe_fk(Company, unwrap(cd.get("ref_company")))
            if not any(cd.values()):
                continue
            AssocClientCompany.objects.create(ref_client=client, **cd)

        # --- Related: Frequent Flyers ---
        for flyer_data in frequent_flyers_data:
            flyer_data = clean_row(flyer_data)
            flyer_data["ref_airline"] = self.safe_fk(Airlines, unwrap(flyer_data.get("ref_airline")), lookup_field="airline_name")
            flyer_data["ff_no"] = self.clean_str(flyer_data.get("ff_no"))
            if not any(flyer_data.values()):
                continue
            ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)

        # --- Related: Family Members ---
        meaningful_fields = ["clientCode", "firstName", "lastName", "relation", "email", "contactNo"]

        def is_blank_field(value):
            return value is None or (isinstance(value, str) and value.strip() == "") or (isinstance(value, list) and len(value) == 0)

        for fam in family_members_data:
            if all(is_blank_field(fam.get(field)) for field in meaningful_fields):
                continue

            fam_code = self._normalize_code(fam.get("clientCode"))
            fam_data = {
                "ref_client": client,
                "client_type": "Family Member",
                "client_status": "Active",
                "client_code": fam_code,
                "client_salutation": fam.get("salutation"),
                "client_first_name": fam.get("firstName"),
                "client_middle_name": fam.get("middleName"),
                "client_last_name": fam.get("lastName"),
                "relation": unwrap(fam.get("relation")),
                "crossrelation": unwrap(fam.get("crossrelation")),
                "contact_no": fam.get("contactNo"),
                "email": fam.get("email"),
                "dob": self.clean_date(unwrap(fam.get("dob"))),
                "gender": fam.get("gender"),
                "occupation": fam.get("occupation"),
                "aadhaar_no": fam.get("aadhaarNo"),
                "aadhaar_card_file": fam.get("aadhaarCard"),
                "pan_no": fam.get("panNo"),
                "pan_card_file": fam.get("panCard"),
                "residential_address": fam.get("residential_address") or client.residential_address,
                "residential_country": self.safe_fk(Countries, unwrap(fam.get("residential_country"))) or client.residential_country,
                "residential_state": self.safe_fk(State, unwrap(fam.get("residential_state"))) or client.residential_state,
                "residential_city": self.safe_fk(Cities, unwrap(fam.get("residential_city"))) or client.residential_city,
                "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
                "anniversary_date": self.clean_date(unwrap(fam.get("anniversary_date")))
            }

            family_client = Client.objects.create(**fam_data)

            # --- Family member passports ---
            for fp in fam.get("client_passport", []):
                fp = clean_row(fp, file_map={"passport_file": "passport_file"})
                fp["passport_expiry_date"] = self.clean_date(unwrap(fp.get("passport_expiry_date")))
                fp["country"] = self.safe_fk(Countries, unwrap(fp.get("country")))
                if not any(fp.values()):
                    continue
                ClientPassport.objects.create(ref_client=family_client, **fp)

            # --- Relations ---
            if fam.get("relation"):
                ClientRelation.objects.create(from_client=client, to_client=family_client, relation=fam["relation"])
            if fam.get("crossrelation"):
                ClientRelation.objects.create(from_client=family_client, to_client=client, relation=fam["crossrelation"])

        return client


    
    @transaction.atomic
    def update(self, instance, validated_data):
        passports_data = validated_data.pop("client_passport", [])
        visas_data = validated_data.pop("client_visa", [])
        insurances_data = validated_data.pop("travel_insurance", [])
        docs_data = validated_data.pop("client_documents", [])
        companies_data = validated_data.pop("client_companies", [])
        frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])

        validated_data.pop("family_members", None)  # Ignore family members in update
        validated_data.pop("familyMembers", None)  # Remove read-only field

        # --- Normalize foreign keys ---
        fk_fields = ["residential_country", "residential_state", "residential_city"]
        validated_data = self.normalize_foreign_keys(validated_data, fk_fields)

        validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))
        validated_data["dob"] = self.clean_date(validated_data.get("dob"))
        validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))

        if "preferred_contact_method" in validated_data:
            validated_data["preferred_contact_method"] = self.normalize_preferred_contact_method(
                validated_data.get("preferred_contact_method")
            )

        files = self.context.get("request").FILES if self.context.get("request") else None
        if files:
            if "aadhaar_card_file" in files:
                instance.aadhaar_card_file = files["aadhaar_card_file"]
            if "pan_card_file" in files:
                instance.pan_card_file = files["pan_card_file"]

        # --- Handle uploaded files ---
        files = self.context.get("request").FILES if self.context.get("request") else None
        if files:
            if "aadhaar_card_file" in files:
                instance.aadhaar_card_file = files["aadhaar_card_file"]
            if "pan_card_file" in files:
                instance.pan_card_file = files["pan_card_file"]

        # --- Update main client fields ---
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        # --- Update or create related objects ---
        for pd in passports_data:
            pd["passport_expiry_date"] = self.clean_date(pd.get("passport_expiry_date"))
            ClientPassport.objects.update_or_create(
                ref_client=instance,
                passport_no=pd.get("passport_no"),
                defaults=pd
            )

        for vd in visas_data:
            vd["ref_visa_country"] = self.safe_fk(Countries, vd.get("ref_visa_country"), "ref_visa_country")
            vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
            vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))
            ClientVisa.objects.update_or_create(
                ref_client=instance,
                visa_no=vd.get("visa_no"),
                defaults=vd
            )

        for ins in insurances_data:
            ins["insurance_from_date"] = self.clean_date(ins.get("insurance_from_date"))
            ins["insurance_to_date"] = self.clean_date(ins.get("insurance_to_date"))
            ClientTravelInsurance.objects.update_or_create(
                ref_client=instance,
                id=ins.get("id"),   # or some valid FK field if you have one
                defaults={
                    "insurance_document": ins.get("insurance_document"),
                    "insurance_from_date": ins.get("insurance_from_date"),
                    "insurance_to_date": ins.get("insurance_to_date"),
                }
            )

        for doc in docs_data:
            if doc:
                ClientDocument.objects.update_or_create(
                    ref_client=instance,
                    other_document=doc.get("other_document"),
                    defaults=doc
                )

        for cd in companies_data:
            cd["ref_company"] = self.safe_fk(Company, cd.get("ref_company"), "ref_company")
            AssocClientCompany.objects.update_or_create(
                ref_client=instance,
                ref_company=cd["ref_company"],
                defaults=cd
            )

        for flyer_data in frequent_flyers_data:
            flyer_data["ref_airline"] = self.safe_fk(Airlines, flyer_data.get("ref_airline"), "ref_airline")
            ClientFrequentFlyer.objects.update_or_create(
                ref_client=instance,
                ff_no=flyer_data.get("ff_no"),
                defaults=flyer_data
            )

        return instance
'''

# class FullClientSerializer(serializers.ModelSerializer):
#     # --- Primary/Foreign keys ---
#     country_code = CountrySerializer(required=False, allow_null=True)
#     residential_country = serializers.PrimaryKeyRelatedField(
#         queryset=Countries.objects.all(), write_only=True, required=False, allow_null=True
#     )
#     residential_state = serializers.PrimaryKeyRelatedField(
#         queryset=State.objects.all(), write_only=True, required=False, allow_null=True
#     )
#     residential_city = serializers.PrimaryKeyRelatedField(
#         queryset=Cities.objects.all(), write_only=True, required=False, allow_null=True
#     )

#     # --- Nested serializers ---
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     client_visa = ClientVisaSerializer(many=True, required=False, allow_null=True)
#     travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False, allow_null=True)
#     client_companies = AssocClientCompanySerializer(many=True, required=False, allow_null=True)
#     client_documents = OtherDocumentSerializer(many=True, required=False, allow_null=True)
#     client_frequent_flyers = FrequentflyerSerializer(many=True, required=False, allow_null=True)
#     family_members = FamilyMemberInSerializer(many=True, write_only=True, required=False, allow_null=True)
#     familyMembers = serializers.SerializerMethodField(read_only=True)

#     # --- File uploads ---
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True)

#     # --- Flexible date fields ---
#     dob = serializers.DateField(required=False, allow_null=True)
#     anniversary_date = serializers.DateField(required=False, allow_null=True)

#     class Meta:
#         model = Client
#         fields = [
#             "client_id", "client_code", "client_type", "client_salutation", "client_first_name", "relation",
#             "crossrelation", "client_middle_name", "client_last_name", "dob", "country_code", "contact_no", "email",
#             "gender", "residential_address", "residential_city", "residential_state", "residential_country",
#             "residential_pincode", "marital_status", "anniversary_date", "reference_from", "reference_remark",
#             "occupation", "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
#             "ref_preferred_airline", "star_rating", "stay_preference", "room_preference", "extra_amenities",
#             "seat_preference", "seat_preference_other", "meal_preference", "fare_preference", "created_at",
#             "created_by", "updated_at", "updated_by", "client_passport", "client_visa", "travel_insurance",
#             "client_companies", "client_documents", "client_frequent_flyers", "family_members", "familyMembers"
#         ]

#         read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

#     def to_internal_value(self, data):

#         # --- normalize top-level empty -> None ---
#         # client_code must be None rather than empty string to avoid unique '' collisions
#         if "client_code" in data and (data["client_code"] == "" or str(data["client_code"]).strip() == ""):
#             data["client_code"] = None

#         # Convert empty date strings to None
#         date_fields = ["dob", "anniversary_date"]
#         for field in date_fields:
#             if field in data and data[field] == "":
#                 data[field] = None

#         # Convert empty strings to None for nullable foreign keys
#         fk_fields = [
#             "country_code", "residential_country", "residential_state", "residential_city", "ref_preferred_airline",
#         ]
#         for f in fk_fields:
#             if f in data and data[f] == "":
#                 data[f] = None

#         # Wrap single dicts in list if needed for many=True fields
#         many_fields = [
#             "client_passport", "client_visa", "travel_insurance", "client_companies", "client_documents",
#             "familyMembers", "client_frequent_flyers"]
#         for field in many_fields:
#             val = data.get(field)
#             if isinstance(val, dict):
#                 data[field] = [val]
#             elif val is None:
#                 data[field] = []

#         # Filter out empty client_documents before DRF validation
#         docs = data.get("client_documents", [])
#         if isinstance(docs, list):
#             cleaned_docs = []
#             for doc in docs:
#                 if doc.get("other_document") or doc.get("other_document_name"):
#                     cleaned_docs.append(doc)
#             data["client_documents"] = cleaned_docs

#         # Remove empty string IDs in nested fields
#         nested_fields = [
#             "client_passport",
#             "client_visa",
#             "travel_insurance",
#             "client_companies",
#             "family_members",
#             "client_frequent_flyers"
#         ]
#         for field in nested_fields:
#             items = data.get(field, [])
#             if isinstance(items, list):
#                 for item in items:
#                     if "id" in item and item["id"] == "":
#                         item.pop("id")

#         return data

#     PREFERED_CONTACT_METHODS = [
#         ('Call', 'Call'),
#         ('Whatsapp', 'Whatsapp'),
#         ('Email', 'Email'),
#         ('Group Message', 'Group Message'),
#     ]

#     # -----------------------
#     # Helper functions
#     # -----------------------
#     def _normalize_preferred_methods(self, value):
#         """Normalize inputs to lowercase canonical keys."""
#         if not value:
#             return []
#         if isinstance(value, str):
#             raw = [s.strip() for s in value.split(',') if s.strip()]
#         elif isinstance(value, (list, tuple)):
#             raw = value
#         else:
#             raw = [value]

#         alias_map = {
#             'mail': 'email', 'email': 'email',
#             'call': 'phone', 'phone': 'phone', 'mobile': 'phone',
#             'whatsapp': 'whatsapp', 'wa': 'whatsapp',
#             'group_message': 'group_message', 'group message': 'group_message', 'group': 'group_message'
#         }

#         normalized = []
#         for v in raw:
#             if isinstance(v, dict):
#                 candidate = v.get('id') or v.get('value') or v.get('label') or next(iter(v.values()), None)
#             else:
#                 candidate = v
#             if candidate:
#                 cand = str(candidate).lower().replace(' ', '_')
#                 mapped = alias_map.get(cand, cand)
#                 normalized.append(mapped)
#         return normalized

#     def validate_preferred_contact_method(self, value):
#         normalized = self._normalize_preferred_methods(value)
#         allowed = {k.lower() for k, _ in self.PREFERED_CONTACT_METHODS}  # tuple first element
#         invalid = [v for v in normalized if v not in allowed]
#         if invalid:
#             raise serializers.ValidationError(f"{', '.join(invalid)} is not a valid choice.")
#         # Return comma-separated string for model
#         return ",".join(normalized)

#     # -----------------------
#     # Field-level validation
#     # -----------------------
#     # def validate_aadhaar_no(self, value):
#     #     if value and not value.isdigit():
#     #         raise serializers.ValidationError("Aadhaar must be numeric.")
#     #     return value

#     # def validate_pan_no(self, value):
#     #     if value and len(value) != 10:
#     #         raise serializers.ValidationError("PAN must be 10 characters.")
#     #     return value

    
#     '''
#     # Object-level validation
#     def validate(self, data):
#         # Family-member client code uniqueness
#         family_members = self.initial_data.get("family_members", [])
#         for fam in family_members:
#             fam_code = fam.get("clientCode")
#             if fam_code and Client.objects.filter(client_code=fam_code).exists():
#                 raise serializers.ValidationError({
#                     "family_member_client_code": f"Client code '{fam_code}' already exists."
#                 })
#         # Normalize preferred_contact_method
#         if "preferred_contact_method" in data:
#             data["preferred_contact_method"] = self.validate_preferred_contact_method(
#                 data.get("preferred_contact_method")
#             )
#         return data
#     '''

#     def validate(self, data):
#         """
#         - Check family member clientCode uniqueness (only when non-empty).
#         - Check main client_code uniqueness (only when non-empty).
#         """
#         # Family members uniqueness
#         family_members_raw = self.initial_data.get("family_members", []) or []
#         for fam in family_members_raw:
#             fam_code = (fam.get("clientCode") or "").strip()
#             if not fam_code:
#                 continue  # skip empty -> will be set to None later

#             qs = Client.objects.filter(client_code=fam_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({
#                     "family_member_client_code": f"Client code '{fam_code}' already exists."
#                 })

#         # Main client_code uniqueness
#         main_code = (self.initial_data.get("client_code") or data.get("client_code") or "").strip()
#         if main_code:
#             qs = Client.objects.filter(client_code=main_code)
#             if self.instance:
#                 qs = qs.exclude(pk=self.instance.client_id)
#             if qs.exists():
#                 raise serializers.ValidationError({
#                     "client_code": f"Client code '{main_code}' already exists."
#                 })

#         return data

#     # -----------------------
#     # Nested serializers
#     # -----------------------
#     def get_familyMembers(self, obj):
#         members = Client.objects.filter(ref_client=obj)
#         return FullClientSerializer(members, many=True, context=self.context).data
    

#     def clean_date(self, date_str):
#         """Convert empty strings or invalid dates to None."""
#         if date_str in ("", None):
#             return None
#         return date_str
    
#     def _normalize_code(self, code: str | None) -> str | None:
#         """
#         Ensure blank client_code is stored as None.
#         You can also auto-generate if you want unique always.
#         """
#         code = (code or "").strip()
#         if not code:
#             return None
#         return code
    
#     def _normalize_fk(self, value, model_cls=None):
#         if value in ("", None):
#             return None
#         if model_cls:
#             return model_cls.objects.filter(pk=value).first()
#         return value
    
#     def _resolve_fk(self, model, value, field_name):
#         """Normalize foreign key fields: allow None, validate IDs."""
#         if not value or value == "":
#             return None   # <-- just None, not (None,)
#         try:
#             return model.objects.get(pk=value)
#         except model.DoesNotExist:
#             raise serializers.ValidationError({
#                 field_name: f"Invalid id '{value}' for {model.__name__}."
#             })
    
#     def normalize_foreign_keys(data, fk_fields):
#         """Convert foreign key ids to model instances, set empty to None."""
#         from .models import Countries, States, Cities, Company  # import as per your models

#         model_map = {
#             "residential_country": Countries,
#             "residential_state": States,
#             "residential_city": Cities,
#             "ref_company": Company,
#         }

#         for field in fk_fields:
#             value = data.get(field)
#             if not value:  # empty or None
#                 data[field] = None
#             else:
#                 Model = model_map.get(field)
#                 if Model:
#                     try:
#                         data[field] = Model.objects.get(id=value)
#                     except Model.DoesNotExist:
#                         data[field] = None
#         return data


#     # -----------------------
#     # Creation
#     # -----------------------
#     @transaction.atomic
#     def create(self, validated_data):
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyers_data = validated_data.pop("client_frequent_flyers", [])
#         family_members_data = validated_data.pop("family_members", [])

#         # Ensure read-only SerializerMethodField is not passed to model
#         validated_data.pop("familyMembers", None)

#         # Clean FKs for Client
#         # validated_data["country_code"] = self._resolve_fk(Countries, validated_data.get("country_code"), "country_code")
#         # validated_data["residential_country"] = self._resolve_fk(Countries, validated_data.get("residential_country"), "residential_country")
#         # validated_data["ref_preferred_airline"] = self._resolve_fk(Airlines, validated_data.get("ref_preferred_airline"), "ref_preferred_airline")

#         fk_fields = ["residential_country", "residential_state", "residential_city"]
#         validated_data = normalize_foreign_keys(validated_data, fk_fields)

#         validated_data["client_code"] = self._normalize_code(validated_data.get("client_code"))

#         validated_data["client_type"] = "Primary Member"
#         validated_data["client_status"] = "Active"

#         validated_data["dob"] = self.clean_date(validated_data.get("dob"))
#         validated_data["anniversary_date"] = self.clean_date(validated_data.get("anniversary_date"))

#         client = Client.objects.create(**validated_data)

#         # Related objects
#         for pd in passports_data:
#             pd["passport_expiry_date"] = self.clean_date(validated_data.get("passport_expiry_date"))
#             ClientPassport.objects.create(ref_client=client, **pd)

#         for vd in visas_data:
#             # Fix empty country values
#             # if not vd.get("ref_visa_country"):
#             #     vd["ref_visa_country"] = None
#             # else:
#             #     vd["ref_visa_country"] = Countries.objects.get(pk=vd["ref_visa_country"])
#             vd["ref_visa_country"] = self._resolve_fk(Countries, vd.get("ref_visa_country"), "ref_visa_country")
#             vd["visa_from_date"] = self.clean_date(vd.get("visa_from_date"))
#             vd["visa_to_date"] = self.clean_date(vd.get("visa_to_date"))

#             ClientVisa.objects.create(ref_client=client, **vd)

#         for ins in insurances_data:
#             ins["insurance_from_date"] = self.clean_date(validated_data.get("insurance_from_date"))
#             ins["insurance_to_date"] = self.clean_date(validated_data.get("insurance_to_date"))
#             ClientTravelInsurance.objects.create(ref_client=client, **ins)

#         for doc in docs_data:
#             if doc:
#                 ClientDocument.objects.create(ref_client=client, **doc)

#         for cd in companies_data:
#             cd["ref_company"] = self._resolve_fk(Company, cd.get("ref_company"), "ref_company")
#             AssocClientCompany.objects.create(ref_client=client, **cd)

#         for flyer_data in frequent_flyers_data:
#             # airline_id = flyer_data.get("ref_airline")
#             flyer_data["ref_airline"] = self._resolve_fk(Airlines, flyer_data.get("ref_airline"), "ref_airline")
#             # If it's an Airlines object → extract pk
#             # if isinstance(airline_id, Airlines):
#             #     airline_id = airline_id.id
#             # if airline_id and not Airlines.objects.filter(pk=airline_id).exists():
#             #     raise serializers.ValidationError({
#             #         "client_frequent_flyers": f"Airline id '{airline_id}' not found."
#             #     })
#             ClientFrequentFlyer.objects.create(ref_client=client, **flyer_data)


#         # Family members
#         for fam in family_members_data:
#             fam_code = self._normalize_code(fam.get("clientCode"))

#         fam["country_code"] = self._resolve_fk(Countries, fam.get("countryCode"), "countryCode"),
#         fam["residential_country"] = self._resolve_fk(Countries, fam.get("residential_country"), "residential_country"),
#         for fam in family_members_data:
#             fk_fields = ["residential_country", "residential_state", "residential_city"]
#             fam_data = normalize_foreign_keys(fam_data, fk_fields)
#             fam_data = {
#                 "ref_client": client,
#                 "client_type": "Family Member",
#                 "client_status": "Active",
#                 "client_code": fam_code,
#                 "client_salutation": fam.get("salutation", ""),
#                 "client_first_name": fam.get("firstName", ""),
#                 "client_middle_name": fam.get("middleName", ""),
#                 "client_last_name": fam.get("lastName", ""),
#                 "relation": fam.get("relation", ""),
#                 "crossrelation": fam.get("crossrelation", ""),
#                 # "country_code_id": fam.get("countryCode"),
#                 "contact_no": fam.get("contactNo", ""),
#                 "email": fam.get("email", ""),
#                 "dob": self.clean_date(fam.get("dob")),
#                 "gender": fam.get("gender", ""),
#                 "occupation": fam.get("occupation", ""),
#                 "aadhaar_no": fam.get("aadhaarNo", ""),
#                 "aadhaar_card_file": fam.get("aadhaarCard"),
#                 "pan_no": fam.get("panNo", ""),
#                 "pan_card_file": fam.get("panCard"),
#                 "residential_address": fam.get("residential_address") or client.residential_address,
#                 "residential_city": fam.get("residential_city") or client.residential_city,
#                 "residential_state": fam.get("residential_state") or client.residential_state,
#                 "residential_country": fam.get("residential_country") or client.residential_country,
#                 "residential_pincode": fam.get("residential_pincode") or client.residential_pincode,
#             }
#             family_client = Client.objects.create(**fam_data)

#             # family passports
#             for pp in fam.get("client_passport", []):
#                 ClientPassport.objects.create(ref_client=fam_data, **pp)

#             # family visas
#             for vv in fam.get("client_visa", []):
#                 ClientVisa.objects.create(ref_client=fam_data, **vv)

#             # family travel insurances
#             for ti in fam.get("travel_insurance", []):
#                 ClientTravelInsurance.objects.create(ref_client=fam_data, **ti)

#             # family documents
#             for doc in fam.get("client_documents", []):
#                 if not doc.get("other_document") and not doc.get("other_document_name"):
#                     continue
#                 ClientDocument.objects.create(ref_client=fam_data, **doc)

#             # # family companies
#             # for comp in fam.get("client_companies", []):
#             #     AssocClientCompany.objects.create(ref_client=fam_data, **comp)

#             # created_family.append(fam_data)

#             # --- relations ---
#             if fam.get("relation"):
#                 ClientRelation.objects.create(
#                     from_client=client,
#                     to_client=family_client,
#                     relation=fam["relation"]
#                 )
#             if fam.get("crossrelation"):
#                 ClientRelation.objects.create(
#                     from_client=family_client,
#                     to_client=client,
#                     relation=fam["crossrelation"]
#                 )

#         return client

#     @transaction.atomic
#     def update(self, instance, validated_data):
#         # Normalize preferred_contact_method first
#         if "preferred_contact_method" in validated_data:
#             validated_data["preferred_contact_method"] = self._normalize_preferred_methods(
#                 validated_data.get("preferred_contact_method")
#             )

#         request = self.context.get("request")
#         files = request.FILES if request else None

#         # Handle file uploads if provided
#         if files:
#             if "aadhaar_card_file" in files:
#                 instance.aadhaar_card_file = files["aadhaar_card_file"]
#             if "pan_card_file" in files:
#                 instance.pan_card_file = files["pan_card_file"]

#         # --- Handle file fields (skip if not provided) ---
#         for field in ["aadhaar_card_file", "pan_card_file"]:
#             file_value = validated_data.get(field, None)
#             if not file_value:
#                 validated_data.pop(field, None)

#         # --- Pop nested data ---
#         passports_data = validated_data.pop("client_passport", [])
#         visas_data = validated_data.pop("client_visa", [])
#         insurances_data = validated_data.pop("travel_insurance", [])
#         docs_data = validated_data.pop("client_documents", [])
#         companies_data = validated_data.pop("client_companies", [])
#         frequent_flyer_data = validated_data.pop("client_frequent_flyers", [])

#         # --- Update base client fields ---
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)
#         instance.save()

#         # helper to convert nested dict values -> IDs
#         def _extract_id(val):
#             if val is None:
#                 return None
#             if isinstance(val, dict):
#                 return val.get("id") or val.get("pk") or val.get("value") or next(iter(val.values()), None)
#             return val

#         def _clean_defaults(d):
#             """Return copy of dict where nested dicts are replaced by their id-like value."""
#             nd = {}
#             for k, v in (d or {}).items():
#                 if isinstance(v, dict):
#                     nd[k] = _extract_id(v)
#                 else:
#                     nd[k] = v
#             return nd

#         # --- Passports ---
#         for pd in passports_data:
#             if not any(v for v in pd.values() if v not in ("", None, [], {})):
#                 continue
#             ClientPassport.objects.update_or_create(
#                 ref_client=instance,
#                 passport_no=pd.get("passport_no"),
#                 defaults=_clean_defaults(pd),
#             )

#         # --- Visas ---
#         for vd in visas_data:
#             if not any(v for v in vd.values() if v not in ("", None, [], {})):
#                 continue

#             ref_visa_country = _extract_id(vd.get("ref_visa_country"))

#             ClientVisa.objects.update_or_create(
#                 ref_client=instance,
#                 visa_type=vd.get("visa_type"),
#                 ref_visa_country_id=ref_visa_country,
#                 defaults=_clean_defaults(vd),
#             )

#         # --- Travel Insurance ---
#         for ins in insurances_data:
#             if not any(v for v in ins.values() if v not in ("", None, [], {})):
#                 continue
#             ClientTravelInsurance.objects.update_or_create(
#                 ref_client=instance,
#                 insurance_document=ins.get("insurance_document"),
#                 defaults=_clean_defaults(ins),
#             )

#         # --- Documents ---
#         for doc in docs_data:
#             if not doc.get("other_document") and not doc.get("other_document_name"):
#                 continue
#             ClientDocument.objects.update_or_create(
#                 ref_client=instance,
#                 other_document_name=doc.get("other_document_name"),
#                 defaults=_clean_defaults(doc),
#             )

#         # --- Companies ---
#         for comp in companies_data:
#             if not comp.get("ref_company"):
#                 continue
#             ref_company_id = _extract_id(comp.get("ref_company"))
#             AssocClientCompany.objects.update_or_create(
#                 ref_client=instance,
#                 ref_company_id=ref_company_id,
#                 defaults=_clean_defaults(comp),
#             )

#         # --- Frequent Flyers ---
#         for ff in frequent_flyer_data:
#             if not ff.get("ff_no"):
#                 continue
#             ClientFrequentFlyer.objects.update_or_create(
#                 ref_client=instance,
#                 ff_no=ff.get("ff_no"),
#                 defaults=_clean_defaults(ff),
#             )

#         return instance

    
#     def to_representation(self, instance):
#         data = super().to_representation(instance)
#         request = self.context.get("request")
#         if request and request.method == "POST":
#             # Hide empty nested lists for family members only on create
#             if "family_members" in data:
#                 for fam in data["family_members"]:
#                     for field in ["client_visa", "travel_insurance", "client_companies", "client_documents", "family_members"]:
#                         if not fam.get(field):
#                             fam.pop(field)
#         return data



class FamilyMemberListSerializer(serializers.ListSerializer):
    @transaction.atomic
    def create(self, validated_data):
        primary_client = self.context["primary_client"]
        created_by = self.context.get("created_by")

        family_members = []
        for item in validated_data:
            # Pass created_by in context for each item serializer
            serializer = AddFamilyMemberSerializer(
                data=item, 
                context={"primary_client": primary_client, "created_by": created_by}
            )
            serializer.is_valid(raise_exception=True)
            instance = serializer.save()
            family_members.append(instance)
        return family_members

# class AddFamilyMemberSerializer(serializers.ModelSerializer):
    
#     client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
#     aadhaar_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
#     pan_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
#     dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)
    
#     created_by = serializers.SerializerMethodField()

#     class Meta:
#         model = Client
#         list_serializer_class = FamilyMemberListSerializer
#         fields = [
#             "client_code", "client_salutation", "client_first_name",
#             "client_middle_name", "client_last_name", "dob", "gender", 
#             "contact_no", "email", "relation", "crossrelation",
#             "aadhaar_no", "aadhaar_card_file",
#             "pan_no", "pan_card_file",
#             "client_passport",
#             "created_by", "created_at",
#         ]

#     def get_created_by(self, obj):
#         return obj.created_by.username if obj.created_by else None

#     @transaction.atomic
#     def create(self, validated_data):
#         primary_client = self.context.get("primary_client")
#         created_by = self.context.get("created_by")

#         # Normalize DOB
#         dob_value = validated_data.get("dob")
#         if not dob_value or dob_value in ["", "null", None]:
#             validated_data["dob"] = None
#         elif isinstance(dob_value, str):
#             try:
#                 validated_data["dob"] = datetime.strptime(dob_value, "%Y-%m-%d").date()
#             except ValueError:
#                 validated_data["dob"] = None

#         # Extract nested serializers data as necessary
#         passports_data = validated_data.pop("client_passport", [])
#         aadhaar_file = validated_data.pop("aadhaar_card_file", None)
#         pan_file = validated_data.pop("pan_card_file", None)

#         # Required fields validation
#         if not validated_data.get("client_code") or not validated_data.get("client_first_name"):
#             raise serializers.ValidationError({
#                 "detail": "client_code and client_first_name are required to create a family member."
#             })

#         fam_data = {
#             "ref_client": primary_client,
#             "client_type": "Family Member",
#             "client_status": 1,
#             "client_code": validated_data.get("client_code"),
#             "client_first_name": validated_data.get("client_first_name"),
#             "client_middle_name": validated_data.get("client_middle_name", ""),
#             "client_last_name": validated_data.get("client_last_name", ""),
#             "client_salutation": validated_data.get("client_salutation", ""),
#             "relation": validated_data.get("relation", ""),
#             "crossrelation": validated_data.get("crossrelation", ""),
#             "contact_no": validated_data.get("contact_no", ""),
#             "email": validated_data.get("email", ""),
#             "dob": validated_data.get("dob"),
#             "gender": validated_data.get("gender", ""),
#             "occupation": validated_data.get("occupation", ""),
#             "aadhaar_no": validated_data.get("aadhaar_no", ""),
#             "aadhaar_card_file": aadhaar_file,
#             "pan_no": validated_data.get("pan_no", ""),
#             "pan_card_file": pan_file,
#             "created_by": created_by,
#         }

#         # Create Client instance
#         fam_client = Client.objects.create(**fam_data)

#         # Save passports if meaningful data exists
#         for pd in passports_data:
#             passport_no = pd.get("passport_no") or pd.get("passportNo")
#             passport_file = pd.get("passport_file")
#             expiry_value = pd.get("passport_expiry_date") or pd.get("expiry")

#             if not passport_no and not passport_file:
#                 continue  # skip empty passport entry

#             if isinstance(expiry_value, str):
#                 try:
#                     expiry_value = datetime.strptime(expiry_value, "%Y-%m-%d").date()
#                 except ValueError:
#                     expiry_value = None

#             ClientPassport.objects.create(
#                 ref_client=fam_client,
#                 passport_no=passport_no,
#                 passport_expiry_date=expiry_value,
#                 passport_file=passport_file
#             )

#         # Save relations
#         if fam_data.get("relation"):
#             ClientRelation.objects.create(
#                 from_client=primary_client, to_client=fam_client, relation=fam_data["relation"]
#             )
#         if fam_data.get("crossrelation"):
#             ClientRelation.objects.create(
#                 from_client=fam_client, to_client=primary_client, relation=fam_data["crossrelation"]
#             )

#         return fam_client

#     def to_representation(self, instance):
#         rep = super().to_representation(instance)
#         if instance.created_by:
#             rep["created_by"] = instance.created_by.username
#         return rep

class AddFamilyMemberSerializer(serializers.ModelSerializer):
    client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)
    aadhaar_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
    pan_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
    dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    created_by = serializers.SerializerMethodField()

    class Meta:
        model = Client
        list_serializer_class = FamilyMemberListSerializer
        fields = [
            "client_code", "client_salutation", "client_first_name",
            "client_middle_name", "client_last_name", "dob", "gender",
            "contact_no", "email", "relation", "crossrelation",
            "aadhaar_no", "aadhaar_card_file",
            "pan_no", "pan_card_file",
            "client_passport",
            "created_by", "created_at",
        ]

    def get_created_by(self, obj):
        return obj.created_by.username if obj.created_by else None

    def validate_aadhaar_card_file(self, value):
        if value is None:
            return None
        if not isinstance(value, (InMemoryUploadedFile, TemporaryUploadedFile)):
            raise serializers.ValidationError("Invalid file format for aadhaar_card_file.")
        return value

    def validate_pan_card_file(self, value):
        if value is None:
            return None
        if not isinstance(value, (InMemoryUploadedFile, TemporaryUploadedFile)):
            raise serializers.ValidationError("Invalid file format for pan_card_file.")
        return value

    # @transaction.atomic
    # def create(self, validated_data):
    #     primary_client = self.context.get("primary_client")
    #     created_by = self.context.get("created_by")

    #     # Normalize DOB
    #     dob_value = validated_data.get("dob")
    #     if not dob_value or dob_value in ["", "null", None]:
    #         validated_data["dob"] = None
    #     elif isinstance(dob_value, str):
    #         try:
    #             validated_data["dob"] = datetime.strptime(dob_value, "%Y-%m-%d").date()
    #         except ValueError:
    #             validated_data["dob"] = None

    #     # Extract nested serializers data
    #     passports_data = validated_data.pop("client_passport", [])
    #     aadhaar_file = validated_data.pop("aadhaar_card_file", None)
    #     pan_file = validated_data.pop("pan_card_file", None)

    #     # Required fields validation
    #     if not validated_data.get("client_code") or not validated_data.get("client_first_name"):
    #         raise serializers.ValidationError({
    #             "detail": "client_code and client_first_name are required to create a family member."
    #         })

    #     # Prepare family member data
    #     fam_data = {
    #         "ref_client": primary_client,
    #         "client_type": "Family Member",
    #         "client_status": 1,
    #         "client_code": validated_data.get("client_code"),
    #         "client_first_name": validated_data.get("client_first_name"),
    #         "client_middle_name": validated_data.get("client_middle_name", ""),
    #         "client_last_name": validated_data.get("client_last_name", ""),
    #         "client_salutation": validated_data.get("client_salutation", ""),
    #         "relation": validated_data.get("relation", ""),
    #         "crossrelation": validated_data.get("crossrelation", ""),
    #         "contact_no": validated_data.get("contact_no", ""),
    #         "email": validated_data.get("email", ""),
    #         "dob": validated_data.get("dob"),
    #         "gender": validated_data.get("gender", ""),
    #         "occupation": validated_data.get("occupation", ""),
    #         "aadhaar_no": validated_data.get("aadhaar_no", ""),
    #         "aadhaar_card_file": aadhaar_file,
    #         "pan_no": validated_data.get("pan_no", ""),
    #         "pan_card_file": pan_file,
    #         "created_by": created_by,
    #     }

    #     # Create Client instance
    #     try:
    #         fam_client = Client.objects.create(**fam_data)
    #     except Exception as e:
    #         raise serializers.ValidationError({"detail": f"Failed to create client: {str(e)}"})

    #     # Save passports if meaningful data exists
    #     for pd in passports_data:
    #         passport_no = pd.get("passport_no") or pd.get("passportNo")
    #         passport_file = pd.get("passport_file")
    #         expiry_value = pd.get("passport_expiry_date") or pd.get("expiry")

    #         if not passport_no and not passport_file:
    #             continue  # Skip empty passport entry

    #         if isinstance(expiry_value, str):
    #             try:
    #                 expiry_value = datetime.strptime(expiry_value, "%Y-%m-%d").date()
    #             except ValueError:
    #                 expiry_value = None

    #         try:
    #             ClientPassport.objects.create(
    #                 ref_client=fam_client,
    #                 passport_no=passport_no,
    #                 passport_expiry_date=expiry_value,
    #                 passport_file=passport_file
    #             )
    #         except Exception as e:
    #             raise serializers.ValidationError({"detail": f"Failed to create passport: {str(e)}"})

    #     # Save relations
    #     if fam_data.get("relation"):
    #         ClientRelation.objects.create(
    #             from_client=primary_client, to_client=fam_client, relation=fam_data["relation"]
    #         )
    #     if fam_data.get("crossrelation"):
    #         ClientRelation.objects.create(
    #             from_client=fam_client, to_client=primary_client, relation=fam_data["crossrelation"]
    #         )

    #     return fam_client

    # 
    
    @transaction.atomic
    def create(self, validated_data):
        primary_client = self.context.get("primary_client")
        created_by = self.context.get("created_by")

        # Normalize DOB
        dob_value = validated_data.get("dob")
        if not dob_value or dob_value in ["", "null", None]:
            validated_data["dob"] = None
        elif isinstance(dob_value, str):
            try:
                validated_data["dob"] = datetime.strptime(dob_value, "%Y-%m-%d").date()
            except ValueError:
                validated_data["dob"] = None

        # Extract nested serializers data
        passports_data = validated_data.pop("client_passport", [])
        aadhaar_file = validated_data.pop("aadhaar_card_file", None)
        pan_file = validated_data.pop("pan_card_file", None)

        # Required fields validation
        if not validated_data.get("client_code") or not validated_data.get("client_first_name"):
            raise serializers.ValidationError({
                "detail": "client_code and client_first_name are required to create a family member."
            })

        # Prepare family member data
        fam_data = {
            "ref_client": primary_client,
            "client_type": "Family Member",
            "client_status": 1,
            "client_code": validated_data.get("client_code"),
            "client_first_name": validated_data.get("client_first_name"),
            "client_middle_name": validated_data.get("client_middle_name", ""),
            "client_last_name": validated_data.get("client_last_name", ""),
            "client_salutation": validated_data.get("client_salutation", ""),
            "relation": validated_data.get("relation", ""),
            "crossrelation": validated_data.get("crossrelation", ""),
            "contact_no": validated_data.get("contact_no", ""),
            "email": validated_data.get("email", ""),
            "dob": validated_data.get("dob"),
            "gender": validated_data.get("gender", ""),
            "occupation": validated_data.get("occupation", ""),
            "aadhaar_no": validated_data.get("aadhaar_no", ""),
            "aadhaar_card_file": aadhaar_file,
            "pan_no": validated_data.get("pan_no", ""),
            "pan_card_file": pan_file,
            "created_by": created_by,
        }

        # Create Client instance
        try:
            fam_client = Client.objects.create(**fam_data)
        except Exception as e:
            raise serializers.ValidationError({"detail": f"Failed to create client: {str(e)}"})

        # Save passports if meaningful data exists
        for pd in passports_data:
            passport_no = pd.get("passport_no") or pd.get("passportNo")
            passport_file = pd.get("passport_file")
            expiry_value = pd.get("passport_expiry_date") or pd.get("expiry")

            # Modified condition: Create passport if at least one of passport_no or passport_expiry_date is provided
            if not passport_no and not expiry_value and not passport_file:
                continue  # Skip if all passport fields are empty

            if isinstance(expiry_value, str):
                try:
                    expiry_value = datetime.strptime(expiry_value, "%Y-%m-%d").date()
                except ValueError:
                    expiry_value = None

            try:
                ClientPassport.objects.create(
                    ref_client=fam_client,
                    passport_no=passport_no if passport_no else None,
                    passport_expiry_date=expiry_value,
                    passport_file=passport_file
                )
            except Exception as e:
                raise serializers.ValidationError({"detail": f"Failed to create passport: {str(e)}"})

        # Save relations
        if fam_data.get("relation"):
            ClientRelation.objects.create(
                from_client=primary_client, to_client=fam_client, relation=fam_data["relation"]
            )
        if fam_data.get("crossrelation"):
            ClientRelation.objects.create(
                from_client=fam_client, to_client=primary_client, relation=fam_data["crossrelation"]
            )

        return fam_client
    
    def to_representation(self, instance):
        rep = super().to_representation(instance)
        if instance.created_by:
            rep["created_by"] = instance.created_by.username
        return rep

'''
class AddFamilyMemberSerializer(serializers.ModelSerializer):
    client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)

    # Use CharField so "" or null is accepted, actual file will still be picked up
    aadhaar_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
    pan_card_file = serializers.FileField(required=False, allow_null=True, use_url=True)
    dob = serializers.CharField(required=False, allow_blank=True, allow_null=True)

    class Meta:
        model = Client
        list_serializer_class = FamilyMemberListSerializer
        fields = [
            "client_code", "client_salutation", "client_first_name",
            "client_middle_name", "client_last_name", "dob", "gender",
            "contact_no", "email", "relation", "crossrelation",
            "aadhaar_no", "aadhaar_card_file",
            "pan_no", "pan_card_file",
            "client_passport",
        ]
        read_only_fields = ("created_at", "created_by", "updated_at", "updated_by")

    @transaction.atomic
    def create(self, validated_data):
        primary_client = self.context["primary_client"]
        request = self.context.get("request")
        user = request.user if request and hasattr(request, "user") else None

        # --- Normalize DOB ---
        dob_value = validated_data.get("dob")
        if not dob_value or dob_value in ["", "null", None]:
            validated_data["dob"] = None
        elif isinstance(dob_value, str):
            try:
                validated_data["dob"] = datetime.strptime(dob_value, "%Y-%m-%d").date()
            except ValueError:
                validated_data["dob"] = None  # fallback

        # Extract passports if provided
        passports_data = validated_data.pop("client_passport", [])
        aadhaar_file = validated_data.pop("aadhaar_card_file", None)
        pan_file = validated_data.pop("pan_card_file", None)
        validated_data.pop("created_by", None)

        # Minimal required fields check
        if not validated_data.get("client_code") or not validated_data.get("client_first_name"):
            raise serializers.ValidationError(
                {"detail": "client_code and client_first_name are required to create a family member."}
            )

        # Build family member data
        fam_data = {
            "ref_client": primary_client,
            "client_type": "Family Member",
            "client_status": 1,
            "client_code": validated_data.get("client_code"),
            "client_first_name": validated_data.get("client_first_name"),
            "client_middle_name": validated_data.get("client_middle_name", ""),
            "client_last_name": validated_data.get("client_last_name", ""),
            "client_salutation": validated_data.get("client_salutation", ""),
            "relation": validated_data.get("relation", ""),
            "crossrelation": validated_data.get("crossrelation", ""),
            "contact_no": validated_data.get("contact_no", ""),
            "email": validated_data.get("email", ""),
            "dob": validated_data.get("dob"),
            "gender": validated_data.get("gender", ""),
            "occupation": validated_data.get("occupation", ""),
            "aadhaar_no": validated_data.get("aadhaar_no", ""),
            "aadhaar_card_file": aadhaar_file,
            "pan_no": validated_data.get("pan_no", ""),
            "pan_card_file": pan_file,
        }
        # fam_data.pop("created_by", None)
        print("DEBUG request.user:", self.context.get("request").user)
        fam_client = Client.objects.create(**fam_data, created_by=user, created_at=timezone.now(), client_type="Family Member", ref_client=primary_client)

        # Save passports if provided
        for pd in passports_data:
            expiry_value = pd.get("passport_expiry_date") or pd.get("expiry")
            if isinstance(expiry_value, str):
                try:
                    expiry_value = datetime.strptime(expiry_value, "%Y-%m-%d").date()
                except ValueError:
                    expiry_value = None

            ClientPassport.objects.create(
                ref_client=fam_client,
                passport_no=pd.get("passport_no") or pd.get("passportNo") or "",
                passport_expiry_date=expiry_value,
                passport_file=pd.get("passport_file")
            )

        # Save relations
        if fam_data.get("relation"):
            ClientRelation.objects.create(
                from_client=primary_client, to_client=fam_client, relation=fam_data["relation"]
            )
        if fam_data.get("crossrelation"):
            ClientRelation.objects.create(
                from_client=fam_client, to_client=primary_client, relation=fam_data["crossrelation"]
            )

        return fam_client
    
    def to_representation(self, instance):
        rep = super().to_representation(instance)
        if instance.created_by:
            rep["created_by"] = instance.created_by.username
        if instance.updated_by:
            rep["updated_by"] = instance.updated_by.username
        return rep

'''



'''
class FamilyMemberListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        primary_client = self.context["primary_client"]
        family_members = []
        for item in validated_data:
            serializer = AddFamilyMemberSerializer(
                data=item,
                context={"primary_client": primary_client}
            )
            serializer.is_valid(raise_exception=True)
            family_members.append(serializer.save())
        return family_members

class AddFamilyMemberSerializer(serializers.ModelSerializer):
    client_passport = ClientPassportSerializer(many=True, required=False, allow_null=True)

    class Meta:
        model = Client
        list_serializer_class = FamilyMemberListSerializer  # <-- enable multiple
        fields = [
            "client_code", "client_salutation", "client_first_name",
            "client_middle_name", "client_last_name", "dob", "gender",
            "contact_no", "email", "relation", "crossrelation", 
            "aadhaar_no", "aadhaar_card_file",
            "pan_no", "pan_card_file",
            "client_passport",
        ]

    def create(self, validated_data):
        passports_data = validated_data.pop("client_passport", [])
        primary_client = self.context["primary_client"]

        validated_data["ref_client"] = primary_client
        validated_data["client_type"] = "Family Member"
        validated_data.setdefault("client_status", "Active")

        fam_client = Client.objects.create(**validated_data)

        for pd in passports_data:
            ClientPassport.objects.create(ref_client=fam_client, **pd)

        relation = validated_data.get("relation")
        crossrelation = validated_data.get("crossrelation")
        if relation:
            ClientRelation.objects.create(from_client=primary_client, to_client=fam_client, relation=relation)
        if crossrelation:
            ClientRelation.objects.create(from_client=fam_client, to_client=primary_client, relation=crossrelation)

        return fam_client
'''

'''
class FullClientSerializer(serializers.ModelSerializer):
    client_passport = ClientPassportSerializer(many=True, required=False)
    client_visa = ClientVisaSerializer(many=True, required=False)
    travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False)
    client_companies = AssocClientCompanySerializer(many=True, required=False)
    client_documents = OtherDocumentSerializer(many=True, required=False)

    # other_document = serializers.FileField(many=True, required=False, allow_null=True)
    other_document = serializers.ListField(child=serializers.FileField(), required=False, allow_empty=True)
    other_document_name = serializers.ListField(child=serializers.CharField(allow_blank=True), required=False, allow_empty=True)

    # FAMILY MEMBERS
    family_members = serializers.SerializerMethodField(read_only=True)
    familyMembers = FamilyMemberInSerializer(many=True, write_only=True, required=False)

    # Residential fields for writes
    residential_city = serializers.PrimaryKeyRelatedField(
        queryset=Cities.objects.all(), write_only=True, required=False
    )
    residential_state = serializers.PrimaryKeyRelatedField(
        queryset=State.objects.all(), write_only=True, required=False
    )
    residential_country = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), write_only=True, required=False
    )

    # Residential fields for reads
    residential_city = CitySerializer(read_only=True)
    residential_state = StateSerializer(read_only=True)
    residential_country = CountrySerializer(read_only=True)

    class Meta:
        model = Client
        fields = [
            "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
            "client_middle_name", "client_last_name", "dob", "country_code", "contact_no", "email", "gender",
            "residential_address", "residential_city", "residential_state", "residential_country", "residential_pincode",
            "marital_status", "anniversary_date", "reference_from", "reference_remark", "occupation",
            "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
            "ref_preferred_airline", "star_rating", "stay_preference", "room_preference", "extra_amenities",
            "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
            "other_document", "other_document_name",
            "created_at", "created_by", "updated_at", "updated_by",
            "client_passport", "client_visa", "travel_insurance", "client_companies", "client_documents",
            "family_members", "familyMembers"
        ]

    def get_family_members(self, obj):
        members = Client.objects.filter(ref_client_id=obj.client_id)
        return FullClientSerializer(members, many=True, context=self.context).data

    def to_internal_value(self, data):
        # Wrap single dicts in list if needed
        for field in ["client_passport", "client_visa", "travel_insurance", "client_companies", "client_documents", "familyMembers"]:
            if isinstance(data.get(field), dict):
                data[field] = [data[field]]
        return super().to_internal_value(data)

    @transaction.atomic
    def create(self, validated_data):
        passports_data = validated_data.pop('client_passport', [])
        visas_data = validated_data.pop('client_visa', [])
        insurances_data = validated_data.pop('travel_insurance', [])
        docs_data = validated_data.pop('client_documents', [])
        companies_data = validated_data.pop('client_companies', [])
        family_data = validated_data.pop('familyMembers', [])

        validated_data["client_type"] = "Primary Member"
        validated_data.setdefault("client_status", "Active")

        client = Client.objects.create(**validated_data)

        # RELATED OBJECTS
        for pd in passports_data:
            ClientPassport.objects.create(ref_client=client, **pd)
        for vd in visas_data:
            ClientVisa.objects.create(ref_client=client, **vd)
        for ins in insurances_data:
            ClientTravelInsurance.objects.create(ref_client=client, **ins)
        for doc in docs_data:
            ClientDocument.objects.create(ref_client=client, **doc)
        for comp in companies_data:
            AssocClientCompany.objects.create(ref_client_id=client, **comp)

        # FAMILY MEMBERS
        created_family = []
        for fam in family_data:
            fam_data = Client.objects.create(
                ref_client_id=client.client_id,
                client_type="Family Member",
                client_status="Active",
                client_code=fam.get("clientCode") or "",
                client_salutation=fam.get("salutation") or "",
                client_first_name=fam.get("firstName") or "",
                client_middle_name=fam.get("middleName") or "",
                client_last_name=fam.get("lastName") or "",
                country_code_id=fam.get("countryCode"),
                contact_no=fam.get("contactNo") or "",
                email=fam.get("email") or "",
                dob=fam.get("dob") or None,
                gender=fam.get("gender") or "",
                occupation=fam.get("occupation") or "",
                aadhaar_no=fam.get("aadhaarNo") or "",
                aadhaar_card_file=fam.get("aadhaarCard"),
                pan_no=fam.get("panNo") or "",
                pan_card_file=fam.get("panCard"),
            )

            # Copy address from primary client if missing
            fam_data["residential_address"] = fam.get("residential_address") or client.residential_address
            fam_data["residential_city"] = fam.get("residential_city") or client.residential_city
            fam_data["residential_state"] = fam.get("residential_state") or client.residential_state
            fam_data["residential_country"] = fam.get("residential_country") or client.residential_country
            fam_data["residential_pincode"] = fam.get("residential_pincode") or client.residential_pincode

            fam_client = Client.objects.create(**fam_data)

            # Main <-> family relations
            if fam.get("relation"):
                ClientRelation.objects.create(from_client=client, to_client=fam_client, relation=fam.get("relation"))
            if fam.get("crossRelation"):
                ClientRelation.objects.create(from_client=fam_client, to_client=client, relation=fam.get("crossRelation"))

            # Family passports
            for pp in fam.get("passports", []):
                ClientPassport.objects.create(
                    ref_client=fam_client,
                    passport_no=pp.get("passportNo") or "",
                    passport_expiry_date=pp.get("passportExpiry"),
                    passport_file=pp.get("passportFile"),
                )

            created_family.append(fam_client)

        # Relations BETWEEN family members
        for idx, fam in enumerate(family_data):
            this_client = created_family[idx]
            for rel in fam.get("relationsWithOthers", []) or []:
                j = rel.get("toIndex", 0)
                j = j - 1 if j > 0 else j
                if j < 0 or j >= len(created_family) or j == idx:
                    continue
                other = created_family[j]
                if rel.get("relation"):
                    ClientRelation.objects.create(from_client=this_client, to_client=other, relation=rel.get("relation"))
                if rel.get("crossRelation"):
                    ClientRelation.objects.create(from_client=other, to_client=this_client, relation=rel.get("crossRelation"))

        return client

    @transaction.atomic
    def update(self, instance, validated_data):
        passports_data = validated_data.pop('client_passport', None)
        visas_data = validated_data.pop('client_visa', None)
        insurances_data = validated_data.pop('travel_insurance', None)
        docs_data = validated_data.pop('client_documents', None)
        companies_data = validated_data.pop('client_companies', None)
        family_data = validated_data.pop('familyMembers', None)

        validated_data["client_type"] = "Primary Member"
        validated_data.setdefault("client_status", "Active")

        # Update main client
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        # RELATED OBJECTS
        if passports_data is not None:
            ClientPassport.objects.filter(ref_client=instance).delete()
            for pd in passports_data:
                ClientPassport.objects.create(ref_client=instance, **pd)

        if visas_data is not None:
            ClientVisa.objects.filter(ref_client=instance).delete()
            for vd in visas_data:
                ClientVisa.objects.create(ref_client=instance, **vd)

        if insurances_data is not None:
            ClientTravelInsurance.objects.filter(ref_client=instance).delete()
            for ins in insurances_data:
                ClientTravelInsurance.objects.create(ref_client=instance, **ins)

        if docs_data is not None:
            ClientDocument.objects.filter(ref_client=instance).delete()
            for doc in docs_data:
                ClientDocument.objects.create(ref_client=instance, **doc)

        if companies_data is not None:
            AssocClientCompany.objects.filter(ref_client=instance).delete()
            for comp in companies_data:
                AssocClientCompany.objects.create(ref_client_id=instance, **comp)

        # FAMILY MEMBERS
        if family_data is not None:
            # Delete existing family members
            Client.objects.filter(ref_client_id=instance.client_id).delete()
            created_family = []

            for fam in family_data:
                fam_data = {
                    "ref_client_id": instance.client_id,
                    "client_type": "Family Member",
                    "client_status": "Active",
                    "client_code": fam.get("clientCode") or "",
                    "client_salutation": fam.get("salutation") or "",
                    "client_first_name": fam.get("firstName") or "",
                    "client_middle_name": fam.get("middleName") or "",
                    "client_last_name": fam.get("lastName") or "",
                    "country_code_id": fam.get("countryCode"),
                    "contact_no": fam.get("contactNo") or "",
                    "email": fam.get("email") or "",
                    "dob": fam.get("dob") or None,
                    "gender": fam.get("gender") or "",
                    "occupation": fam.get("occupation") or "",
                    "aadhaar_no": fam.get("aadhaarNo") or "",
                    "aadhaar_card_file": fam.get("aadhaarCard"),
                    "pan_no": fam.get("panNo") or "",
                    "pan_card_file": fam.get("panCard"),
                }

                # Copy address if missing
                fam_data["residential_address"] = fam.get("residential_address") or instance.residential_address
                fam_data["residential_city"] = fam.get("residential_city") or instance.residential_city
                fam_data["residential_state"] = fam.get("residential_state") or instance.residential_state
                fam_data["residential_country"] = fam.get("residential_country") or instance.residential_country
                fam_data["residential_pincode"] = fam.get("residential_pincode") or instance.residential_pincode

                fam_client = Client.objects.create(**fam_data)

                # Main <-> family relations
                if fam.get("relation"):
                    ClientRelation.objects.create(from_client=instance, to_client=fam_client, relation=fam.get("relation"))
                if fam.get("crossRelation"):
                    ClientRelation.objects.create(from_client=fam_client, to_client=instance, relation=fam.get("crossRelation"))

                # Family passports
                for pp in fam.get("passports", []):
                    ClientPassport.objects.create(
                        ref_client=fam_client,
                        passport_no=pp.get("passportNo") or "",
                        passport_expiry_date=pp.get("passportExpiry") or None,
                        passport_file=pp.get("passportFile"),
                    )

                created_family.append(fam_client)

            # Relations BETWEEN family members
            for idx, fam in enumerate(family_data):
                this_client = created_family[idx]
                for rel in fam.get("relationsWithOthers", []) or []:
                    j = rel.get("toIndex", 0)
                    j = j - 1 if j > 0 else j
                    if j < 0 or j >= len(created_family) or j == idx:
                        continue
                    other = created_family[j]
                    if rel.get("relation"):
                        ClientRelation.objects.create(from_client=this_client, to_client=other, relation=rel.get("relation"))
                    if rel.get("crossRelation"):
                        ClientRelation.objects.create(
                            from_client=other, to_client=this_client, relation=rel.get("crossRelation")
                        )

        return instance
'''

'''
class FullClientSerializer(serializers.ModelSerializer):
    client_passport = ClientPassportSerializer(many=True, required=False)
    client_visa = ClientVisaSerializer(many=True, required=False)
    travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False)
    client_companies = AssocClientCompanySerializer(many=True, required=False)
    client_documents = OtherDocumentSerializer(many=True, required=False)

    residential_city = serializers.PrimaryKeyRelatedField(read_only=True)
    residential_state = serializers.PrimaryKeyRelatedField(read_only=True)
    residential_country = serializers.PrimaryKeyRelatedField(read_only=True)
    # country_code = serializers.PrimaryKeyRelatedField(read_only=True)

    created_at = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
    updated_at = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)

    other_document = serializers.CharField(required=False, allow_null=True)
    other_document_name = serializers.CharField(required=False, allow_null=True)

    # For writes (accept ID)
    residential_city = serializers.PrimaryKeyRelatedField(
        queryset=Cities.objects.all(), source="residential_city", write_only=True, required=False
    )
    residential_state = serializers.PrimaryKeyRelatedField(
        queryset=State.objects.all(), source="residential_state", write_only=True, required=False
    )
    residential_country = serializers.PrimaryKeyRelatedField(
        queryset=Countries.objects.all(), source="residential_country", write_only=True, required=False
    )

    # residential_city = serializers.PrimaryKeyRelatedField(
    #     queryset=Cities.objects.all(), required=False
    # )
    # residential_state = serializers.PrimaryKeyRelatedField(
    #     queryset=State.objects.all(), required=False
    # )
    # residential_country = serializers.PrimaryKeyRelatedField(
    #     queryset=Countries.objects.all(), required=False
    # )

    

    # For reads (nested representation)
    residential_city = CitySerializer(read_only=True)
    residential_state = StateSerializer(read_only=True)
    residential_country = CountrySerializer(read_only=True)

    # company_country = serializers.PrimaryKeyRelatedField(
    #     queryset=Countries.objects.all(), required=False, allow_null=True
    # )
    # company_state = serializers.PrimaryKeyRelatedField(
    #     queryset=State.objects.all(), required=False
    # )
    # company_city = serializers.PrimaryKeyRelatedField(
    #     queryset=Cities.objects.all(), required=False
    # )

    class Meta:
        model = Client
        fields = [
            "client_id", "client_code", "client_type", "client_salutation", "client_first_name",
            "client_middle_name", "client_last_name", "dob", "country_code", "contact_no", "email", "gender",
            "residential_address", "residential_city", "residential_state", "residential_country", "residential_pincode",
            "marital_status", "anniversary_date", "reference_from", "reference_remark", "occupation",
            "preferred_contact_method", "aadhaar_no", "pan_no", "aadhaar_card_file", "pan_card_file",
            "ref_preferred_airline", "star_rating", "stay_preference", "room_preference", "extra_amenities",
            "seat_preference", "seat_preference_other", "meal_preference", "fare_preference",
            "other_document", "other_document_name",
            # "visa_type", "passport_size_photograph", "visa_from_date", "visa_to_date",
            "created_at", "created_by", "updated_at", "updated_by",
            "client_passport", "client_visa", "travel_insurance", "client_companies", "client_documents",
        ]

    # def to_representation(self, instance):
    #     data = super().to_representation(instance)

    #     if instance.residential_country:
    #         data["residential_country"] = {
    #             "id": instance.residential_country.id,
    #             "name": instance.residential_country.name,
    #         }

    #     if instance.residential_state:
    #         data["residential_state"] = {
    #             "id": instance.residential_state.id,
    #             "name": instance.residential_state.name,
    #         }

    #     if instance.residential_city:
    #         data["residential_city"] = {
    #             "id": instance.residential_city.id,
    #             "name": instance.residential_city.name,
    #         }

    #     return data

    def get_aadhaar_card_file_url(self, obj):
        if obj.aadhaar_card_file and hasattr(obj.aadhaar_card_file, "url"):
            return obj.aadhaar_card_file.url
        return None
    
    def get_pan_card_file(self, obj):
        return obj.pan_card_file.url if obj.pan_card_file else None
    
    def get_residential_country(self, obj):
        if obj.residential_country:
            return {
                "id": obj.residential_country.id,
                "name": obj.residential_country.country_name
            }
        return None

    def get_residential_state(self, obj):
        if obj.residential_state:
            return {
                "id": obj.residential_state.id,
                "name": obj.residential_state.state_name
            }
        return None

    def get_residential_city(self, obj):
        if obj.residential_city:
            return {
                "id": obj.residential_city.id,
                "name": obj.residential_city.city_name
            }
        return None
    
    def to_internal_value(self, data):
        for field in ["client_passport", "client_visa", "travel_insurance", "client_companies", "client_documents"]:
            if isinstance(data.get(field), dict):
                data[field] = [data[field]]  # auto-wrap single dict in a list
        return super().to_internal_value(data)
    

    def create(self, validated_data):
        passports_data = validated_data.pop('client_passport', [])
        visas_data = validated_data.pop('client_visa', [])
        insurances_data = validated_data.pop('travel_insurance', [])
        docs_data = validated_data.pop('client_documents', [])
        companies_data = validated_data.pop('client_companies', [])

        client = Client.objects.create(**validated_data)

        for pd in passports_data:
            ClientPassport.objects.create(ref_client=client, **pd)

        for vd in visas_data:
            ClientVisa.objects.create(ref_client=client, **vd)

        for ins in insurances_data:
            ClientTravelInsurance.objects.create(ref_client=client, **ins)
        for doc in docs_data:
            ClientDocument.objects.create(ref_client=client, **doc)
        for comp in companies_data:
            AssocClientCompany.objects.create(ref_client_id=client, **comp)

        return client

    def update(self, instance, validated_data):
        passports_data = validated_data.pop('client_passport', None)
        visas_data = validated_data.pop('client_visa', None)
        insurances_data = validated_data.pop('travel_insurance', None)
        docs_data = validated_data.pop('client_documents', None)
        companies_data = validated_data.pop('client_companies', None)

        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        if passports_data is not None:
            ClientPassport.objects.filter(ref_client=instance).delete()
            for pd in passports_data:
                ClientPassport.objects.create(ref_client=instance, **pd)
        if visas_data is not None:
            ClientVisa.objects.filter(ref_client=instance).delete()
            for vd in visas_data:
                ClientVisa.objects.create(ref_client=instance, **vd)
        if insurances_data is not None:
            ClientTravelInsurance.objects.filter(ref_client=instance).delete()
            for ins in insurances_data:
                ClientTravelInsurance.objects.create(ref_client=instance, **ins)
        if docs_data:
            ClientDocument.objects.filter(ref_client=instance).delete()
        for doc in docs_data:
            ClientDocument.objects.create(ref_client=instance, **doc)
        if companies_data is not None:
            AssocClientCompany.objects.filter(ref_client=instance).delete()
            for comp in companies_data:
                AssocClientCompany.objects.create(ref_client_ids=instance, **comp)

        return instance
'''

'''
# Nested serializers
class ClientPassportSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientPassport
        fields = ['passport_file', 'passport_no', 'passport_expiry_date']

class ClientVisaSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientVisa
        fields = ['ref_visa_country', 'visa_type']

class ClientTravelInsuranceSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientTravelInsurance
        fields = ['insurance_document', 'insurance_from_date', 'insurance_to_date']

class OtherDocumentSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientDocument
        fields = ['document_name', 'document_file']

class AssocClientCompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = AssocClientCompany
        fields = ['company_name', 'designation', 'primary']

class FullClientSerializer(serializers.ModelSerializer):
    # Nested serializers
    client_passport = ClientPassportSerializer(many=True, required=False)
    client_visa = ClientVisaSerializer(many=True, required=False)
    travel_insurance = ClientTravelInsuranceSerializer(many=True, required=False)
    client_documents = OtherDocumentSerializer(many=True, required=False)
    client_companies = AssocClientCompanySerializer(many=True, required=False)

    class Meta:
        model = Client
        fields = [
            'client_code', 'client_salutation', 'client_first_name', 'client_middle_name', 'client_last_name',
            'dob', 'country_code', 'contact_no', 'email', 'gender', 'marital_status', 'anniversary_date',
            'reference_from', 'reference_remark', 'occupation', 'preferred_contact_method',
            'aadhaar_no', 'pan_no',
            'star_rating', 'stay_preference', 'room_preference', 'extra_amenities',
            'seat_preference', 'seat_preference_other', 'meal_preference', 'fare_preference',
            'client_passport', 'client_visa', 'travel_insurance', 'client_documents', 'client_companies'
        ]

    def create(self, validated_data):
        client_details_data = validated_data.pop('clientDetails', {})
        companies_data = validated_data.pop('companies', [])
        preferences_data = validated_data.pop('preferences', {})
        visa_travel_data = validated_data.pop('visaTravel', {})

        # Create client with clientDetails fields
        client = Client.objects.create(
            client_first_name=client_details_data.get('client_first_name', ''),
            client_middle_name=client_details_data.get('client_middle_name', ''),
            client_last_name=client_details_data.get('client_last_name', ''),
            client_code=client_details_data.get('client_code', ''),
            aadhaar_no=client_details_data.get('aadharNo', ''),
            pan_no=client_details_data.get('panNo', ''),
            # add other client fields here
        )

        # Preferences
        if preferences_data:
            client.star_rating = preferences_data.get('starRating', 0)
            client.stay_preference = preferences_data.get('stayPreference', '')
            client.room_preference = preferences_data.get('roomPreference', '')
            client.extra_amenities = preferences_data.get('extraAmenities', '')
            client.save()

        # Companies
        for comp in companies_data:
            AssocClientCompany.objects.create(
                ref_client=client,
                designation=comp.get('designation', ''),
                primary=comp.get('primary', False),
                company_name=comp.get('companyName', '')
            )

        # Visas
        for visa in visa_travel_data.get('visas', []):
            country_name = visa.get('country')
            country_obj = Countries.objects.filter(name=country_name).first() if country_name else None
            ClientVisa.objects.create(
                ref_client=client,
                ref_visa_country=country_obj,
                visa_type=visa.get('type', '')
            )

        return client

    def update(self, instance, validated_data):
        # Similar logic for update: update client + delete and recreate nested objects
        passports_data = validated_data.pop('client_passport', None)
        visas_data = validated_data.pop('client_visa', None)
        insurances_data = validated_data.pop('travel_insurance', None)
        documents_data = validated_data.pop('client_documents', None)
        companies_data = validated_data.pop('client_companies', None)

        # Update client fields
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        if passports_data is not None:
            ClientPassport.objects.filter(ref_client=instance).delete()
            for pd in passports_data:
                ClientPassport.objects.create(ref_client=instance, **pd)

        if visas_data is not None:
            ClientVisa.objects.filter(ref_client=instance).delete()
            for vd in visas_data:
                country_name = vd.pop('ref_visa_country', None)
                country_obj = None
                if country_name:
                    country_obj = Countries.objects.get(name=country_name)
                ClientVisa.objects.create(ref_client=instance, ref_visa_country=country_obj, **vd)

        if insurances_data is not None:
            ClientTravelInsurance.objects.filter(ref_client=instance).delete()
            for ins in insurances_data:
                ClientTravelInsurance.objects.create(ref_client=instance, **ins)

        if documents_data is not None:
            ClientDocument.objects.filter(ref_client=instance).delete()
            for doc in documents_data:
                ClientDocument.objects.create(ref_client=instance, **doc)

        if companies_data is not None:
            AssocClientCompany.objects.filter(ref_client=instance).delete()
            for comp in companies_data:
                if 'primary' in comp and isinstance(comp['primary'], str):
                    comp['primary'] = comp['primary'].lower() == 'true'
                AssocClientCompany.objects.create(ref_client=instance, **comp)

        return instance
'''



# ---------- Menus / Misc ----------
class MenuSerializer(serializers.ModelSerializer):
    submenus = serializers.SerializerMethodField()

    class Meta:
        model = Menu
        fields = [
            "id",
            "menu_name",
            "menu_action",
            "menu_url",
            "menu_order_no",
            "menu_default",
            "menu_status",
            "submenus",
        ]

    def get_submenus(self, obj):
        return MenuSerializer(obj.submenus.all(), many=True).data




class EmailSetupSerializer(serializers.ModelSerializer):
    # emails = ReportEmailSerializer(many=True)

    class Meta:
        model = EmailSetup
        fields = ["id", "report_type", "emails"]

    def create(self, validated_data):
        emails_data = validated_data.pop("emails", [])
        setup = EmailSetup.objects.create(**validated_data)

        # for email_data in emails_data:
        #     ReportEmail.objects.create(setup=setup, **email_data)

        return setup

    def update(self, instance, validated_data):
        emails_data = validated_data.pop("emails", [])

        # update report_type if changed
        instance.report_type = validated_data.get("report_type", instance.report_type)
        instance.save()

        # replace old emails with new ones
        # instance.emails.all().delete()
        # for email_data in emails_data:
        #     ReportEmail.objects.create(setup=instance, **email_data)

        return instance
