"""
Base views providing reusable API views for list, create, retrieve, update, and destroy operations with custom responses.
"""
from django.utils import timezone
from rest_framework import generics, status
from rest_framework.response import Response
from core.response import *


class CustomListAPIView(generics.ListAPIView):
    """
    A reusable base view for custom list APIs with manual pagination and standardized responses.
    """
    pagination_enabled = False  # You can toggle this if needed later

    def get_filtered_paginated_queryset(self, request):
        """
        Filter and paginate the queryset based on request parameters.
        """
        base_queryset = self.get_queryset()
        filtered_queryset = self.filter_queryset(base_queryset)

        if not base_queryset.exists():
            return None, success_response(data=None, code=status.HTTP_200_OK, message=blankData)

        if not filtered_queryset.exists():
            return None, success_response(data=None, code=status.HTTP_200_OK, message=filterRecordEmpty)

        limit = request.query_params.get('limit')
        offset = request.query_params.get('offset')

        if limit is not None and offset is not None:
            try:
                limit = int(limit)
                offset = int(offset)
                filtered_queryset = filtered_queryset[offset:offset + limit]
            except ValueError:
                return None, fail_response(code=status.HTTP_400_BAD_REQUEST, message=limitOffset)

        return filtered_queryset, None

    def list(self, request, *args, **kwargs):
        """
        List objects with custom response formatting.
        """
        queryset, early_response = self.get_filtered_paginated_queryset(request)
        if early_response:
            return Response(early_response)

        serializer = self.get_serializer(queryset, many=True)
        return Response(
            success_response(data=serializer.data, code=status.HTTP_200_OK, message=getMessage))


class CustomCreateAPIView(generics.CreateAPIView):
    """
    Base view for create APIs.
    """
    pagination_enabled = False  # default: manual pagination

    def create(self, request, *args, **kwargs):
        """
        Create an object with custom response formatting.
        """
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return Response(
            success_response(serializer.data, code=status.HTTP_200_OK, message=createdMessage))


class CustomRetrieveDestroyAPIView(generics.RetrieveDestroyAPIView):
    """
    Base view for retrieve and destroy APIs with custom responses.
    """

    def retrieve(self, request, *args, **kwargs):
        """
        Retrieve an object with custom response formatting.
        """
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(success_response(
                data=serializer.data,
                code=status.HTTP_200_OK,
                message=getMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_404_NOT_FOUND, message=str(e)))

    def destroy(self, request, *args, **kwargs):
        """
        Destroy an object with custom response formatting.
        """
        try:
            instance = self.get_object()
            self.perform_destroy(instance)
            return Response(success_response(
                data=None,
                code=status.HTTP_204_NO_CONTENT,
                message=deletedMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_400_BAD_REQUEST, message=str(e)))


class CustomListCreateAPIView(generics.ListCreateAPIView):
    """
    Base view for list and create APIs with manual pagination and custom responses.
    """
    pagination_enabled = False  # default: manual pagination

    def get_queryset_data(self, request):
        """
        Handles filtering and manual offset/limit pagination.
        """
        base_queryset = self.get_queryset()
        filtered_queryset = self.filter_queryset(base_queryset)

        if not base_queryset.exists():
            return None, success_response(data=None, code=status.HTTP_200_OK, message=blankData)

        if not filtered_queryset.exists():
            return None, success_response(data=None, code=status.HTTP_200_OK, message=filterRecordEmpty)

        limit = request.query_params.get("limit")
        offset = request.query_params.get("offset")

        if limit is not None and offset is not None:
            try:
                limit = int(limit)
                offset = int(offset)
                filtered_queryset = filtered_queryset[offset:offset + limit]
            except ValueError:
                return None, fail_response(code=status.HTTP_400_BAD_REQUEST, message=limitOffset)

        return filtered_queryset, None

    def list(self, request, *args, **kwargs):
        """
        List objects with custom response formatting.
        """
        queryset, early_response = self.get_queryset_data(request)
        if early_response:
            return Response(early_response)

        serializer = self.get_serializer(queryset, many=True)
        return Response(
            success_response(serializer.data, code=status.HTTP_200_OK, message=getMessage)
        )

    def create(self, request, *args, **kwargs):
        """
        Create an object with custom response formatting.
        """
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return Response(
            success_response(serializer.data, code=status.HTTP_200_OK, message=createdMessage))


class CustomRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    """
    Base view for retrieve, update, and destroy APIs with custom responses.
    """

    def retrieve(self, request, *args, **kwargs):
        """
        Retrieve an object with custom response formatting.
        """
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(success_response(
                data=serializer.data,
                code=status.HTTP_200_OK,
                message=getMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_404_NOT_FOUND, message=str(e)))

    def update(self, request, *args, **kwargs):
        """
        Update an object with custom response formatting.
        """
        partial = kwargs.get('partial', False)
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=request.data, partial=partial)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)
            return Response(success_response(
                data=serializer.data,
                code=status.HTTP_200_OK,
                message=updatedMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_400_BAD_REQUEST, message=str(e)))

    def destroy(self, request, *args, **kwargs):
        """
        Destroy an object with custom response formatting.
        """
        try:
            instance = self.get_object()
            self.perform_destroy(instance)
            return Response(success_response(
                data=None,
                code=status.HTTP_204_NO_CONTENT,
                message=deletedMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_400_BAD_REQUEST, message=str(e)))


class CustomRetrieveUpdateSoftDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    """
    Base view for retrieve, update, and soft destroy APIs with custom responses.
    """

    def retrieve(self, request, *args, **kwargs):
        """
        Retrieve an object with custom response formatting.
        """
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(success_response(
                data=serializer.data,
                code=status.HTTP_200_OK,
                message=getMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_404_NOT_FOUND, message=str(e)))

    def update(self, request, *args, **kwargs):
        """
        Update an object with custom response formatting.
        """
        partial = kwargs.get('partial', False)
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=request.data, partial=partial)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)
            return Response(success_response(
                data=serializer.data,
                code=status.HTTP_200_OK,
                message=updatedMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_400_BAD_REQUEST, message=str(e)))

    def destroy(self, request, *args, **kwargs):
        """
        Soft destroy (mark as deleted) an object with custom response formatting.
        """
        try:
            instance = self.get_object()
            instance.deletedOn = timezone.now()
            instance.save(update_fields=['deletedOn'])
            return Response(success_response(
                data=None,
                code=status.HTTP_204_NO_CONTENT,
                message=softDeletedMessage
            ))
        except Exception as e:
            return Response(fail_response(code=status.HTTP_400_BAD_REQUEST, message=str(e)))
