from collections import defaultdict
from hrms.models.user import JRPUser
from prj_mgt.models.projects import Project, ProjectMember, ProjectModule, ProjectTask
from prj_mgt.serializers.projects import ProjectMemberSerializer, ProjectModuleSerializer, ProjectSerializer, ProjectTaskRetriveSerializer, ProjectTaskSerializer
from hrms.views._views_mixins import ListAndSerializerMixin
from rest_framework import viewsets, permissions
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import viewsets, permissions
from rest_framework.decorators import action
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework import status
from django.db.models import Count


class ProjectViewSet(ListAndSerializerMixin, viewsets.ModelViewSet):
    
    serializer_class = ProjectSerializer
    serializer_classes = {
        "update": ProjectSerializer, # update
        "retrieve": ProjectSerializer, "get item by id "
        "create": ProjectSerializer, #save
        "list": ProjectSerializer, ##"all objects list"
        # ... other actions
    }
    default_serializer_class = ProjectSerializer
    queryset = Project.objects.all().order_by('-created_at')
     
    permission_classes = [IsAuthenticated]   
    
    def perform_create(self, serializer):
        """ Set the created_by user when creating a new DepartmentType. """
        serializer.save(created_by=self.request.user.id)

    def perform_update(self, serializer):
        """ Set the updated_by user when updating a DepartmentType. """
        serializer.save(updated_by=self.request.user.id)
   
    @action(detail=False, methods=["GET"], name="DDL List")     
    def ddl(self, request, *args, **kwargs):        
         
        data_list = Project.objects.all()
         

        data_list_serializr = self.default_serializer_class(
            data_list, read_only=True, many=True
        )    
        filtered_data = [{'id': item['id'], 'name': item['project_name']} for item in data_list_serializr.data]
        return Response(filtered_data)
    
class ProjectMembersViewSet(ListAndSerializerMixin, viewsets.ModelViewSet):
    
    serializer_class = ProjectMemberSerializer
    serializer_classes = {
        "update": ProjectMemberSerializer, # update
        "retrieve": ProjectMemberSerializer, "get item by id "
        "create": ProjectMemberSerializer, #save
        "list": ProjectMemberSerializer, ##"all objects list"
        # ... other actions
    }
    default_serializer_class = ProjectMemberSerializer
    queryset = ProjectMember.objects.all().order_by('-created_at')
     
    permission_classes = [IsAuthenticated]   
    
    def perform_create(self, serializer):
        """ Set the created_by user when creating a new DepartmentType. """
        serializer.save(created_by=self.request.user.id)

    def perform_update(self, serializer):
        """ Set the updated_by user when updating a DepartmentType. """
        serializer.save(updated_by=self.request.user.id)
   
    @action(detail=False, methods=["GET"], name="DDL List")
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'project_id',
                openapi.IN_QUERY,
                description="project_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )     
    def ddl(self, request, *args, **kwargs): 
         
        project_id = request.query_params.get('project_id', None)
        print('project_id',project_id)      
         
         
         
        data_list = ProjectMember.objects.filter(project_id=project_id).select_related('member')

        filtered_data = [
            {
                'id': item.member.id,
                'name': item.member.first_name + ' ' + item.member.last_name + ' (' + item.role + ')'  if item.member.first_name else item.member.email
            }
            for item in data_list
        ]
        
        return Response(filtered_data)
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'project_id',
                openapi.IN_QUERY,
                description="project_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )     
    def list(self, request, *args, **kwargs): 
         
        project_id = request.query_params.get('project_id', None)
             
         
        
        members = ProjectMember.objects.filter(project_id=project_id).select_related('project', 'member')
        print('data_list',members) 
        
        member_list = []

        for member in members:
            print('member',member)
            member_list.append({
                "member_id": member.id,
                "role": member.role,
                "joined_at": member.joined_at,
                "is_active": member.is_active,
                "project": {
                    "id": member.project.id,
                    "name": member.project.project_name,  # assuming Project has a 'name' field
                },
                "user": {
                    "id": member.member.id,
                    "name": member.member.first_name + ' ' + member.member.last_name,  # assuming JRPUser has a 'username'
                    "email": member.member.email,        # or other user fields
                }
            })

        return Response(member_list)
    
