from django.db.models import Count, Q
from django.http import JsonResponse
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin, CreateModelMixin
from rest_framework.viewsets import GenericViewSet

from assets.constants import RESOLVED_STATUS
from assets.filters import AssetFilter
from assets.models.assets import Asset, OperatingSystem, AssetListGroup, AssetManufacturer
from assets.serializers.assets import AssetGroupSerializer, AssetInfoSerializer, OsSerializer, AssetDetailSerializer, \
    AssetCsvExportSerializer, AssetListSerializer, AssetCreateUpdateSerializer, AssetActiveProblemsSerializer, \
    AssetAuthorizeSerializer, AssetManufacturerSerializer
from core.mixins import ApiPermissionCheckMixin, ExportToCsvMixin, DestroyModelResponseStatus200Mixin
from perms.models import Perm


class AssetViewSet(ApiPermissionCheckMixin,
                   ListModelMixin,
                   RetrieveModelMixin,
                   UpdateModelMixin,
                   DestroyModelResponseStatus200Mixin,
                   ExportToCsvMixin,
                   GenericViewSet):
    column_titles = AssetCsvExportSerializer.Meta.fields
    console_permissions = {'csv_export': [Perm.can_export_assets], 'list': [Perm.can_view_assets_list],
                           'destroy': [Perm.can_delete_asset], 'retrieve': [Perm.can_view_asset],
                           'authorize_assets': [Perm.can_view_assets_list], 'update': [Perm.can_edit_asset],
                           'partial_update': [Perm.can_edit_asset],
                           }
    filters = []
    filterset_class = AssetFilter

    class Meta:
        model = Asset

    def get_queryset(self):
        return Asset.objects.annotate(count_incidents=Count('incidents', filter=~Q(status=RESOLVED_STATUS)))

    def get_serializer_class(self):
        if self.action == 'list':
            return AssetListSerializer
        if self.action in ['update', 'partial_update']:
            return AssetCreateUpdateSerializer
        return AssetDetailSerializer

    @action(detail=False, methods=["POST"], name="authorize_assets")
    def authorize_assets(self, request):
        """ API for authorizing assets by changing its status from NEW to ALLOWED """
        serializer = AssetAuthorizeSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        assets_to_change = serializer.validated_data['selected_assets']
        Asset.objects.filter(pk__in=assets_to_change).update(status=Asset.AllowStatus.ALLOWED)
        return JsonResponse({'status': 'ok'})


class AssetGroupViewSet(ApiPermissionCheckMixin,
                        ListModelMixin,
                        RetrieveModelMixin,
                        CreateModelMixin,
                        UpdateModelMixin,
                        DestroyModelResponseStatus200Mixin,
                        GenericViewSet):
    serializer_class = AssetGroupSerializer
    queryset = AssetListGroup.objects.order_by('name').all()
    console_permissions = {'default': [Perm.can_view_assets_list]}

    class Meta:
        model = AssetListGroup


class AssetInfoViewSet(ApiPermissionCheckMixin,
                       RetrieveModelMixin,
                       ListModelMixin,
                       GenericViewSet):
    serializer_class = AssetInfoSerializer
    console_permissions = {'retrieve': [Perm.can_view_asset], 'list': [Perm.can_view_assets_list]}
    queryset = Asset.objects.all()

    class Meta:
        model = Asset


class OsViewSet(ApiPermissionCheckMixin,
                ListModelMixin,
                RetrieveModelMixin,
                CreateModelMixin,
                UpdateModelMixin,
                DestroyModelResponseStatus200Mixin,
                GenericViewSet):
    serializer_class = OsSerializer
    queryset = OperatingSystem.objects.order_by('name')
    console_permissions = {'list': [Perm.can_edit_assets_catalogs], 'destroy': [Perm.can_edit_assets_catalogs],
                           'retrieve': [Perm.can_edit_assets_catalogs], 'update': [Perm.can_edit_assets_catalogs],
                           'partial_update': [Perm.can_edit_assets_catalogs], 'create': [Perm.can_edit_assets_catalogs]
                           }

    class Meta:
        model = OsSerializer


class AssetProblemsViewSet(ApiPermissionCheckMixin, RetrieveModelMixin, GenericViewSet):
    serializer_class = AssetActiveProblemsSerializer
    console_permissions = {'retrieve': [Perm.can_view_incidents_list]}
    queryset = Asset.objects.all()

    class Meta:
        model = Asset


class AssetManufacturersViewSet(ApiPermissionCheckMixin,
                                ListModelMixin,
                                RetrieveModelMixin,
                                CreateModelMixin,
                                UpdateModelMixin,
                                DestroyModelResponseStatus200Mixin,
                                GenericViewSet):
    serializer_class = AssetManufacturerSerializer
    queryset = AssetManufacturer.objects.all()
    console_permissions = {'list': [Perm.can_edit_assets_catalogs], 'destroy': [Perm.can_edit_assets_catalogs],
                           'retrieve': [Perm.can_edit_assets_catalogs], 'update': [Perm.can_edit_assets_catalogs],
                           'partial_update': [Perm.can_edit_assets_catalogs], 'create': [Perm.can_edit_assets_catalogs]
                           }

    class Meta:
        model = AssetManufacturer
