from rest_framework import serializers
from django.db import transaction
from django.contrib.auth.hashers import make_password, check_password   # ✅ Fix 2: added check_password
from .models import (
    Agency, Client, Employee, Agreement, ScopeNode, ResponsibilityNode,
    TimelinePhase, PaymentSection, PaymentMilestone, AnnexureTemplate,
    Annexure, Terms, AgreementTerms, CustomSection, AgreementAttachment,
    Signature, AgreementHistory, AgreementTemplate, TemplateSection,
    AgreementPageTemplate, AgreementPage
)
from agreements.utils.helper import generate_agreement_number, validate_timeline_overlap
import base64
import uuid
from django.core.files.base import ContentFile


class Base64ImageField(serializers.ImageField):
    """
    A Django REST framework field for handling image-uploads through raw post data.
    It uses base64 encoding for sending images.
    """
    def to_internal_value(self, data):
        if isinstance(data, str) and data.startswith('data:image'):
            # Base64 image
            format, imgstr = data.split(';base64,')
            ext = format.split('/')[-1]
            name = f"{uuid.uuid4()}.{ext}"
            data = ContentFile(base64.b64decode(imgstr), name=name)
        return super().to_internal_value(data)


# ---------- Basic serializers ----------
class AgencySerializer(serializers.ModelSerializer):
    class Meta:
        model = Agency
        fields = '__all__'


class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = '__all__'


class EmployeeSerializer(serializers.ModelSerializer):
    full_name = serializers.SerializerMethodField()
    username = serializers.SerializerMethodField()

    class Meta:
        model = Employee
        fields = ['id', 'user', 'designation', 'full_name', 'username']

    def get_full_name(self, obj):
        return obj.user.get_full_name()

    def get_username(self, obj):
        return obj.user.username


# ---------- Hierarchical Scope with Node Type ----------
class ScopeNodeWriteSerializer(serializers.ModelSerializer):
    agreement = serializers.HiddenField(default=None)
    children = serializers.ListSerializer(child=serializers.DictField(), required=False)
    parent = serializers.PrimaryKeyRelatedField(
        queryset=ScopeNode.objects.all(),
        required=False,
        allow_null=True
    )

    class Meta:
        model = ScopeNode
        fields = ['id', 'name', 'parent', 'description', 'node_type', 'order', 'children', 'agreement']
        read_only_fields = ['agreement']
        validators = []

    def create(self, validated_data):
        validated_data.pop("id", None)
        children_data = validated_data.pop('children', [])
        agreement = validated_data.pop("agreement", None)
        parent = validated_data.pop("parent", None)

        node = ScopeNode.objects.create(
            agreement=agreement,
            parent=parent,
            **validated_data
        )
        for index, child_data in enumerate(children_data):
            child_data = child_data.copy()
            child_data.pop("id", None)

            self.create({
                **child_data,
                "agreement": agreement,
                "parent": node,
                "order": index,
            })
        return node

    def update(self, instance, validated_data):
        validated_data.pop('agreement', None)
        children_data = validated_data.pop('children', None)
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        if children_data is not None:
            existing_ids = set(instance.children.values_list('id', flat=True))
            new_ids = set()
            for child_data in children_data:
                child_id = child_data.get('id')
                if child_id and child_id in existing_ids:
                    child = ScopeNode.objects.get(id=child_id, parent=instance)
                    child_serializer = ScopeNodeWriteSerializer(
                        child,
                        data=child_data,
                        partial=True,
                        context={'agreement': instance.agreement}
                    )
                    child_serializer.is_valid(raise_exception=True)
                    child_serializer.save()
                    new_ids.add(child_id)
                else:
                    child_data.pop('id', None)
                    child_data['parent'] = instance.pk
                    child_serializer = ScopeNodeWriteSerializer(
                        data=child_data,
                        context={'agreement': instance.agreement}
                    )
                    child_serializer.is_valid(raise_exception=True)
                    child_serializer.save()
                    new_ids.add(child_serializer.instance.id)
            to_delete = existing_ids - new_ids
            if to_delete:
                ScopeNode.objects.filter(id__in=to_delete).delete()
        return instance


