# -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""
from email.mime.image import MIMEImage
from pathlib import Path
from typing import List

from django.conf import settings
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMultiAlternatives
from django.shortcuts import redirect, render, reverse
from django.template.loader import render_to_string
from django.utils import encoding, html, http
from django.views import generic

from . import forms, tokens


def login_view(request):
    form = forms.LoginForm(request.POST or None)

    msg = None

    if request.method == "POST":

        if form.is_valid():
            email = form.cleaned_data.get("email")
            password = form.cleaned_data.get("password")
            user = authenticate(username=email, password=password)
            if user is not None:
                login(request, user)
                return redirect("home")
            else:
                msg = 'Invalid credentials'
        else:
            msg = 'Incorrect credentials provided'

    return render(request, "accounts/login.html", {"form": form, "msg": msg})


def register_user(request):
    if request.method == "POST":
        form = forms.SignUpForm(request.POST)
        profile_form = forms.ProfileForm(request.POST)
        if form.is_valid() and profile_form.is_valid():
            user = form.save(commit=False)
            user.username = user.email
            user.is_active = False
            user.save()

            for attr, val in profile_form.cleaned_data.items():
                setattr(user.profile, attr, val)
            user.profile.save()

            current_site = get_current_site(request)
            subject = 'Delta Carbon EPC Tool - Activate Your Account'

            html_message = get_confirmation_email_args(user, current_site)
            icons_to_attach = get_email_icons()

            email = create_email_with_inline_images(subject, html_message, user.email, icons_to_attach)
            email.send()

            return redirect('activation_sent')
    else:
        form = forms.SignUpForm()
        profile_form = forms.ProfileForm()

    terms_of_service = render_to_string('legal/terms_of_service.html')

    return render(
        request,
        "accounts/register.html",
        {"form": form, "profile_form": profile_form, "terms_of_service": terms_of_service},
    )


def get_email_icons() -> List[Path]:
    image_dir = settings.STATIC_CORE / "assets" / "img"
    icon_dir = image_dir / "icons"
    delta_carbon_logo = image_dir / "delta_carbon" / "PNGs Low Res" / "DC Logo FA-02.png"
    icons_to_attach = list(icon_dir.glob("*.png"))
    icons_to_attach.append(delta_carbon_logo)
    return icons_to_attach


def get_confirmation_email_args(user, current_site):
    confirmation_message = f"Hi {user.get_full_name()}, please click on the link below to confirm your registration."

    return render_to_string(
        'emails/body.html',
        {
            'email_title': "New User Registration",
            'email_message': confirmation_message,
            'domain': current_site.domain,
            'uid': http.urlsafe_base64_encode(encoding.force_bytes(user.pk)),
            'token': tokens.account_activation_token.make_token(user),
        },
    )


def create_email_with_inline_images(subject, html_message, email, images_to_attach) -> EmailMultiAlternatives:
    plain_message = html.strip_tags(html_message)

    email = EmailMultiAlternatives(subject, plain_message, settings.DEFAULT_FROM_EMAIL, [email])

    email.attach_alternative(html_message, "text/html")
    email.mixed_subtype = 'related'

    for image_content in images_to_attach:
        with image_content.open('rb') as file:
            image = MIMEImage(file.read())
            image.add_header('Content-ID', f"<{image_content.name.replace(' ', '-')}>")
            email.attach(image)

    return email


def activate(request, uidb64, token):
    try:
        uid = encoding.force_text(http.urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except (TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None

    if user is not None and tokens.account_activation_token.check_token(user, token):
        user.is_active = True
        user.profile.email_confirmed = True
        user.save()
        login(request, user)
        return redirect('activation_welcome')
    else:
        return render(request, 'accounts/activation_invalid.html')


def activation_sent(request):
    return render(request, 'accounts/activation_sent.html')


def activation_welcome(request):
    return render(request, 'accounts/activation_welcome.html')


class SettingsUpdateView(generic.edit.UpdateView):
    model = User
    user_form = forms.UserEditForm
    profile_form = forms.ProfileEditForm
    template_name = 'accounts/settings.html'

    def get_context_data(self, **kwargs):
        return {
            'user': (self.user_form(instance=self.object)),
            'profile': (self.profile_form(instance=self.object.profile)),
        }

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

    def get_success_url(self):
        return reverse('settings')

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        user = self.user_form(request.POST, instance=self.object)
        profile = self.profile_form(request.POST, instance=self.object.profile)

        # TODO: Fix why this isn't saving with the other fields.
        if 'profile_photo' in request.FILES:
            request.user.profile.profile_photo = request.FILES['profile_photo']
            request.user.profile.save()
        if 'cover_photo' in request.FILES:
            request.user.profile.cover_photo = request.FILES['cover_photo']
            request.user.profile.save()

        for form in (user, profile):
            if form.is_valid() and form.has_changed():
                form.save()

        return redirect(self.get_success_url())