class ProjectModuleViewSet(ListAndSerializerMixin, viewsets.ModelViewSet):
    
    serializer_class = ProjectModuleSerializer
    serializer_classes = {
        "update": ProjectModuleSerializer, # update
        "retrieve": ProjectModuleSerializer, "get item by id "
        "create": ProjectModuleSerializer, #save
        "list": ProjectModuleSerializer, ##"all objects list"
        # ... other actions
    }
    default_serializer_class = ProjectModuleSerializer
    queryset = ProjectModule.objects.all().order_by('-created_at')
     
    permission_classes = [IsAuthenticated]   
    
    def perform_create(self, serializer):
        """ Set the created_by user when creating a new DepartmentType. """
        serializer.save(created_by=self.request.user.id)

    def perform_update(self, serializer):
        """ Set the updated_by user when updating a DepartmentType. """
        serializer.save(updated_by=self.request.user.id)
   
    @action(detail=False, methods=["GET"], name="DDL List")
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'project_id',
                openapi.IN_QUERY,
                description="project_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )     
    def ddl(self, request, *args, **kwargs): 
         
        project_id = request.query_params.get('project_id', None)
        print('project_id',project_id)      
         
        data_list = ProjectModule.objects.filter(project_id=project_id)
         
        
        filtered_data = [
            {
                'id': item.id,
                'name': item.title 
            }
            for item in data_list
        ]
        
        return Response(filtered_data)
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'project_id',
                openapi.IN_QUERY,
                description="project_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )     
    def list(self, request, *args, **kwargs): 
         
        project_id = request.query_params.get('project_id', None)
             
         
        if project_id:
            data_list = ProjectModule.objects.filter(project_id=project_id).select_related('project')
        else:
            data_list = ProjectModule.objects.all().select_related('project')
        print('data_list',data_list) 
        
        module_data=[]
        for module in data_list:
            module_data.append({
                "module_id": module.id,
                "module_title": module.title,
                "module_description": module.description,
                "active": module.active,
                "project_id": module.project.id,
                "project_name": module.project.project_name,  # assuming `name` field exists in Project
                "project_description": module.project.description,  # if applicable
            })
        # data_list_serializr = self.default_serializer_class(
        #     data_list, read_only=True, many=True
        # )  
        
        return Response(module_data)