class ScopeNodeReadSerializer(serializers.ModelSerializer):
    children = serializers.SerializerMethodField()

    class Meta:
        model = ScopeNode
        fields = [
            "id",
            "parent",
            "name",
            "description",
            "node_type",
            "order",
            "children",
        ]

    def get_children(self, obj):
        return ScopeNodeReadSerializer(
            obj.children.all().order_by("order"),
            many=True
        ).data


# Similarly for ResponsibilityNode with node_type
class ResponsibilityNodeWriteSerializer(serializers.ModelSerializer):
    agreement = serializers.HiddenField(default=None)
    children = serializers.ListSerializer(child=serializers.DictField(), required=False)
    parent = serializers.PrimaryKeyRelatedField(
        queryset=ResponsibilityNode.objects.all(),
        required=False,
        allow_null=True
    )

    class Meta:
        model = ResponsibilityNode
        fields = ['id', 'name', 'parent', 'description', 'node_type', 'order', 'children', 'agreement']
        read_only_fields = ['agreement']
        validators = []

    def create(self, validated_data):
        validated_data.pop("id", None)
        children_data = validated_data.pop('children', [])
        agreement = validated_data.pop("agreement", None)
        parent = validated_data.pop("parent", None)
        
        node = ResponsibilityNode.objects.create(
            agreement=agreement,
            parent=parent,
            **validated_data
        )
        print(
            f"Creating: {validated_data['name']} | "
            f"Parent={parent.id if parent else None} | "
            f"Order={validated_data.get('order')}"
        )
        for index, child_data in enumerate(children_data):
            child_data = child_data.copy()
            child_data.pop("id", None)

            self.create({
                **child_data,
                "agreement": agreement,
                "parent": node,
                "order": index,
            })
        return node

    def update(self, instance, validated_data):
        validated_data.pop('agreement', None)
        children_data = validated_data.pop('children', None)
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        if children_data is not None:
            existing_ids = set(instance.children.values_list('id', flat=True))
            new_ids = set()
            for child_data in children_data:
                child_id = child_data.get('id')
                if child_id and child_id in existing_ids:
                    child = ResponsibilityNode.objects.get(id=child_id, parent=instance)
                    child_serializer = ResponsibilityNodeWriteSerializer(
                        child,
                        data=child_data,
                        partial=True,
                        context={'agreement': instance.agreement}
                    )
                    child_serializer.is_valid(raise_exception=True)
                    child_serializer.save()
                    new_ids.add(child_id)
                else:
                    child_data.pop('id', None)
                    child_data['parent'] = instance.pk
                    child_serializer = ResponsibilityNodeWriteSerializer(
                        data=child_data,
                        context={'agreement': instance.agreement}
                    )
                    child_serializer.is_valid(raise_exception=True)
                    child_serializer.save()
                    new_ids.add(child_serializer.instance.id)
            to_delete = existing_ids - new_ids
            if to_delete:
                ResponsibilityNode.objects.filter(id__in=to_delete).delete()
        return instance


class ResponsibilityNodeReadSerializer(serializers.ModelSerializer):
    children = serializers.SerializerMethodField()

    class Meta:
        model = ResponsibilityNode
        fields = [
            "id",
            "parent",
            "name",
            "description",
            "node_type",
            "order",
            "children",
        ]

    def get_children(self, obj):
        return ResponsibilityNodeReadSerializer(
            obj.children.all().order_by("order"),
            many=True
        ).data


# ---------- Timeline Phase (duration is computed) ----------
class TimelinePhaseSerializer(serializers.ModelSerializer):
    duration_days = serializers.ReadOnlyField()

    class Meta:
        model = TimelinePhase
        fields = ['id', 'phase_name', 'description', 'start_day', 'end_day', 'duration_days', 'order', 'color', 'icon', 'progress', 'is_milestone']

    def validate(self, data):
        if data.get('start_day', 0) > data.get('end_day', 0):
            raise serializers.ValidationError("Start day cannot be after end day.")
        return data


