from django.utils.http import urlencode
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth import login, logout
from django.http import HttpResponseRedirect
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import RedirectView, FormView, TemplateView
from django.core.cache import cache

from users.forms import LoginForm, UserRegistrationForm, ChangePasswordForm, ForgotPasswordForm, ResetPasswordForm
from users.models import User


class LoginView(TemplateView):

    def get(self, request, *args, **kwargs):
        data = self.get_context_data()
        data['form'] = LoginForm()
        request.session.set_test_cookie()
        return self.render_to_response(data)

    def post(self, request, *args, **kwargs):
        data = self.get_context_data()
        data['form'] = LoginForm(request, request.POST)

        if data['form'].is_valid():
            try:
                user = data['form'].get_user()
                if user is None:
                    raise Exception('User does not exist')
                login(request, user)
                messages.success(request, 'Login successful')

                return HttpResponseRedirect(
                    reverse_lazy('index')
                )
            except Exception as e:
                if 'invalid password' in str(e).lower():
                    messages.error(request, _('Invalid password'))
                elif 'user is not active' in str(e).lower():
                    messages.error(request, _('User is not active'))
                elif 'user does not exist' in str(e).lower():
                    messages.error(request, _('User does not exist'))
                else:
                    messages.error(request, e)

        else:
            for field, errors in data['form'].errors.items():
                for error in errors:
                    messages.error(request, f'{field}: {error}')

        return self.render_to_response(data)


class LogoutView(LoginRequiredMixin, RedirectView):
    def get(self, request, *args, **kwargs):
        logout(request)
        messages.success(request, _('You have been logged out.'))

        return HttpResponseRedirect(
            reverse_lazy('index')
        )


class ChangePasswordView(LoginRequiredMixin, TemplateView):

    def get(self, request, *args, **kwargs):
        data = self.get_context_data()
        data['form'] = ChangePasswordForm()
        return self.render_to_response(data)

    def post(self, request, *args, **kwargs):
        data = self.get_context_data()
        data['form'] = ChangePasswordForm(request.POST)

        if data['form'].is_valid():
            # check old password
            if not data['form'].cleaned_data['password']:
                messages.error(request, _('Old password is required'))
                return self.render_to_response(data)

            if not request.user.check_password(data['form'].cleaned_data['password']):
                messages.error(request, _('Invalid actual password'))
                return self.render_to_response(data)

            if data['form'].cleaned_data['password1'] != data['form'].cleaned_data['password1']:
                messages.error(request, _('Passwords do not match'))
                return self.render_to_response(data)

            # change password
            request.user.set_password(data['form'].cleaned_data['password1'])
            request.user.save()

            # re-login
            login(request, request.user)
            messages.success(request, _('Password changed successfully'))

            return HttpResponseRedirect(
                reverse_lazy('index')
            )
        else:
            for field, errors in data['form'].errors.items():
                for error in errors:
                    messages.error(request, f'{field}: {error}')

        return self.render_to_response(data)

