from datetime import date

import factory
from psycopg.types.range import DateRange
from wbcore.contrib.directory.factories import EmailContactFactory, EntryFactory

from wbaccounting.models import EntryAccountingInformation, Vat, VatRate


class VatFactory(factory.django.DjangoModelFactory):
    name = "Default VAT"
    primary = True

    class Meta:
        model = Vat
        django_get_or_create = ("primary",)

    @factory.post_generation
    def initiate_rate(self, create, extracted, **kwargs):
        if not create:
            return
        if not self.rates.exists():
            VatRate.objects.create(vat=self, timespan=DateRange(date(2010, 1, 1), None), rate=0.08)


class EntryAccountingInformationFactory(factory.django.DjangoModelFactory):
    class Meta:  # type: ignore
        model = EntryAccountingInformation
        skip_postgeneration_save = True
        django_get_or_create = ("entry",)

    entry = factory.SubFactory("wbcore.contrib.directory.factories.EntryFactory")
    tax_id = factory.Faker("text", max_nb_chars=64)
    vat = factory.SubFactory(VatFactory)
    send_mail = factory.Faker("pybool")
    counterparty_is_private = False

    email_body = factory.Faker("paragraph")

    @factory.post_generation
    def post(self, create, extracted, **kwargs):
        if isinstance(self, EntryAccountingInformationFactory) and not create:
            self.email_to.add(EmailContactFactory.create())
            self.email_cc_add(EmailContactFactory.create())
            self.email_bcc.add(EmailContactFactory.create())

        if isinstance(self, dict):
            self["email_to"] = [EmailContactFactory.create().id]
            self["email_cc"] = [EmailContactFactory.create().id]
            self["email_bcc"] = [EmailContactFactory.create().id]

    @factory.post_generation
    def exempt_users(self, create, extracted, **kwargs):
        if not create:
            return

        if extracted:
            for user in extracted:
                self.exempt_users.add(user)

    default_currency = factory.SubFactory("wbcore.contrib.currency.factories.CurrencyFactory")


class EntryAccountingFactory(EntryFactory):
    @factory.post_generation
    def entry_accounting_information(self, create, extracted, **kwargs):
        if not create:
            return
        EntryAccountingInformationFactory.create(entry=self)