# ---------- Payment Milestone ----------
class PaymentMilestoneSerializer(serializers.ModelSerializer):
    class Meta:
        model = PaymentMilestone
        fields = ['id', 'milestone_name', 'percentage', 'amount', 'due_date', 'order']

    def validate(self, data):
        if data['percentage'] < 0 or data['percentage'] > 100:
            raise serializers.ValidationError("Percentage must be between 0 and 100.")
        return data


# ---------- Payment Section (with stored calculations) ----------
class PaymentSectionSerializer(serializers.ModelSerializer):
    milestones = PaymentMilestoneSerializer(many=True, required=False)

    class Meta:
        model = PaymentSection
        fields = [
            'id', 'subtotal', 'currency', 'gst_percent', 'discount_percent',
            'tds_percent', 'advance_amount', 'gst_amount', 'discount_amount',
            'tds_amount', 'grand_total', 'final_payable', 'finalized',
            'payment_terms', 'milestones'
        ]
        read_only_fields = ['gst_amount', 'discount_amount', 'tds_amount', 'grand_total', 'final_payable', 'finalized']

    def validate(self, data):
        milestones_data = data.get('milestones', [])
        if milestones_data:
            total_percentage = sum(m.get('percentage', 0) for m in milestones_data)
            if total_percentage != 100:
                raise serializers.ValidationError("Total percentage of payment milestones must equal 100%.")
        return data

    def create(self, validated_data):
        milestones_data = validated_data.pop('milestones', [])
        payment = PaymentSection.objects.create(**validated_data)
        for milestone_data in milestones_data:
            if 'amount' not in milestone_data or milestone_data['amount'] is None:
                milestone_data['amount'] = (milestone_data['percentage'] / 100) * payment.subtotal
            PaymentMilestone.objects.create(payment=payment, **milestone_data)
        return payment

    def update(self, instance, validated_data):
        milestones_data = validated_data.pop('milestones', None)
    
        # Update normal payment fields
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
    
        instance.save()
    
        if milestones_data is not None:
    
            existing_milestones = {
                milestone.order: milestone
                for milestone in instance.milestones.all()
            }
    
            new_orders = set()
    
            for m_data in milestones_data:
    
                m_id = m_data.get('id')
                m_order = m_data.get('order')
    
                milestone = None
    
                # --------------------------------------------------
                # 1. Try ID first
                # --------------------------------------------------
                if m_id:
                    milestone = PaymentMilestone.objects.filter(
                        id=m_id,
                        payment=instance
                    ).first()
    
                # --------------------------------------------------
                # 2. If ID is missing, use order
                # --------------------------------------------------
                if milestone is None and m_order is not None:
                    milestone = existing_milestones.get(m_order)
    
                # --------------------------------------------------
                # 3. Existing milestone → UPDATE
                # --------------------------------------------------
                if milestone:
    
                    if 'percentage' in m_data:
                        m_data['amount'] = (
                            m_data['percentage'] / 100
                        ) * instance.subtotal
    
                    for attr, value in m_data.items():
                        if attr != 'id':
                            setattr(milestone, attr, value)
    
                    milestone.save()
    
                    new_orders.add(milestone.order)
    
                # --------------------------------------------------
                # 4. New milestone → CREATE
                # --------------------------------------------------
                else:
    
                    m_data.pop('id', None)
    
                    if (
                        'amount' not in m_data
                        or m_data['amount'] is None
                    ):
                        m_data['amount'] = (
                            m_data['percentage'] / 100
                        ) * instance.subtotal
    
                    milestone = PaymentMilestone.objects.create(
                        payment=instance,
                        **m_data
                    )
    
                    new_orders.add(milestone.order)
    
            # ------------------------------------------------------
            # Delete milestones removed from the request
            # ------------------------------------------------------
    
            existing_orders = set(existing_milestones.keys())
    
            orders_to_delete = existing_orders - new_orders
    
            if orders_to_delete:
                PaymentMilestone.objects.filter(
                    payment=instance,
                    order__in=orders_to_delete
                ).delete()
    
        return instance


# ---------- Annexure ----------
class AnnexureSerializer(serializers.ModelSerializer):
    class Meta:
        model = Annexure
        fields = ['id', 'content', 'template']


