from django.db.models import Q
from django.http.response import JsonResponse
from django.core.paginator import Paginator
from .utils import JsonResponseUtil
from django.views import generic

class DatatablesMixin:
    """
    Mixin for handling Datatables parameters, filtering, sorting, pagination,
    and response preparation.
    """
    filter_fields = []
    search_fields = []

    def get_datatables_params(self, request):
        """
        Extracts Datatables parameters from the request.
        """
        draw = request.GET.get('draw', 1)
        start = request.GET.get("start", 0)
        length = request.GET.get("length", 10)
        order_columns = request.GET.getlist('order[][column]')
        order_directions = request.GET.getlist('order[][dir]')
        search_value = request.GET.get("search[value]", "")
        return draw, start, length, order_columns, order_directions, search_value

    def get_filters(self, request):
        """
        Extracts and applies filters based on request parameters.
        """
        filters = {}
        for field in self.filter_fields:
            value = request.GET.get(field)
            if value:
                filters[field] = value
            return filters

    def get_sorting(self, request, order_columns, order_directions):
        """
        Constructs the sorting order based on request parameters.
        """
        sorting = []
        for i in range(len(order_columns)):
            column_index = int(order_columns[i])
            order = order_directions[i]
            field = self.model._meta.get_field(column_index).name
            sorting.append('-' + field if order == 'desc' else field)
        return sorting

    def get_search_filters(self, request, search_value, search_fields):
        """
        Generates Q objects for global and individual column search.
        """
        search_filters = Q()
        if search_value:
            for field in search_fields:
                search_filters |= Q(**{f'{field}__icontains': search_value})
            if 'columns' in request.GET:
                search_filters = Q()
                for i, column_index in enumerate(request.GET.getlist('order[][column]')):
                    if request.GET.get(f'columns[{column_index}][search][value]'):
                        field = self.model._meta.get_field(int(column_index)).name
                        search_filters |= Q(**{f'{field}__icontains': request.GET.get(f'columns[{column_index}][search][value]')})
        return search_filters

    def get_pagination(self, queryset, start, length):
        """
        Performs pagination based on the requested page and page size.
        """
        paginator = Paginator(queryset, length)
        page_number = (int(start) // int(length)) + 1
        page_obj = paginator.page(page_number)

        total_count = paginator.count
        filtered_count = len(page_obj.object_list)

        return page_obj, total_count, filtered_count

    def prepare_datatables_response(self, draw, total_count, filtered_count, data):
        """
        Prepares the JSON response for Datatables.
        """
        return JsonResponse({
            "draw": draw,
            "recordsTotal": total_count,
            "recordsFiltered": filtered_count,
            "data": data
        })


class ActionMixin(generic.View):
    model = None

    def post(self, request, *args, **kwargs):

        if self.model is None:
            raise NotImplementedError("Subclasses of BaseActionView must define a 'model' attribute.")

        action = request.POST.get('action')  # 'archive', 'active', or 'unarchive'
        ids = request.POST.getlist('ids[]')  # List of IDs to perform action on
        active = request.POST.get('active')
        print(f"arhive action {action} and id is {ids} and active data is {active}")
        if action == 'archive':
            # Update 'deleted' field to True for the selected users
            self.model.objects.filter(id__in=ids).update(deleted=True, active=False)
            message = 'Record archived successfully.'
        elif action == 'active':
            # Update 'active' field to True for the selected users
            self.model.objects.filter(id__in=ids).update(active=active.capitalize())
            message = 'Record updated successfully.'
        elif action == 'unarchive':
            # Update 'deleted' field to False for the selected users
            self.model.objects.filter(id__in=ids).update(deleted=False)
            message = 'Record unarchived successfully.'
        else:
            return JsonResponseUtil.error(message="Invalid Action")

        return JsonResponseUtil.success(message=message)