from rest_framework.views import APIView
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from rest_framework.filters import SearchFilter, OrderingFilter

from apps.project.models import Project
from apps.employee.models import ActivityType, Activity
from apps.vendor.models import Vendor

from apps.user.models import User
from apps.consultant.models import Consultant
from apps.contractor.models import Contractor
from apps.user.serializers.admin_dashboard import ActivityTypeSerializer, ProjectSerializer, UserSerializer

from django.db.models import Sum, Count, OuterRef, Subquery, Q, F
from datetime import date, timedelta

from core.utils.helper import timedelta_to_custom_format

import pendulum



class SpentHoursDashboardAPIView(APIView):

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

        month = request.query_params.get('month', pendulum.now().month)
        year = request.query_params.get('year', pendulum.now().year)

        start_date = pendulum.datetime(int(year), int(month), 1).start_of('month')
        end_date = start_date.end_of('month')

        project_hours = Project.objects.filter(
                activity__start_date_time__gte=start_date,
                activity__end_date_time__lte=end_date
            ).annotate(
                total_hours=Sum('activity__total_duration')
            ).exclude(total_hours__isnull=True)

        serializer = ProjectSerializer(project_hours, many=True)
        return Response(serializer.data)


class MostUsedActivityTypeDashboardAPIView(APIView):

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

        month = request.query_params.get('month', pendulum.now().month)
        year = request.query_params.get('year', pendulum.now().year)

        start_date = pendulum.datetime(int(year), int(month), 1).start_of('month')
        end_date = start_date.end_of('month')

        most_used_activity_types = ActivityType.objects.filter(is_active = True,
            activity__start_date_time__gte=start_date,
            activity__end_date_time__lte=end_date
        ).annotate(
            activity_count=Count('activity')
        ).exclude(activity_count__isnull=True).exclude(activity_count=0).order_by('-activity_count')

        serializer = ActivityTypeSerializer(most_used_activity_types, many=True)
        return Response(serializer.data)


class YesterdayActiveUsersDashboardAPIView(APIView):

     def get(self, request, *args, **kwargs):
        yesterday = date.today() - timedelta(days = 1)
        with_trashed = self.request.query_params.get('with_trashed')

        activity_qs = Activity.objects.filter(user_id=OuterRef('pk'), start_date_time__date=yesterday) \
                        .values('user_id') \
                        .annotate(total_working_duration=Sum('total_duration')) \
                        .values('user_id', 'total_working_duration')

        active_users_queryset = User.objects.filter(is_active=True).filter_employee().values('id') \
            .annotate_full_name() \
            .annotate(total_working_duration=Subquery(activity_qs.values('total_working_duration'))) \
            .filter(total_working_duration__isnull=False) \
            .order_by('-total_working_duration').annotate(deleted_at=F('deleted_at'))

        if with_trashed == 'true':
            active_users_queryset = User.objects.with_trashed().filter(is_active=True).filter_employee().values('id') \
            .annotate_full_name() \
            .annotate(total_working_duration=Subquery(activity_qs.values('total_working_duration'))) \
            .filter(total_working_duration__isnull=False) \
            .order_by('-total_working_duration').annotate(deleted_at=F('deleted_at'))

        active_users_list = [
            {**item, 'total_working_duration': timedelta_to_custom_format(item['total_working_duration'])}
            for item in list(active_users_queryset)
        ]

        return Response(active_users_list)


class DashboardTotalsAPIView(APIView):

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

        total_employees = User.objects.filter(is_active=True).filter_employee().count()
        total_projects = Project.objects.count()
        total_activity_types = ActivityType.objects.filter(is_active=True).count()
        total_vendors = Vendor.objects.count()
        total_consultants = Consultant.objects.count()
        total_contractor = Contractor.objects.count()
        return Response({
            'total_employees': total_employees,
            'total_projects': total_projects,
            'total_activity_types': total_activity_types,
            'total_vendors': total_vendors,
            'total_consultants': total_consultants,
            'total_contractor': total_contractor
        })


class TopEmployeesMaxHoursAPIView(APIView):

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

        month = request.query_params.get('month', pendulum.now().month)
        year = request.query_params.get('year', pendulum.now().year)

        start_date = pendulum.datetime(int(year), int(month), 1).start_of('month')
        end_date = start_date.end_of('month')

        top_employees_max_hours = User.objects.filter(
            activity__start_date_time__date__gte=start_date,
            activity__start_date_time__date__lte=end_date,
            role__name='employee', is_active=True, activity__deleted_at__isnull=True, activity__deleted_by_id__isnull=True
        ).annotate(
            total_duration=Sum('activity__total_duration')
        ).order_by('-total_duration').exclude(total_duration__isnull=True).exclude(total_duration='00:00:00').distinct()[:5]

        serializer = UserSerializer(top_employees_max_hours, context={"start_date": start_date, "end_date": end_date}, many=True)
        return Response(serializer.data)


class TopEmployeesMinHoursAPIView(APIView):

    def get(self, request, *args, **kwargs):
        month = request.query_params.get('month', pendulum.now().month)
        year = request.query_params.get('year', pendulum.now().year)

        start_date = pendulum.datetime(int(year), int(month), 1).start_of('month')
        end_date = start_date.end_of('month')

        top_employees_min_hours = User.objects.filter(
            activity__start_date_time__date__gte=start_date,
            activity__start_date_time__date__lte=end_date,
            role__name='employee', is_active=True
        ).annotate(
            total_duration=Sum('activity__total_duration')
        ).exclude(total_duration__isnull=True).exclude(total_duration='00:00:00').distinct().order_by('total_duration')[:5]

        serializer = UserSerializer(top_employees_min_hours, many=True, context={"start_date": start_date, "end_date": end_date})
        return Response(serializer.data)


class EmployeesHoursAPIView(ListAPIView):
    serializer_class = UserSerializer
    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['full_name', 'id' ]
    ordering_fields = ['id', 'full_name', 'total_duration' ]

    def get_queryset(self):
        month = self.request.query_params.get('month', pendulum.now().month)
        year = self.request.query_params.get('year', pendulum.now().year)

        start_date = pendulum.datetime(int(year), int(month), 1).start_of('month')
        end_date = start_date.end_of('month')

        queryset = User.objects.filter(
            activity__start_date_time__date__gte=start_date,
            activity__start_date_time__date__lte=end_date,
            role__name='employee', is_active=True
        ).annotate_full_name().annotate(
            total_duration=Sum('activity__total_duration')
        ).exclude(total_duration__isnull=True).exclude(total_duration='00:00:00').distinct()

        return queryset