# ---------- AgreementTerms ----------
class AgreementTermsSerializer(serializers.ModelSerializer):
    class Meta:
        model = AgreementTerms
        fields = ['id', 'terms', 'order']


# ---------- CustomSection ----------
class CustomSectionSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomSection
        fields = ['id', 'section_type', 'name', 'content', 'order']


# ---------- Attachment ----------
class AgreementAttachmentSerializer(serializers.ModelSerializer):
    agreement_no = serializers.CharField(source='agreement.agreement_no', read_only=True)
    description = serializers.CharField(source='agreement.title', read_only=True)

    class Meta:
        model = AgreementAttachment
        fields = ['id', 'agreement', 'agreement_no', 'file', 'description', 'uploaded_at']
        read_only_fields = ['uploaded_at']


# ---------- Signature (with metadata) ----------
class SignatureSerializer(serializers.ModelSerializer):
    agency_signature = Base64ImageField(required=False, allow_null=True)
    client_signature = Base64ImageField(required=False, allow_null=True)

    class Meta:
        model = Signature
        # ✅ Fix 3: Added new fields from updated model
        fields = [
            'id', 'agency_name', 'agency_designation', 'agency_signature',
            'client_name', 'client_signature', 'signed_date',
            'ip_address', 'signed_time', 'device_info', 'browser_info', 'location',
            'signed_by_client', 'signed_by_agency', 'signature_hash'
        ]


# ---------- History ----------
class AgreementHistorySerializer(serializers.ModelSerializer):
    agreement_no = serializers.CharField(source='agreement.agreement_no', read_only=True)

    class Meta:
        model = AgreementHistory
        fields = ['id', 'action', 'user', 'timestamp', 'details', 'agreement_no']


# ---------- Template & Sections ----------
class TemplateSectionSerializer(serializers.ModelSerializer):
    class Meta:
        model = TemplateSection
        fields = ['id', 'section_type', 'data', 'order']


class AgreementTemplateSerializer(serializers.ModelSerializer):
    sections = TemplateSectionSerializer(many=True, required=False)

    class Meta:
        model = AgreementTemplate
        fields = ['id', 'name', 'description', 'created_at', 'sections']

    def create(self, validated_data):
        sections_data = validated_data.pop('sections', [])
        template = AgreementTemplate.objects.create(**validated_data)
        for section_data in sections_data:
            TemplateSection.objects.create(template=template, **section_data)
        return template

    def update(self, instance, validated_data):
        sections_data = validated_data.pop('sections', None)
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        if sections_data is not None:
            instance.sections.all().delete()
            for section_data in sections_data:
                TemplateSection.objects.create(template=instance, **section_data)
        return instance


# ---------- HTML Page Templates ----------
class AgreementPageTemplateSerializer(serializers.ModelSerializer):
    class Meta:
        model = AgreementPageTemplate
        fields = ['id', 'name', 'template_pdf', 'is_default']


class AgreementPageSerializer(serializers.ModelSerializer):
    class Meta:
        model = AgreementPage
        fields = ['id', 'page_template', 'rendered_html', 'created_at']


