# -*- coding: utf-8 -*-
from __future__ import annotations

from django.contrib import messages
import django.db
from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.generic import FormView

from hotpocket_backend.apps.accounts.decorators import account_required
from hotpocket_backend.apps.accounts.mixins import AccountRequiredMixin
from hotpocket_backend.apps.ui.forms.accounts.settings import (
    FederatedPasswordForm,
    FederatedProfileForm,
    PasswordForm,
    ProfileForm,
    SettingsForm,
)


@account_required
def settings(request: HttpRequest) -> HttpResponse:
    return redirect(reverse('ui.accounts.settings.profile'))


class BaseSettingsView(AccountRequiredMixin, FormView):
    template_name = 'ui/accounts/settings.html'

    @property
    def is_federated(self) -> bool:
        return all((
            self.request.user.is_anonymous is False,
            self.request.user.has_usable_password() is False,
        ))

    def get_context_data(self, **kwargs) -> dict:
        result = super().get_context_data(**kwargs)

        result.update({
            'is_federated': self.is_federated,
        })

        return result


class ProfileView(BaseSettingsView):
    def get_form_class(self) -> type[ProfileForm]:
        if self.is_federated is True:
            return FederatedProfileForm

        return ProfileForm

    def get_initial(self) -> dict:
        result = super().get_initial()

        result.update({
            'username': self.request.user.username,
            'first_name': self.request.user.first_name,
            'last_name': self.request.user.last_name,
            'email': self.request.user.email,
        })

        return result

    def get_context_data(self, **kwargs) -> dict:
        result = super().get_context_data(**kwargs)

        result.update({
            'title': _('Profile'),
            'active_tab': 'profile',
        })

        return result

    def form_valid(self, form: ProfileForm) -> HttpResponse:
        assert self.is_federated is False, (
            'Refuse to save profile of a federated account: '
            f'account=`{self.request.user}`'
        )

        with django.db.transaction.atomic():
            self.request.user.first_name = form.cleaned_data['first_name']
            self.request.user.last_name = form.cleaned_data['last_name']
            self.request.user.email = form.cleaned_data['email']
            self.request.user.save()

        messages.add_message(
            self.request,
            messages.SUCCESS,
            message=_('Your profile has been been updated!'),
        )

        return super().form_valid(form)

    def get_success_url(self) -> str:
        return reverse('ui.accounts.settings.profile')


class PasswordView(BaseSettingsView):
    def get_form_class(self) -> type[PasswordForm]:
        if self.is_federated is True:
            return FederatedPasswordForm

        return PasswordForm

    def get_form(self,
                 form_class: type[PasswordForm] | None = None,
                 ) -> PasswordForm:
        form_class = form_class or self.get_form_class()
        return form_class(self.request.user, **self.get_form_kwargs())

    def get_context_data(self, **kwargs) -> dict:
        result = super().get_context_data(**kwargs)

        result.update({
            'title': _('Password'),
            'active_tab': 'password',
        })

        return result

    def form_valid(self, form: PasswordForm) -> HttpResponse:
        assert self.is_federated is False, (
            'Refuse to change password of a federated account: '
            f'account=`{self.request.user}`'
        )

        with django.db.transaction.atomic():
            form.set_password_and_save(
                self.request.user,
                password_field_name='new_password1',
            )

        messages.add_message(
            self.request,
            messages.SUCCESS,
            message=_('Your password has been changed!'),
        )

        return super().form_valid(form)

    def get_success_url(self) -> str:
        return reverse('ui.accounts.settings.password')


class SettingsView(BaseSettingsView):
    form_class = SettingsForm

    def get_context_data(self, **kwargs) -> dict:
        result = super().get_context_data(**kwargs)

        result.update({
            'title': _('Settings'),
            'active_tab': 'settings',
            'is_federated': False,
        })

        return result

    def get_initial(self) -> dict:
        return self.request.user.settings

    def form_valid(self, form: PasswordForm) -> HttpResponse:
        with django.db.transaction.atomic():
            self.request.user.raw_settings = form.cleaned_data
            self.request.user.save()

        messages.add_message(
            self.request,
            messages.SUCCESS,
            message=_('Your settings have been updated!'),
        )

        return super().form_valid(form)

    def get_success_url(self) -> str:
        return reverse('ui.accounts.settings.settings')
