from django.http import HttpResponse
from rest_framework.decorators import action
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from core.mixins import ApiPermissionCheckMixin
from devices.enums import DeviceType
from devices.models.firewall import ArmaIndustrialFirewall
from devices.serializers.firewall import FirewallSerializer, CheckFirewallConnectionSerializer, \
    AifUploadIdsRulesetsSerializer, AifUploadConfigSerializer
from devices.services.firewall import FirewallService
from devices.services.vector import VectorService
from devices.tasks.firewall import download_files_from_firewall_task


class ArmaIndustrialFirewallViewSet(ApiPermissionCheckMixin, ModelViewSet):
    queryset = ArmaIndustrialFirewall.objects.all()
    serializer_class = FirewallSerializer

    def perform_create(self, serializer):
        check_connection_serializer = CheckFirewallConnectionSerializer(data=self.request.data)
        check_connection_serializer.is_valid(raise_exception=True)

        fs = FirewallService()
        fs.check_connection(check_connection_serializer.validated_data)
        firewall = serializer.save(type=DeviceType.FIREWALL)

        fs.firewall = firewall

        vector = VectorService(firewall)
        vector.update_config()

    def perform_update(self, serializer):
        check_connection_serializer = CheckFirewallConnectionSerializer(data=self.request.data)
        check_connection_serializer.is_valid(raise_exception=True)
        fs = FirewallService()
        fs.check_connection(check_connection_serializer.validated_data)

        firewall = serializer.save()
        vector = VectorService(firewall)
        vector.update_config()

    def perform_destroy(self, device):
        vector = VectorService(device)
        vector.delete_config()
        device.delete()

    @action(detail=True, methods=['GET'])
    def status(self, request, *args, **kwargs):
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        response = FirewallService(firewall).check_status()
        return Response(response)

    @action(detail=True, methods=['POST'])
    def upload_ids_rulesets(self, request, *args, **kwargs):
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        serializer = AifUploadIdsRulesetsSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        rulesets_file = serializer.validated_data['rulesets']
        response = FirewallService(firewall).upload_file(rulesets_file, 'rulesets')
        return Response(response)

    @action(detail=True, methods=['POST'])
    def upload_config(self, request, *args, **kwargs):
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        serializer = AifUploadConfigSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        config_file = serializer.validated_data['conffile']
        response = FirewallService(firewall).upload_file(config_file, 'config')
        return Response(response)

    @action(detail=True, methods=['GET'])
    def download_rulesets(self, request, *args, **kwargs):  # Deprecated
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        file_byte, name = FirewallService(firewall).download_file('rulesets')
        response = HttpResponse(file_byte, content_type="application/file")
        response['Content-Disposition'] = f'attachment; filename="{name}"'
        return response

    @action(detail=True, methods=['GET'])
    def download_config(self, request, *args, **kwargs):  # Deprecated
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        file_byte, name = FirewallService(firewall).download_file('config')
        response = HttpResponse(file_byte, content_type="application/file")
        response['Content-Disposition'] = f'attachment; filename="{name}"'
        return response

    @action(detail=True, methods=['GET'])
    def download_config_new(self, request, *args, **kwargs): # todo remove suffix _new
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        task = download_files_from_firewall_task.apply_async(args=(firewall.pk, request.user.pk, 'config'))
        return Response({'task_id': task.id})

    @action(detail=True, methods=['GET'])
    def download_rulesets_new(self, request, *args, **kwargs):  # todo remove suffix _new
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        task = download_files_from_firewall_task.apply_async(args=(firewall.pk, request.user.pk, 'rulesets'))
        return Response({'task_id': task.id})

    @action(detail=True, methods=['POST'])
    def reboot(self, request, *args, **kwargs):
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        response = FirewallService(firewall).reboot()
        return Response(response)

    @action(detail=True, methods=['GET'])
    def rule_fields(self, request, *args, **kwargs):
        firewall = get_object_or_404(ArmaIndustrialFirewall, pk=kwargs['pk'])
        response = FirewallService(firewall).rule_fields(request)
        return Response(response)
