from django.views.generic import View
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import never_cache
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import (
    get_object_or_404,
    render,
)
from gbe.models import (
    Conference,
    UserMessage,
)
from gbe_logging import log_func
from gbe.functions import (
    validate_profile,
)
from gbe.email.functions import notify_reviewers_on_bid_change
from gbetext import (
    no_login_msg,
    fee_instructions,
    full_login_msg,
    payment_needed_msg,
    payment_details_error,
)
from gbe_utils.text import no_profile_msg
from gbe.ticketing_idd_interface import (
    get_payment_details,
    get_ticket_form,
    fee_paid,
)


class MakeBidView(View):
    form = None
    has_draft = True
    instructions = ''
    payment_form = None
    coordinated = False

    def groundwork(self, request, args, kwargs):
        self.owner = validate_profile(request, require=False)
        if not self.owner or not self.owner.complete:
            user_message = UserMessage.objects.get_or_create(
                view=self.__class__.__name__,
                code="PROFILE_INCOMPLETE",
                defaults={
                    'summary': "Profile Incomplete",
                    'description': no_profile_msg})
            messages.warning(request, user_message[0].description)
            return '%s?next=%s' % (
                reverse('profile_update', urlconf='gbe.urls'),
                reverse('%s_create' % self.bid_type.lower(),
                        urlconf='gbe.urls'))

        self.bid_object = None
        if "bid_id" in kwargs:
            bid_id = kwargs.get("bid_id")
            self.bid_object = get_object_or_404(self.bid_class, pk=bid_id)
            self.conference = self.bid_object.b_conference
        else:
            self.conference = Conference.objects.filter(
                    accepting_bids=True).first()

    def make_post_forms(self, request, the_form):
        if self.bid_object:
            self.form = the_form(
                request.POST,
                instance=self.bid_object,
                initial=self.get_initial(),
                prefix=self.prefix)
        else:
            self.form = the_form(
                request.POST,
                initial=self.get_initial(),
                prefix=self.prefix)
        self.set_up_form()

    def set_up_post(self, request):
        the_form = None
        if 'submit' in list(request.POST.keys()) or not self.has_draft:
            the_form = self.submit_form
            user_message = UserMessage.objects.get_or_create(
                view=self.__class__.__name__,
                code="SUBMIT_SUCCESS",
                defaults={
                    'summary': "%s Submit Success" % self.bid_type,
                    'description': self.submit_msg})
        else:
            the_form = self.draft_form
            user_message = UserMessage.objects.get_or_create(
                view=self.__class__.__name__,
                code="DRAFT_SUCCESS",
                defaults={
                    'summary': "%s Save Draft Success" % self.bid_type,
                    'description': self.draft_msg})
        self.make_post_forms(request, the_form)
        return user_message

    def make_context(self, request):
        paid = fee_paid(
            self.bid_type,
            self.owner.user_object.username,
            self.conference)
        instructions = UserMessage.objects.get_or_create(
            view=self.__class__.__name__,
            code="BID_INSTRUCTIONS",
            defaults={
                'summary': "%s Bid Instructions" % self.bid_type,
                'description': self.instructions})
        context = {
            'conference': self.conference,
            'forms': [self.form],
            'page_title': self.page_title,
            'view_title': self.view_title,
            'draft_fields': self.draft_fields,
            'submit_fields': self.submit_fields,
            'fee_paid': paid,
            'view_header_text': instructions[0].description,
            }
        if not paid and not self.coordinated:
            user_message = UserMessage.objects.get_or_create(
                view=self.__class__.__name__,
                code="FEE_MESSAGE",
                defaults={
                    'summary': "%s Pre-submit Message" % self.bid_type,
                    'description': fee_instructions})

            messages.info(
                request,
                user_message[0].description)
            if self.payment_form:
                context['forms'] += [self.payment_form]
            else:
                context['forms'] += [get_ticket_form(self.bid_class.__name__,
                                                     self.conference)]
        return context

    def get_create_form(self, request):
        if self.bid_object:
            self.form = self.submit_form(
                prefix=self.prefix,
                instance=self.bid_object,
                initial=self.get_initial())
        else:
            self.form = self.submit_form(
                prefix=self.prefix,
                initial=self.get_initial())
        self.set_up_form()

        return render(
            request,
            'gbe/bid.tmpl',
            self.make_context(request)
        )

    def check_validity(self, request):
        return self.form.is_valid()

    def set_up_form(self):
        pass

    def get_invalid_response(self, request):
        self.set_up_form()
        context = self.make_context(request)
        return render(
            request,
            'gbe/bid.tmpl',
            context)

    def submit_bid(self, request):
        self.bid_object.submitted = True
        self.bid_object.save()
        notify_reviewers_on_bid_change(
            self.owner,
            self.bid_object,
            self.bid_type,
            "Submission",
            self.conference,
            '%s Reviewers' % self.bid_type,
            reverse('%s_review' % self.bid_type.lower(),
                    urlconf='gbe.urls'))

    @never_cache
    @log_func
    def get(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            follow_on = '?next=%s' % reverse(
                '%s_create' % self.bid_type.lower(),
                urlconf='gbe.urls')
            user_message = UserMessage.objects.get_or_create(
                view=self.__class__.__name__,
                code="USER_NOT_LOGGED_IN",
                defaults={
                    'summary': "Need Login - %s Bid",
                    'description': no_login_msg})
            full_msg = full_login_msg % (
                user_message[0].description,
                reverse('login', urlconf='gbe.urls') + follow_on)
            messages.warning(request, full_msg)

            return HttpResponseRedirect(
                reverse('register', urlconf='gbe.urls') + follow_on)

        redirect = self.groundwork(request, args, kwargs)
        if redirect:
            return HttpResponseRedirect(redirect)

        return self.get_create_form(request)

    @never_cache
    @log_func
    @method_decorator(login_required)
    def post(self, request, *args, **kwargs):
        cart_items = []
        paypal_button = None
        total = None
        redirect = None
        redirect = self.groundwork(request, args, kwargs)
        if redirect:
            return HttpResponseRedirect(redirect)

        user_message = self.set_up_post(request)

        # check bid validity
        if not self.check_validity(request):
            return self.get_invalid_response(request)

        if not self.coordinated and not fee_paid(
                self.bid_type,
                self.owner.user_object.username,
                self.conference) and "draft" not in list(request.POST.keys()):
            self.payment_form = get_ticket_form(self.bid_class.__name__,
                                                self.conference,
                                                request.POST)
            if not self.payment_form.is_valid():
                error_message = UserMessage.objects.get_or_create(
                        view=self.__class__.__name__,
                        code="PAYMENT_CHOICE_INVALID",
                        defaults={
                            'summary': "User Made Invalid Ticket Choice",
                            'description': payment_details_error})
                messages.error(request, error_message[0].description)
                return self.get_invalid_response(request)

        # save bid
        if not self.bid_object:
            self.bid_object = self.form.save(commit=False)

        self.set_valid_form(request)

        # if this isn't a draft, move forward through process, setting up
        # payment review if payment is needed
        if "submit" in list(request.POST.keys()):
            if self.payment_form:
                cart_items, paypal_button, total = get_payment_details(
                    request,
                    self.payment_form,
                    self.bid_type,
                    self.bid_object.pk,
                    self.owner.user_object.pk)

                dynamic_message = UserMessage.objects.get_or_create(
                    view=self.__class__.__name__,
                    code="NOT_PAID_INSTRUCTIONS",
                    defaults={
                        'summary': "%s Not Paid" % self.bid_type,
                        'description': payment_needed_msg})
                page_title = '%s Payment' % self.bid_type
                return render(
                    request,
                    'gbe/confirm_pay.tmpl',
                    {'dynamic_message': dynamic_message[0].description,
                     'page_title': page_title,
                     'cart_items': cart_items,
                     'total': total,
                     'paypal_button': paypal_button})
            else:
                redirect = self.submit_bid(request)

        messages.success(request, user_message[0].description)
        return HttpResponseRedirect(
            redirect or reverse('home', urlconf='gbe.urls'))

    def dispatch(self, *args, **kwargs):
        return super(MakeBidView, self).dispatch(*args, **kwargs)

[(215, 'django.utils.decorators.method_decorator', 'method_decorator', False, 'from django.utils.decorators import method_decorator\n'), (44, 'gbe.functions.validate_profile', 'validate_profile', False, 'from gbe.functions import validate_profile\n'), (103, 'gbe.ticketing_idd_interface.fee_paid', 'fee_paid', False, 'from gbe.ticketing_idd_interface import get_payment_details, get_ticket_form, fee_paid\n'), (107, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (168, 'django.shortcuts.render', 'render', False, 'from django.shortcuts import get_object_or_404, render\n'), (283, 'django.contrib.messages.success', 'messages.success', False, 'from django.contrib import messages\n'), (46, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (52, 'django.contrib.messages.warning', 'messages.warning', False, 'from django.contrib import messages\n'), (61, 'django.shortcuts.get_object_or_404', 'get_object_or_404', False, 'from django.shortcuts import get_object_or_404, render\n'), (85, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (93, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (124, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (131, 'django.contrib.messages.info', 'messages.info', False, 'from django.contrib import messages\n'), (193, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (202, 'django.contrib.messages.warning', 'messages.warning', False, 'from django.contrib import messages\n'), (209, 'django.http.HttpResponseRedirect', 'HttpResponseRedirect', False, 'from django.http import HttpResponseRedirect\n'), (223, 'django.http.HttpResponseRedirect', 'HttpResponseRedirect', False, 'from django.http import HttpResponseRedirect\n'), (235, 'gbe.ticketing_idd_interface.get_ticket_form', 'get_ticket_form', False, 'from gbe.ticketing_idd_interface import get_payment_details, get_ticket_form, fee_paid\n'), (231, 'gbe.ticketing_idd_interface.fee_paid', 'fee_paid', False, 'from gbe.ticketing_idd_interface import get_payment_details, get_ticket_form, fee_paid\n'), (239, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (245, 'django.contrib.messages.error', 'messages.error', False, 'from django.contrib import messages\n'), (258, 'gbe.ticketing_idd_interface.get_payment_details', 'get_payment_details', False, 'from gbe.ticketing_idd_interface import get_payment_details, get_ticket_form, fee_paid\n'), (265, 'gbe.models.UserMessage.objects.get_or_create', 'UserMessage.objects.get_or_create', False, 'from gbe.models import Conference, UserMessage\n'), (272, 'django.shortcuts.render', 'render', False, 'from django.shortcuts import get_object_or_404, render\n'), (285, 'django.urls.reverse', 'reverse', False, 'from django.urls import reverse\n'), (54, 'django.urls.reverse', 'reverse', False, 'from django.urls import reverse\n'), (64, 'gbe.models.Conference.objects.filter', 'Conference.objects.filter', False, 'from gbe.models import Conference, UserMessage\n'), (137, 'gbe.ticketing_idd_interface.get_ticket_form', 'get_ticket_form', False, 'from gbe.ticketing_idd_interface import get_payment_details, get_ticket_form, fee_paid\n'), (205, 'django.urls.reverse', 'reverse', False, 'from django.urls import reverse\n'), (201, 'django.urls.reverse', 'reverse', False, 'from django.urls import reverse\n')]