from django.db import models, transaction
from django.db.models import Max
from datetime import datetime

def generate_agreement_number():
    """Generate unique agreement number with select_for_update."""
    from .models import Agreement
    year = datetime.now().year
    prefix = f"AGR-{year}-"
    with transaction.atomic():
        last = Agreement.objects.select_for_update().filter(agreement_no__startswith=prefix).order_by('agreement_no').last()
        if last:
            parts = last.agreement_no.split('-')
            last_num = int(parts[-1]) if parts[-1].isdigit() else 0
            new_num = last_num + 1
        else:
            new_num = 1
        return f"{prefix}{new_num:04d}"

def validate_timeline_overlap(phases):
    """Return True if no overlap."""
    sorted_phases = sorted(phases, key=lambda x: x['start_day'])
    for i in range(len(sorted_phases)-1):
        if sorted_phases[i]['end_day'] >= sorted_phases[i+1]['start_day']:
            return False
    return True

def clone_agreement(original, new_version=False, new_title=None):
    """
    Deep clone an agreement safely without mutating the original instance.
    Returns the new agreement instance.
    """
    from .models import (
        Agreement, ScopeNode, ResponsibilityNode, TimelinePhase,
        PaymentSection, PaymentMilestone, Annexure, AgreementTerms,
        CustomSection, Signature, AgreementAttachment
    )
    with transaction.atomic():
        # 1. Copy agreement fields
        old_pk = original.pk
        original_dict = {
            'title': new_title or original.title,
            'agreement_date': original.agreement_date,
            'referred_by': original.referred_by,
            'agency': original.agency,
            'principal': original.principal,
            'purpose': original.purpose,
            'status': 'DRAFT',
            'template_used': original.template_used,
        }
        if new_version:
            original_dict['version_number'] = original.version_number + 1
            original_dict['is_latest'] = True
            original_dict['parent_agreement'] = original
            original_dict['agreement_no'] = original.agreement_no  # same number
        else:
            original_dict['version_number'] = 1
            original_dict['is_latest'] = True
            original_dict['parent_agreement'] = None
            original_dict['agreement_no'] = generate_agreement_number()  # new number

        # Create new agreement from fresh dict, not from mutated instance
        new_agreement = Agreement.objects.create(**original_dict)
        new_id = new_agreement.pk

        # 2. Clone ScopeNodes (recursive)
        def clone_scope(node, new_parent=None):
            children = list(node.children.all())
            node.pk = None
            node.agreement_id = new_id
            node.parent = new_parent
            node.save()
            for child in children:
                clone_scope(child, node)
        for root in ScopeNode.objects.filter(agreement_id=old_pk, parent__isnull=True):
            clone_scope(root)

        # 3. Clone ResponsibilityNodes
        def clone_resp(node, new_parent=None):
            children = list(node.children.all())
            node.pk = None
            node.agreement_id = new_id
            node.parent = new_parent
            node.save()
            for child in children:
                clone_resp(child, node)
        for root in ResponsibilityNode.objects.filter(agreement_id=old_pk, parent__isnull=True):
            clone_resp(root)

        # 4. Clone TimelinePhases
        for phase in TimelinePhase.objects.filter(agreement_id=old_pk):
            phase.pk = None
            phase.agreement_id = new_id
            phase.save()

        # 5. Clone PaymentSection + Milestones
        try:
            old_payment = PaymentSection.objects.get(agreement_id=old_pk)
        except PaymentSection.DoesNotExist:
            old_payment = None
        if old_payment:
            milestones = list(old_payment.milestones.all())
            old_payment.pk = None
            old_payment.agreement_id = new_id
            old_payment.finalized = False
            old_payment.save()
            new_payment = old_payment
            for m in milestones:
                m.pk = None
                m.payment_id = new_payment.pk
                m.save()

        # 6. Clone Annexure
        try:
            old_annexure = Annexure.objects.get(agreement_id=old_pk)
        except Annexure.DoesNotExist:
            old_annexure = None
        if old_annexure:
            old_annexure.pk = None
            old_annexure.agreement_id = new_id
            old_annexure.save()

        # 7. Clone AgreementTerms
        for at in AgreementTerms.objects.filter(agreement_id=old_pk):
            at.pk = None
            at.agreement_id = new_id
            at.save()

        # 8. Clone CustomSections
        for cs in CustomSection.objects.filter(agreement_id=old_pk):
            cs.pk = None
            cs.agreement_id = new_id
            cs.save()

        # 9. Clone Attachments (files not copied, only references?)
        # We'll skip file copying; just create new attachment records with same file? (optional)
        # For safety, we won't duplicate files.
        # for att in AgreementAttachment.objects.filter(agreement_id=old_pk):
        #     att.pk = None
        #     att.agreement_id = new_id
        #     att.save()

        # 10. Clone Signature
        try:
            old_sig = Signature.objects.get(agreement_id=old_pk)
        except Signature.DoesNotExist:
            old_sig = None
        if old_sig:
            old_sig.pk = None
            old_sig.agreement_id = new_id
            old_sig.signed_date = None
            old_sig.ip_address = None
            old_sig.signed_time = None
            old_sig.save()

        # 11. Log creation
        from .models import AgreementHistory
        AgreementHistory.objects.create(
            agreement=new_agreement,
            action='CREATED',
            user=None,  # can be set later
            details={'cloned_from': old_pk}
        )

        return new_agreement