from django.conf import settings
from django.shortcuts import render
from .models import User
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions
from django.http import Http404, FileResponse
from password_reset.views import Recover, Reset

from .serializers import UserSerializer
from .forms import CaptchaPasswordRecoveryForm, PasswordChangeForm, \
    ProfileConfigureForm, RecoveryPasswordResetForm, ConfirmAddressForm
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import PasswordChangeView \
    as BasePasswordChangeView
from django.contrib.auth.views import PasswordChangeDoneView \
    as BasePasswordChangeDoneView
from django.contrib import messages
from django.urls import reverse_lazy
from django.views.generic.edit import UpdateView, FormView
from limitmonitor.common import delete_account, parse_order, OrderParseError, \
    active_subscription
from limitmonitor.subscription import SubscriptionManager
from purist.models import AccountType


class UserDetail(APIView):
    """Retrieve a User instance
    """
    permission_classes = (permissions.IsAuthenticated,)

    def get_object(self, user):
        try:
            return User.objects.get(username=user.username)
        except User.DoesNotExists:
            raise Http404

    def get(self, request, format=None):
        user = self.get_object(request.user)
        serializer = UserSerializer(user)
        return Response(serializer.data)


class Recovery(Recover):
    form_class = CaptchaPasswordRecoveryForm
    search_fields = ['username']


class RecoveryPasswordReset(Reset):
    form_class = RecoveryPasswordResetForm


class PasswordChangeDone(BasePasswordChangeDoneView):
    template_name = 'purist/change_password_done.html'

    def get_context_data(self, **kwargs):
        context = super(PasswordChangeDone, self).get_context_data(**kwargs)
        context['username'] = self.request.user.get_username()
        context['site_title'] = settings.SITE_TITLE
        context['site_provider'] = settings.SITE_PROVIDER
        if self.extra_context is not None:
            context.update(self.extra_context)
        return context


class PasswordChange(BasePasswordChangeView):
    template_name = 'purist/change_password.html'
    form_class = PasswordChangeForm
    success_url = reverse_lazy('password_change_done')

    def get_context_data(self, **kwargs):
        context = super(PasswordChange, self).get_context_data(**kwargs)
        context['username'] = self.request.user.get_username()
        context['site_title'] = settings.SITE_TITLE
        context['site_provider'] = settings.SITE_PROVIDER
        if self.extra_context is not None:
            context.update(self.extra_context)
        return context


class ProfileConfigureView(LoginRequiredMixin, UpdateView):
    template_name = 'purist/profile_configure.html'
    form_class = ProfileConfigureForm
    success_url = reverse_lazy('profile')

    def get_form(self):
        f = super().get_form()
        f.user = self.request.user
        return f

    def get_object(self, queryset=None):
        return self.request.user

    def get_context_data(self, **kwargs):
        context = super(ProfileConfigureView, self).get_context_data(**kwargs)
        context['username'] = self.request.user.get_username()
        context['site_title'] = settings.SITE_TITLE
        context['site_provider'] = settings.SITE_PROVIDER
        return context

    def get_initial(self):
        # Prepopulate form fields with values from User Model and
        # WooCommerce
        return {"email": self.object.email,
                "billing_email": self.object.get_woocommerce_billing_email()}

    def form_valid(self, form):
        # If the user is an invitee and has no active invitee
        # subscription we create a new one.
        if self.request.user.account_type == AccountType.INVITED:
            sub = active_subscription(self.request.user)
            if sub is None:
                # create new invitee subs
                SubscriptionManager.create_invitee_subscription(
                    self.request.user)

        return super(ProfileConfigureView, self).form_valid(form)


class DeleteAccountView(LoginRequiredMixin, FormView):

    form_class = ConfirmAddressForm
    template_name = 'purist/account_confirm_delete.html'
    success_url = reverse_lazy('auth_logout')

    # Override get_form() to pass user object to the form
    def get_form(self, *args, **kwargs):
        form = super(DeleteAccountView, self).get_form(*args, **kwargs)
        form.user = self.request.user
        return form

    def form_valid(self, form):
        delete_account(self.request.user)
        messages.add_message(self.request, messages.INFO,
                             'Your account has been permanently deleted.')
        return super(DeleteAccountView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(DeleteAccountView, self).get_context_data(**kwargs)
        orders = self.request.user.get_woocommerce_orders()
        context['shoplink'] = settings.WOO_URL
        context['paid'] = (
            self.request.user.account_type == AccountType.COMPLETE
            or self.request.user.account_type == AccountType.GROUP
        )
        if orders is None:
            context['can_delete'] = True
        else:
            for order in orders:
                try:
                    parsed_o = parse_order(order)
                except OrderParseError:
                    context['can_delete'] = False
                    break
                if parsed_o['is_pending']:
                    context['can_delete'] = False
                    break
                else:
                    context['can_delete'] = True
        return context


def home(request):
    render_data = {
        "username": request.user.get_username(),
        "site_title": settings.SITE_TITLE,
        "site_byline": settings.SITE_BYLINE,
        "site_provider": settings.SITE_PROVIDER,
        "site_provider_link": settings.SITE_PROVIDER_LINK,
    }

    return render(request, 'purist/home.html', render_data)


def jslicense(request):
    render_data = {
        "site_title": settings.SITE_TITLE,
    }

    return render(request, 'purist/jslicense.html', render_data)


def public_area(request, target):
    if target == 'certificate.ovpn':
        f = open('/etc/opt/purist/middleware/certificate.ovpn', 'rb')
    else:
        raise Http404
    res = FileResponse(f, content_type='application/octet-stream')
    return res
