import logging
import os

from django.conf import settings
from rest_framework.generics import RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView, CreateAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from core import constants
from core.mixins import ApiPermissionCheckMixin
from core.models import ConsoleAuthSettings, TLSSettings
from core.serializers import AuthSettingsSerializer, TLSSettingsSerializer
from core.services.tls_settings import handle_uploaded_file, update_nginx, remove_ssl_certificate, restart_nginx, \
    update_model, create_cert
from perms.models import Perm

_log = logging.getLogger(__name__)


class AuthSettingsAPIView(ApiPermissionCheckMixin,
                          RetrieveUpdateAPIView):
    console_permissions = [Perm.can_view_system_settings]
    serializer_class = AuthSettingsSerializer

    def get_object(self):
        auth_settings = ConsoleAuthSettings.get_solo()
        return auth_settings

    class Meta:
        model = ConsoleAuthSettings


class TLSSettingsAPIView(ApiPermissionCheckMixin, RetrieveUpdateDestroyAPIView, CreateAPIView):
    console_permissions = [Perm.can_view_system_settings]
    serializer_class = TLSSettingsSerializer

    def get_object(self):
        tls_settings = TLSSettings.get_solo()
        return tls_settings

    def create(self, request, *args, **kwargs):
        """
            Generate new TLS certificate and save to MEDIA_ROOT
        """
        tls_settings = self.get_object()
        create_cert(tls_settings)
        tls_settings.save()
        data = self.serializer_class(tls_settings).data
        return Response(data)

    def retrieve(self, request, *args, **kwargs):
        tls_settings = self.get_object()
        if os.path.exists(os.path.join(settings.MEDIA_ROOT, constants.DEFAULT_CERT_FILENAME)) and \
                os.path.exists(os.path.join(settings.MEDIA_ROOT, constants.DEFAULT_KEY_FILENAME)):
            tls_settings.certificate.name = constants.DEFAULT_CERT_FILENAME
            tls_settings.key.name = constants.DEFAULT_KEY_FILENAME
            tls_settings.save()
        serializer = self.get_serializer(instance=tls_settings)
        return Response(serializer.data)

    def update(self, request, *args, **kwargs):
        tls_settings = self.get_object()
        serializer = self.get_serializer(instance=tls_settings, data=request.data)
        serializer.is_valid(raise_exception=True)

        tls_settings.enabled = serializer.validated_data["enabled"]

        _log.info("Processing upload files")
        if serializer.validated_data['file_count'] == 2:
            handle_uploaded_file(serializer.validated_data.get("certificate", None),
                                 os.path.join(settings.MEDIA_ROOT, constants.DEFAULT_CERT_FILENAME))
            handle_uploaded_file(serializer.validated_data.get("key", None),
                                 os.path.join(settings.MEDIA_ROOT, constants.DEFAULT_KEY_FILENAME))

        update_model(tls_settings)

        _log.info(f"User [{request.user}] set HTTPS enabled to [{serializer.validated_data['enabled']}]")
        update_nginx(serializer.validated_data["enabled"])
        restart_nginx()
        tls_settings.save()
        tls_settings.clear_cache()

        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        remove_ssl_certificate()
        update_nginx(False)
        restart_nginx()
        _log.info(f"User [{request.user}] set HTTPS enabled to false")

        return Response()


class ProductVersionView(APIView):
    """Product version API"""

    def get(self, request):
        return Response(settings.PRODUCT_VERSION)
