# Give this app a custom verbose name to avoid confusion
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _


class FinancialAppConfig(AppConfig):
    name = 'danceschool.financial'
    verbose_name = _('Financial Functions')

    def ready(self):
        from django.core.exceptions import ValidationError

        from danceschool.core.models import Event, SubstituteTeacher, Invoice, InvoiceItem
        from danceschool.core.constants import getConstant

        # Add some properties to Invoices that are useful for the check-in process.
        # to ensure that the financials are being recorded correctly.

        @property
        def revenueReportedGross(self):
            if hasattr(self, 'revenueitem') and self.revenueitem:
                return self.revenueitem.total
            return 0
        InvoiceItem.add_to_class('revenueReportedGross', revenueReportedGross)

        @property
        def revenueReported(self):
            if hasattr(self, 'revenueitem') and self.revenueitem:
                return self.revenueitem.netRevenue
            return 0
        InvoiceItem.add_to_class('revenueReported', revenueReported)

        @property
        def feesReported(self):
            if hasattr(self, 'revenueitem') and self.revenueitem:
                return self.revenueitem.fees
            return 0
        InvoiceItem.add_to_class('feesReported', feesReported)

        @property
        def taxesReported(self):
            if hasattr(self, 'revenueitem') and self.revenueitem:
                return self.revenueitem.taxes
            return 0
        InvoiceItem.add_to_class('taxesReported', taxesReported)

        @property
        def revenueReceivedGross(self):
            if hasattr(self, 'revenueitem') and self.revenueitem and self.revenueitem.received:
                return self.revenueitem.total
            return 0
        InvoiceItem.add_to_class('revenueReceivedGross', revenueReceivedGross)

        @property
        def revenueReceived(self):
            if hasattr(self, 'revenueitem') and self.revenueitem and self.revenueitem.received:
                return self.revenueitem.netRevenue
            return 0
        InvoiceItem.add_to_class('revenueReceived', revenueReceived)

        @property
        def revenueMismatch(self):
            comparison = self.revenueReported + \
                self.revenueRefundsReported + self.feesReported
            if not self.invoice.buyerPaysSalesTax:
                comparison += self.taxesReported

            return round(self.total, 2) != round(comparison, 2)
        InvoiceItem.add_to_class('revenueMismatch', revenueMismatch)

        @property
        def invoiceRevenueMismatch(self):
            for x in self.invoiceitem_set.all():
                if x.revenueMismatch:
                    return True

            return False
        Invoice.add_to_class('revenueMismatch', invoiceRevenueMismatch)

        @property
        def revenueNotYetReceived(self):
            return self.revenueReceived != self.revenueReported
        InvoiceItem.add_to_class('revenueNotYetReceived', revenueNotYetReceived)

        @property
        def invoiceRevenueNotYetReceived(self):
            for x in self.invoiceitem_set.all():
                if x.revenueNotYetReceived:
                    return True

            return False
        Invoice.add_to_class('revenueNotYetReceived', invoiceRevenueNotYetReceived)

        @property
        def revenueRefundsReported(self):
            if hasattr(self, 'revenueitem') and self.revenueitem:
                return -1 * self.revenueitem.adjustments
            return 0
        InvoiceItem.add_to_class('revenueRefundsReported', revenueRefundsReported)

        @property
        def invoiceRevenueRefundsReported(self):
            return sum([x.revenueRefundsReported for x in self.invoiceitem_set.all()])
        Invoice.add_to_class('revenueRefundsReported', invoiceRevenueRefundsReported)

        # Add a property and a validator to check for and validate that teachers have not
        # already been paid when accepting SubstituteTeacher submissions.
        @property
        def paidOut(self):
            ''' Add a property to Event indicating whether hourly expenses have been paid out. '''
            return (
                True in self.expenseitem_set.filter(
                    expenseRule__staffmemberwageinfo__isnull=False
                ).values_list('paid', flat=True)
            )
        Event.add_to_class('paidOut', paidOut)

        def validate_EnsureNotPaidOut(event_pk):
            '''
            Add a validator to SubstituteTeacher submissions checking if the
            series has been paid out.
            '''
            event = Event.objects.get(pk=event_pk)
            if event.paidOut:
                raise ValidationError(_(
                    'Staff members for this series have already been paid.  ' +
                    'If you need to adjust hours worked, you will need to ' +
                    'request money from them directly.'
                ))

        for field in [f for f in SubstituteTeacher._meta.fields if f.name == 'event']:
            field.validators.append(validate_EnsureNotPaidOut)

        # This ensures that the receivers are loaded.
        from . import handlers
