from django.contrib.auth.models import User
from django.utils.text import slugify
from django.utils.translation import gettext as _

import graphene
from graphene_django import DjangoObjectType
from templated_email import send_templated_mail

from aleksis.apps.postbuero.models import MailAddress
from aleksis.apps.postbuero.schema import MailAddressInputType
from aleksis.core.models import Activity, Person
from aleksis.core.schema.base import PermissionsTypeMixin
from aleksis.core.schema.person import PersonInputType
from aleksis.core.schema.user import UserInputType
from aleksis.core.util.core_helpers import get_site_preferences

from ..models import Event, EventRegistration, Terms, Voucher


class EventRegistrationType(PermissionsTypeMixin, DjangoObjectType):
    class Meta:
        model = EventRegistration


class PaymentInputType(graphene.InputObjectType):
    payment_method = graphene.String(required=True)
    voucher_code = graphene.String(required=False)
    amount = graphene.Int(required=True)


class EventRegistrationInputType(graphene.InputObjectType):
    email = graphene.Field(MailAddressInputType, required=False)
    person = graphene.Field(PersonInputType, required=False)
    user = graphene.Field(UserInputType, required=False)
    school = graphene.String(required=False)
    school_place = graphene.String(required=False)
    school_class = graphene.String(required=False)
    payment = graphene.Field(PaymentInputType, required=False)
    medical_information = graphene.String(required=False)
    comment = graphene.String(required=False)
    additional_fields = graphene.JSONString(required=False)
    terms = graphene.JSONString(required=False)
    retraction_consent = graphene.Boolean(required=True)


class SendEventRegistrationMutation(graphene.Mutation):
    class Arguments:
        event = graphene.ID(required=True)
        event_registration = EventRegistrationInputType(required=True)

    ok = graphene.Boolean()

    def mutate(self, info, event: graphene.ID, event_registration: EventRegistrationInputType, **kwargs):
        event = Event.objects.get(pk=event)

        print(event_registration)

        # Create user
        if event_registration is not None:
            user = User.objects.create(
                username=event_registration["user"]["username"],
                email=event_registration["user"]["email"],
            )
            user.set_password(event_registration["user"]["password"])
            user.save()
        else:
            user = self.request.user

        person, created = Person.objects.get_or_create(
            user=user,
            defaults={
                "email": event_registration["person"]["email"],
                "first_name": event_registration["person"]["first_name"],
                "last_name": event_registration["person"]["last_name"],
            },
        )

        # Store contact information in database
        for field_name in ["date_of_birth", "sex", "address", "mobile_number"]:
            if event_registration["person"] is not None and event_registration["person"][field_name] != "":
                if field_name == "address":
                    for addr_field in ["street", "housenumber", "postal_code", "place"]:
                        setattr(person, addr_field, event_registration["person"]["address"][addr_field])
                else:
                    setattr(person, field_name, event_registration["person"][field_name])
        person.save()

        if event_registration["person"] is not None:
            for guardian_data in event_registration["person"]["guardians"]:
                guardian, created = Person.objects.get_or_create(
                    defaults={
                        "mobile_number": guardian_data["mobile_number"],
                    },
                    first_name=guardian_data["first_name"],
                    last_name=guardian_data["last_name"],
                    email=guardian_data["email"],
                )

                person.guardians.add(guardian)
            person.save()

        if event_registration["email"] is not None:
            _mail_address = MailAddress.objects.create(
                local_part=event_registration["email"]["local_part"],
                domain=event_registration["email"]["domain"],
            )
            _mail_address.person = person
            _mail_address.save()

        school_details = {}
        for field_name in ["school", "school_class", "school_place"]:
            if event_registration[field_name] is not None:
                school_details[field_name] = event_registration[field_name]

        registration = EventRegistration.objects.create(
            managed_by_app_label="",
            event=event,
            person=person,
            medical_information=event_registration["medical_information"],
            **school_details,
        )
        for field in event.additional_fields.all():
            registration.extended_data[
                slugify(field.title).replace("-", "_")
            ] = event_registration["additional_fields"][field.title]

        for field in event_registration["terms"]:
            if not field.startswith("consent_"):
                continue
            pk = int(field.split("_")[1])
            term = Terms.objects.get(id=pk)
            registration.accepted_terms.add(term)

        registration.cost = event.cost

        if event.max_cost is not None and event.max_cost > 0:
            amount = event_registration["payment"].amount

            if amount < event.cost:
                voucher_amount = event.cost - amount
                discount = voucher_amount / event.cost
                Voucher.objects.create(
                    person=person,
                    event=event,
                    used=True,
                    discount=discount,
                )
            elif amount > event.cost:
                registration.donation = amount - event.cost

            # TODO Implement existing voucher handling

            invoice = registration.get_invoice()
            invoice.variant = event_registration["payment"]["payment_method"]
            invoice.save()

        registration.save()

        context = {}
        context["registration"] = registration

#        send_templated_mail(
#            template_name="event_registered",
#            from_email=get_site_preferences()["mail__address"],
#            recipient_list=[get_site_preferences()["paweljong__event_notification_recipient"]],
#            headers={
#                "reply_to": [
#                    person.email,
#                    person.guardians.first().email,
#                ],
#                "X-Zammad-Customer-Email": person.email,
#            },
#            context=context,
#        )

        _act = Activity(
            title=_("You registered for an event"),
            description=_("You registered for the event %s" % event.display_name),
            app="Paweljong",
            user=person,
        )

        if event_registration["retraction_consent"]:
            return SendEventRegistrationMutation(ok=True)

        return SendEventRegistrationMutation(ok=False)