"""
Signal handlers for automatic journal entry creation.

These signals ensure that all loan and expense transactions are automatically
recorded in the accounting system using double-entry bookkeeping.
"""

import logging
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.db import transaction

logger = logging.getLogger(__name__)


@receiver(post_save, sender='loans.Loan')
def create_loan_disbursement_journal_entry(sender, instance, created, **kwargs):
    """
    Automatically create journal entry when a loan is disbursed.
    
    Triggered when:
    - Loan status changes to 'active' (disbursed)
    - Loan has disbursement_date set
    
    Creates:
    - Disbursement journal entry (DR: Loan Portfolio, CR: Cash/Bank)
    """
    from accounting.services.integration_service import IntegrationService
    from accounting.models import JournalEntry
    
    # Only process if loan is active and has disbursement date
    if instance.status != 'active' or not instance.disbursement_date:
        return
    
    # Check if disbursement entry already exists to avoid duplicates
    existing_entry = JournalEntry.objects.filter(
        loan=instance,
        reference_number=f'LOAN-DISB-{instance.loan_number}'
    ).first()
    
    if existing_entry:
        logger.info(f'Disbursement journal entry already exists for loan {instance.loan_number}')
        return
    
    # Create the disbursement journal entry
    try:
        integration_service = IntegrationService()
        journal_entry = integration_service.create_loan_disbursement_entry(
            loan=instance,
            user=instance.approved_by or instance.loan_officer
        )
        logger.info(
            f'Created disbursement journal entry {journal_entry.reference_number} '
            f'for loan {instance.loan_number}'
        )
    except Exception as e:
        logger.error(
            f'Failed to create disbursement journal entry for loan {instance.loan_number}: {e}',
            exc_info=True
        )


@receiver(post_save, sender='loans.Repayment')
def create_repayment_journal_entry(sender, instance, created, **kwargs):
    """
    Automatically create journal entry when a loan repayment is recorded.
    
    Triggered when:
    - New Repayment record is created
    
    Creates:
    - Repayment journal entry (DR: Cash/Bank, CR: Loan Portfolio/Interest/Fees/Penalties)
    """
    from accounting.services.integration_service import IntegrationService
    from accounting.models import JournalEntry
    
    # Only process newly created repayments
    if not created:
        return
    
    # Check if repayment entry already exists to avoid duplicates
    existing_entry = JournalEntry.objects.filter(
        loan=instance.loan,
        reference_number=f'LOAN-REPAY-{instance.receipt_number}'
    ).first()
    
    if existing_entry:
        logger.info(f'Repayment journal entry already exists for receipt {instance.receipt_number}')
        return
    
    # Create the repayment journal entry
    try:
        integration_service = IntegrationService()
        journal_entry = integration_service.create_loan_repayment_entry(
            repayment=instance,
            user=instance.recorded_by or instance.loan.loan_officer
        )
        logger.info(
            f'Created repayment journal entry {journal_entry.reference_number} '
            f'for loan {instance.loan.loan_number}'
        )
    except Exception as e:
        logger.error(
            f'Failed to create repayment journal entry for receipt {instance.receipt_number}: {e}',
            exc_info=True
        )


@receiver(post_save, sender='expenses.Expense')
def create_expense_journal_entry(sender, instance, created, **kwargs):
    """
    Automatically create journal entry when an expense is approved.
    
    Triggered when:
    - Expense status changes to 'approved'
    
    Creates:
    - Expense journal entry (DR: Expense Account, CR: Payment Account)
    """
    from accounting.services.integration_service import IntegrationService
    from accounting.models import JournalEntry
    
    # Only process approved expenses
    if instance.status != 'approved':
        return
    
    # Check if expense entry already exists to avoid duplicates
    existing_entry = JournalEntry.objects.filter(
        expense=instance,
        reference_number=f'EXP-{instance.id}'
    ).first()
    
    if existing_entry:
        logger.info(f'Expense journal entry already exists for expense {instance.id}')
        return
    
    # Create the expense journal entry
    try:
        integration_service = IntegrationService()
        journal_entry = integration_service.create_expense_entry(
            expense=instance,
            user=instance.approved_by
        )
        logger.info(
            f'Created expense journal entry {journal_entry.reference_number} '
            f'for expense {instance.id}'
        )
    except Exception as e:
        logger.error(
            f'Failed to create expense journal entry for expense {instance.id}: {e}',
            exc_info=True
        )