class ProjectTasksViewSet(ListAndSerializerMixin, viewsets.ModelViewSet):
    
    serializer_class = ProjectTaskSerializer
    serializer_classes = {
        "update": ProjectTaskSerializer, # update
        "retrieve": ProjectTaskSerializer, "get item by id "
        "create": ProjectTaskSerializer, #save
        "list": ProjectTaskSerializer, ##"all objects list"
        # ... other actions
    }
    default_serializer_class = ProjectTaskSerializer
    queryset = ProjectTask.objects.all().order_by('-created_at')
    #parser_classes = [MultiPartParser, FormParser]
    
     
    permission_classes = [IsAuthenticated]   
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'attachments', openapi.IN_FORM,
                type=openapi.TYPE_FILE, description="Multiple files", required=False
            ),
        ]
    )
    # def create(self, request, *args, **kwargs):
    #     return super().create(request, *args, **kwargs)
    def perform_create(self, serializer):
        """ Set the created_by user when creating a new DepartmentType. """
        serializer.save(created_by=self.request.user.id)

    def perform_update(self, serializer):
        """ Set the updated_by user when updating a DepartmentType. """
        serializer.save(updated_by=self.request.user.id)
   
    @action(detail=False, methods=["GET"], name="DDL List")
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'module_id',
                openapi.IN_QUERY,
                description="module_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )     
    def ddl(self, request, *args, **kwargs): 
         
        module_id = request.query_params.get('module_id', None)
        print('project_id',module_id)      
         
        data_list = ProjectTask.objects.filter(module_id=module_id)
         
        
        filtered_data = [
            {
                'id': item.id,
                'name': item.title 
            }
            for item in data_list
        ]
        
        return Response(filtered_data)
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'module_id',
                openapi.IN_QUERY,
                description="module_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )     
    def list(self, request, *args, **kwargs): 
         
        module_id = request.query_params.get('module_id', None)
        print('project_id',module_id)      
         
        if module_id:
            data_list = ProjectTask.objects.filter(module_id=module_id).select_related('module')
        else:
            data_list = ProjectTask.objects.all().select_related('module')
         
        
        data_list_serializr = self.default_serializer_class(
            data_list, read_only=True, many=True
        )  
        
        return Response(data_list_serializr.data)
    
    def retrieve(self, request, *args, **kwargs):
        task = self.get_object()  # Get the instance by ID from URL
        serializer = self.get_serializer(task)

        # Customize the response as needed
        data = serializer.data
        data['assigned_member_ids'] = [user.id for user in task.assigned_members.all()]
        print(task.attachments)
        data['attachment_files'] = [attachment.file.url for attachment in task.attachments.all()]

        return Response(data)
    @action(detail=False, methods=["GET"], name="DDL List")
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'user_id',
                openapi.IN_QUERY,
                description="user_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )  
    def get_task_list_by_user(self, request):
        try:
            user_id = request.query_params.get('user_id', None)
             
        except JRPUser.DoesNotExist:
            return Response({"detail": "User not found."}, status=404)

        # Get Projects where user is a member
        # tasks = ProjectTask.objects.filter(
        #     assigned_members__id=700
        # )
        tasks = ProjectTask.objects.filter(
            assigned_members=user_id
        ).select_related('module__project')
        
        project_data = []

        for tasks_obj in tasks:
            task_data=ProjectTaskSerializer(tasks_obj) 

            project_data.append({
                "project_id": tasks_obj.module.project.id,
                "project_name": tasks_obj.module.project.project_name,
                "module_name": tasks_obj.module.title,
                "tasks": [
                    {
                        "task_data": task_data.data 
                    }
                     
                ]
            })

        return Response(project_data)
    @action(detail=False, methods=["GET"], name="DDL List")
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'project_id',
                openapi.IN_QUERY,
                description="user_id Query Param",
                type=openapi.TYPE_INTEGER,
             ),
             
        ],
    )  
    def get_task_list_by_project(self, request):
        try:
            project_id = request.query_params.get('project_id', None)
             
        except Project.DoesNotExist:
            return Response({"detail": "project_id not found."}, status=404)

        # Get Projects where user is a member
        # tasks = ProjectTask.objects.filter(
        #     assigned_members__id=700
        # )
        tasks = ProjectTask.objects.filter(
            module__project__id=project_id
        ).select_related('module__project')
        
        project_data = []

        for tasks_obj in tasks:
            task_data=ProjectTaskRetriveSerializer(tasks_obj) 

            project_data.append({
                "project_id": tasks_obj.module.project.id,
                "project_name": tasks_obj.module.project.project_name,
                "module_name": tasks_obj.module.title,
                "tasks": [
                    {
                        "task_data": task_data.data 
                    }
                     
                ]
            })

        return Response(project_data)
    from collections import defaultdict
    @action(detail=False, methods=["GET"], name="project_task_report List")
    
    @swagger_auto_schema(
        # query_serializer=MyQueryParamSerializer,
        manual_parameters=[
            openapi.Parameter(
                'status', #choices=[('new', 'New'), ('progress', 'In Progress'), ('done', 'Completed')], default='new')
                openapi.IN_QUERY,
                description="status Query Param",
                type=openapi.TYPE_STRING,
             ),
            openapi.Parameter(
                'filter_by', #choices=[('new', 'New'), ('progress', 'In Progress'), ('done', 'Completed')], default='new')
                openapi.IN_QUERY,
                description="filter_by Query Param (project,user,targer_date,priority)",
                type=openapi.TYPE_STRING,
             ),
            openapi.Parameter(
                'filter_value', #choices=[('new', 'New'), ('progress', 'In Progress'), ('done', 'Completed')], default='new')
                openapi.IN_QUERY,
                description="filter_value Query Param",
                type=openapi.TYPE_STRING,
             ),
             
        ],
    )
    def project_task_report(self, request, *args, **kwargs):
        #status = models.CharField(max_length=20, choices=[('new', 'New'), ('progress', 'In Progress'), ('done', 'Completed')], default='new')
        status_filter = request.query_params.get("status")
        group_by = request.query_params.get("filter_by")
        filter_value = request.query_params.get("filter_value")
        print(status_filter)

        if status_filter not in ["In Progress", "Completed"]:
            return Response({"error": "Invalid status"}, status=status.HTTP_400_BAD_REQUEST)

        queryset = ProjectTask.objects.all()

        # Filter by task status
        if status_filter == "In Progress":
            queryset = queryset.exclude(status="done")
        elif status_filter == "Completed":
            queryset = queryset.filter(status="done")

        # Apply filter_value based on group_by
        if group_by == "project" and filter_value:
            queryset = queryset.filter(module__project__project_name__iexact=filter_value)
            group_field = "module__project__project_name"

        elif group_by == "user" and filter_value:
            queryset = queryset.filter(assigned_members__first_name__iexact=filter_value)
            group_field = "assigned_members__email"

        elif group_by == "target_date":
            group_field = "end_date"

        elif group_by == "priority":
            group_field = "priority"

        else:
            return Response({"error": "Invalid or missing group_by"}, status=status.HTTP_400_BAD_REQUEST)

        # Grouping and counting
        #print(queryset)
        grouped = defaultdict(list)

        for task in queryset.select_related('module__project').prefetch_related('assigned_members'):
            for member in task.assigned_members.all():
                grouped[member.first_name].append({
                    "project":task.module.project.project_name,
                    "module": task.module.title,  # or task.module.module_name
                    "title" : task.title,
                    "description": task.description,
                    "priority": task.priority,
                    "target_date": task.end_date.strftime('%d-%m-%Y') if task.end_date else None
                })

        # Convert grouped dict to desired list format
        response_data = [{"name": name, "tasks": task_list} for name, task_list in grouped.items()]

        return Response(response_data)
        report_data = queryset.values(group_field) #.annotate(task_count=Count("id"))

        return Response(report_data)