# ---------- Main Agreement Serializer ----------
class AgreementWriteSerializer(serializers.ModelSerializer):
    scope_nodes = ScopeNodeWriteSerializer(many=True, required=False)
    responsibility_nodes = ResponsibilityNodeWriteSerializer(many=True, required=False)
    timeline_phases = TimelinePhaseSerializer(many=True, required=False)
    payment = PaymentSectionSerializer(required=False)
    annexure = AnnexureSerializer(required=False)
    terms_links = AgreementTermsSerializer(many=True, required=False)
    custom_sections = CustomSectionSerializer(many=True, required=False)
    attachments = AgreementAttachmentSerializer(many=True, required=False, read_only=True)
    signature = SignatureSerializer(required=False)
    history = AgreementHistorySerializer(many=True, read_only=True)

    total_duration = serializers.SerializerMethodField()
    total_scopes = serializers.SerializerMethodField()
    total_responsibilities = serializers.SerializerMethodField()
    total_milestones = serializers.SerializerMethodField()

    agency_name = serializers.CharField(source='agency.company_name', read_only=True)
    principal_name = serializers.CharField(source='principal.company_name', read_only=True)

    client_password = serializers.CharField(write_only=True, required=False)

    # ✅ Fix 4 & 5: Read-only fields and new display fields
    client_sign_token = serializers.ReadOnlyField()
    client_signed = serializers.ReadOnlyField()
    client_viewed = serializers.ReadOnlyField()
    client_signed_at = serializers.ReadOnlyField()

    class Meta:
        model = Agreement
        fields = [
            'id', 'agreement_no', 'title', 'agreement_date', 'referred_by',
            'agency', 'principal', 'purpose', 'status',
            'version_number', 'is_latest', 'parent_agreement', 'template_used',
            'created_at', 'updated_at',
            'scope_nodes', 'responsibility_nodes', 'timeline_phases',
            'payment', 'annexure', 'terms_links', 'custom_sections',
            'attachments', 'signature', 'history', 'agency_name', 'principal_name',
            'total_duration', 'total_scopes', 'total_responsibilities', 'total_milestones',
            'client_password', 'client_sign_token', 'client_signed',
            'client_viewed', 'client_signed_at',   # ✅ Fix 5: added to fields
        ]
        # ✅ Fix 4: Mark fields that should never be editable
        read_only_fields = [
            'agreement_no', 'created_at', 'updated_at', 'version_number', 'is_latest',
            'client_sign_token', 'client_signed'
        ]

    def get_total_duration(self, obj):
        return obj.total_duration

    def get_total_scopes(self, obj):
        return obj.scope_nodes.filter(parent__isnull=True).count()

    def get_total_responsibilities(self, obj):
        return obj.responsibility_nodes.filter(parent__isnull=True).count()

    def get_total_milestones(self, obj):
        if hasattr(obj, 'payment'):
            return obj.payment.milestones.count()
        return 0

    def validate(self, data):
        timeline_data = data.get('timeline_phases', [])
        if timeline_data:
            phases = [{'start_day': p['start_day'], 'end_day': p['end_day']} for p in timeline_data]
            if not validate_timeline_overlap(phases):
                raise serializers.ValidationError("Timeline phases overlap.")
        return data

    @transaction.atomic
    def create(self, validated_data):
        scopes_data = validated_data.pop('scope_nodes', [])
        responsibilities_data = validated_data.pop('responsibility_nodes', [])
        timeline_data = validated_data.pop('timeline_phases', [])
        payment_data = validated_data.pop('payment', None)
        annexure_data = validated_data.pop('annexure', None)
        terms_data = validated_data.pop('terms_links', [])
        custom_data = validated_data.pop('custom_sections', [])
        signature_data = validated_data.pop('signature', None)


        password = validated_data.pop("client_password", None)

        # ✅ Fix 1: Create the agreement only once
        agreement = Agreement.objects.create(**validated_data)

        if password:
            agreement.client_access_password = make_password(password)
            agreement.save(update_fields=["client_access_password"])

        # No second creation – that line is removed.

        for scope_data in scopes_data:
            serializer = ScopeNodeWriteSerializer()
            serializer.create({
                **scope_data,
                "agreement": agreement,
            })

        for resp_data in responsibilities_data:
            serializer = ResponsibilityNodeWriteSerializer()
            serializer.create({
                **resp_data,
                "agreement": agreement,
            })

        for phase_data in timeline_data:
            TimelinePhase.objects.create(agreement=agreement, **phase_data)

        if payment_data:
            payment_serializer = PaymentSectionSerializer(data=payment_data)
            payment_serializer.is_valid(raise_exception=True)
            payment_serializer.save(agreement=agreement)

        if annexure_data:
            Annexure.objects.create(agreement=agreement, **annexure_data)

        for term_data in terms_data:
            AgreementTerms.objects.create(agreement=agreement, **term_data)

        for cs_data in custom_data:
            CustomSection.objects.create(agreement=agreement, **cs_data)

        if signature_data:
            Signature.objects.create(agreement=agreement, **signature_data)

        AgreementHistory.objects.create(agreement=agreement, action='CREATED')
        return agreement

    @transaction.atomic
    def update(self, instance, validated_data):
        scopes_data = validated_data.pop('scope_nodes', None)
        responsibilities_data = validated_data.pop('responsibility_nodes', None)
        timeline_data = validated_data.pop('timeline_phases', None)
        payment_data = validated_data.pop('payment', None)
        annexure_data = validated_data.pop('annexure', None)
        terms_data = validated_data.pop('terms_links', None)
        custom_data = validated_data.pop('custom_sections', None)
        signature_data = validated_data.pop('signature', None)
        

        # ✅ Fix 6: support password update
        password = validated_data.pop("client_password", None)

        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        if password:
            instance.client_access_password = make_password(password)
            instance.save(update_fields=["client_access_password"])

        # Update scopes
        if scopes_data is not None:
            existing_roots = {root.id: root for root in instance.scope_nodes.filter(parent__isnull=True)}
            new_ids = set()
            for scope_data in scopes_data:
                scope_id = scope_data.get('id')
                if scope_id and scope_id in existing_roots:
                    root = existing_roots[scope_id]
                    serializer = ScopeNodeWriteSerializer(root, data=scope_data, partial=True)
                    serializer.is_valid(raise_exception=True)
                    serializer.save()
                    new_ids.add(scope_id)
                else:
                    scope_data.pop('id', None)
                    serializer = ScopeNodeWriteSerializer(data=scope_data)
                    serializer.is_valid(raise_exception=True)
                    serializer.save(agreement=instance)
                    new_ids.add(serializer.instance.id)
            to_delete = set(existing_roots.keys()) - new_ids
            if to_delete:
                ScopeNode.objects.filter(id__in=to_delete).delete()

        if responsibilities_data is not None:
            existing_roots = {root.id: root for root in instance.responsibility_nodes.filter(parent__isnull=True)}
            new_ids = set()
            for resp_data in responsibilities_data:
                resp_id = resp_data.get('id')
                if resp_id and resp_id in existing_roots:
                    root = existing_roots[resp_id]
                    serializer = ResponsibilityNodeWriteSerializer(root, data=resp_data, partial=True)
                    serializer.is_valid(raise_exception=True)
                    serializer.save()
                    new_ids.add(resp_id)
                else:
                    resp_data.pop('id', None)
                    serializer = ResponsibilityNodeWriteSerializer(data=resp_data)
                    serializer.is_valid(raise_exception=True)
                    serializer.save(agreement=instance)
                    new_ids.add(serializer.instance.id)
            to_delete = set(existing_roots.keys()) - new_ids
            if to_delete:
                ResponsibilityNode.objects.filter(id__in=to_delete).delete()

        if timeline_data is not None:
            instance.timeline_phases.all().delete()
            for phase_data in timeline_data:
                TimelinePhase.objects.create(agreement=instance, **phase_data)

        if payment_data is not None:
            if hasattr(instance, 'payment'):
                payment_serializer = PaymentSectionSerializer(instance.payment, data=payment_data, partial=True)
                payment_serializer.is_valid(raise_exception=True)
                payment_serializer.save()
            else:
                payment_serializer = PaymentSectionSerializer(data=payment_data)
                payment_serializer.is_valid(raise_exception=True)
                payment_serializer.save(agreement=instance)

        if annexure_data is not None:
            if hasattr(instance, 'annexure'):
                annexure_serializer = AnnexureSerializer(instance.annexure, data=annexure_data, partial=True)
                annexure_serializer.is_valid(raise_exception=True)
                annexure_serializer.save()
            else:
                Annexure.objects.create(agreement=instance, **annexure_data)

        if terms_data is not None:
            instance.terms_links.all().delete()
            for term_data in terms_data:
                AgreementTerms.objects.create(agreement=instance, **term_data)

        if custom_data is not None:
            instance.custom_sections.all().delete()
            for cs_data in custom_data:
                CustomSection.objects.create(agreement=instance, **cs_data)

        if signature_data is not None:
            if hasattr(instance, 'signature'):
                sig_serializer = SignatureSerializer(instance.signature, data=signature_data, partial=True)
                sig_serializer.is_valid(raise_exception=True)
                sig_serializer.save()
            else:
                Signature.objects.create(agreement=instance, **signature_data)

        AgreementHistory.objects.create(agreement=instance, action='EDITED')
        return instance

class AgreementReadSerializer(serializers.ModelSerializer):
    # Nested read serializers
    scope_nodes = serializers.SerializerMethodField()
    responsibility_nodes = serializers.SerializerMethodField()
    timeline_phases = TimelinePhaseSerializer(many=True, read_only=True)
    payment = PaymentSectionSerializer(read_only=True)
    annexure = AnnexureSerializer(read_only=True)
    terms_links = AgreementTermsSerializer(many=True, read_only=True)
    custom_sections = CustomSectionSerializer(many=True, read_only=True)
    attachments = AgreementAttachmentSerializer(many=True, read_only=True)
    signature = SignatureSerializer(read_only=True)
    history = AgreementHistorySerializer(many=True, read_only=True)

    # Computed fields
    total_duration = serializers.SerializerMethodField()
    total_scopes = serializers.SerializerMethodField()
    total_responsibilities = serializers.SerializerMethodField()
    total_milestones = serializers.SerializerMethodField()

    # Display fields
    agency_name = serializers.CharField(
        source="agency.company_name",
        read_only=True
    )
    principal_name = serializers.CharField(
        source="principal.company_name",
        read_only=True
    )

    class Meta:
        model = Agreement
        fields = [
            "id",
            "agreement_no",
            "title",
            "agreement_date",
            "referred_by",
            "agency",
            "principal",
            "purpose",
            "status",
            "version_number",
            "is_latest",
            "parent_agreement",
            "template_used",
            "created_at",
            "updated_at",

            # Nested data
            "scope_nodes",
            "responsibility_nodes",
            "timeline_phases",
            "payment",
            "annexure",
            "terms_links",
            "custom_sections",
            "attachments",
            "signature",
            "history",

            # Display fields
            "agency_name",
            "principal_name",

            # Calculated fields
            "total_duration",
            "total_scopes",
            "total_responsibilities",
            "total_milestones",

            # Client fields
            "client_sign_token",
            "client_signed",
            "client_viewed",
            "client_signed_at",
        ]

        read_only_fields = fields

    def get_total_duration(self, obj):
        return obj.total_duration

    def get_total_scopes(self, obj):
        return obj.scope_nodes.filter(parent__isnull=True).count()

    def get_total_responsibilities(self, obj):
        return obj.responsibility_nodes.filter(parent__isnull=True).count()

    def get_total_milestones(self, obj):
        if hasattr(obj, "payment"):
            return obj.payment.milestones.count()
        return 0
    
    def get_scope_nodes(self, obj):
        roots = obj.scope_nodes.filter(
            parent__isnull=True
        ).order_by("order")

        return ScopeNodeReadSerializer(
            roots,
            many=True
        ).data


    def get_responsibility_nodes(self, obj):
        roots = obj.responsibility_nodes.filter(
            parent__isnull=True
        ).order_by("order")

        return ResponsibilityNodeReadSerializer(
            roots,
            many=True
        ).data
# ---------- Summary Serializer ----------
class AgreementSummarySerializer(serializers.Serializer):
    total_scopes = serializers.IntegerField()
    total_responsibilities = serializers.IntegerField()
    total_timeline_phases = serializers.IntegerField()
    total_duration = serializers.IntegerField()
    total_amount = serializers.DecimalField(max_digits=12, decimal_places=2)
    payment_milestones_count = serializers.IntegerField()
    status = serializers.CharField()


# ---------- Terms (standalone) ----------
class TermsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Terms
        fields = '__all__'


# ✅ Fix 7: New serializer for client login
class ClientAgreementLoginSerializer(serializers.Serializer):
    agreement_no = serializers.CharField()
    password = serializers.CharField()


# ✅ Fix 8: New serializer for client signing
class ClientAgreementSignSerializer(serializers.Serializer):
    signature = Base64ImageField()
    client_name = serializers.CharField()