from rest_framework.response import Response
from django.shortcuts import get_list_or_404,get_object_or_404
from rest_framework.views import APIView
from rest_framework import generics,status
from authentication.models import User,Role
from user.models import UserInfo
from rest_framework_simplejwt.views import TokenObtainPairView
from django.core.mail import EmailMessage
from quotation.models import Order,Order_Item, Technician_Assigned_Order_Item,Order,Technician_Comment,Invoice
# from product.models import Product
from service.models import Service,Service_Request_image,Question,Chat
from rest_framework.exceptions import PermissionDenied, NotFound, ValidationError
from rest_framework_simplejwt.backends import TokenBackend
from django.db.models import Q
from technician.models import Job_Time,CallDetail,Notification,Job_Interval_Time
from django.utils import timezone
from datetime import datetime
from datetime import date
from customer.models import Customer
from rest_framework.permissions import IsAuthenticated
from django.contrib.auth import login
from authentication.models import User
from django.contrib.auth.hashers import make_password
from django.db.models import Q ,  Exists, OuterRef
from django.core.mail import send_mail
from django.conf import settings
from django.db import transaction
from django.http import FileResponse
import base64
import random
import string
from django.db.models import Prefetch
import json
from customer.models import Customer,Customer_Info
from service.models import Heading,SubHeading,Question,Answer,Parts_Request,ChatImage,Service_Signature,Accepted_Image
from django.core.exceptions import ObjectDoesNotExist
from django.core.mail import EmailMessage
from product.models import Product
from django.shortcuts import render
from django.template.loader import render_to_string
from django.http import HttpResponse
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.pagination import PageNumberPagination            
from leads.models import Lead,Leadnote,Lead_Quote,LeadAttachmentPhotos,LeadAttachmentFiles,ProductUserManualPDFSent,ProductSpecificationPDFSent
from weasyprint import HTML
from django.template.loader import get_template
from io import BytesIO
from xhtml2pdf import pisa
from technician.firebaseManager import sendPush
from fcm_django.models import FCMDevice
from django.http import JsonResponse
from itertools import zip_longest
from rest_framework import status as drf_status
from django.utils.dateparse import parse_date
from datetime import datetime,timedelta
from django.db.models import Max,Min, F, Case, When, DateTimeField, Q
from django.contrib.auth import get_user_model
import os
User = get_user_model()

from technician.technician_api.serializers import (
    NoteActionSerializer,
    LeadAttachmentPhotosSerializer,
    LeadAttachmentFilesSerializer,
    LeadQuoteListSerializer,
    UserSerializer,
    CustomerSerializer,
    LeadNoteCreateSerializer,
    ProductSerializer,
    LeadSerializer,
    LeadSerializerWithoutPagination,
    TechnicianTokenSerializer,
    ForgotPasswordSerializer,
    PasswordResetSerializer,
    AssignedOrderSerializer,
    AssignedItemSerializer,
    AssignedJobsSerializer,
    JobTimeSerializer,
    JobStartStopSerializer,
    JobsViewTechnicianSerializer,
    TechnicianUpdateInstallationStatusSerializer,
    TechnicianCommentSerializer,
    CallDetailSerializer,
    CallDetailPostSerializer,
    CustomerOrderSerializer,
    CustomerOrderItemSerializer,
    CustomerWarrantyOrderSerializer,
    # CustomerServiceSerializer,
    TechnicianServiceAssignedOrderItemSerializer,
    CustomerServiceOrderSerializer,
    # ServiceSerializer,
    AssignedOrderItemDetailSerializer,
    ServiceRequestImageSerializer,
    NotificationSerializer,
    QuestionSerializer,
    QuestionAnsSerializer,
    AnswerSerializer,
    PartsRequestSerializer,
    ChatSerializer,
    ChatImageSerializer ,
    ServiceSignatureSerializer,
    TechnicianAssignedOrderItemSerializer,
    ActivitySerializer,
    CustomerInvoiceSerializer,
    Accepted_ImageSerializer,
    CustomerAnswerSerializer,
    # JobTimerSerializer,
    JobIntervalTimeSerializer,
    OrderItemSerializer,
    ActivityLogSerializer,
#     HeadingSerializer,
#     SubheadingSerializer,
    )

def get_context(serializer):
    context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer.data
    }
    return Response(context,status=status.HTTP_200_OK)

def get_exception_context(exception):
    context ={
            "status": status.HTTP_400_BAD_REQUEST,
            "success": False,
            "response": str(exception)
    }
    return Response(context,status=status.HTTP_400_BAD_REQUEST)
    
class RefreshFCMTokenAPI(APIView):
    def post(self,request,*args,**kwargs):
        data = request.data
        print(data)
        print(request.META.get('HTTP_AUTHORIZATION', " "))
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        get_logged_in_user = valid_data['user_id']

        print(get_logged_in_user)
        user = User.objects.get(id=get_logged_in_user)
        
        fcm_registration_token = data.get('fcm_registration_token',None)
        print(fcm_registration_token)
        device_type = data.get('device_type',None)
        device_id = data.get('device_id',None)
        device_name = data.get('device_name',None)
        if fcm_registration_token is None:
            context = {
                "status":status.HTTP_400_BAD_REQUEST,
                "success":False,
                "erros_status":True,
                "response":"fcm_registration_token field may not be empty!"
            }
            return Response(context,status=status.HTTP_400_BAD_REQUEST)
        if device_type is None:
            context = {
                "status":status.HTTP_400_BAD_REQUEST,
                "success":False,
                "erros_status":True,
                "response":"device_type field may not be empty!"
            }
            return Response(context,status=status.HTTP_400_BAD_REQUEST)
        fcm_device_exists = FCMDevice.objects.filter(user_id=user.id,registration_id=fcm_registration_token)
        print(fcm_device_exists)
        print(fcm_device_exists)
        if fcm_device_exists:
            print(fcm_registration_token)
            print("deepak")
            # print(json.loads(fcm_registration_token))
            get_fcm_device = FCMDevice.objects.get(user_id=user.id,registration_id=fcm_registration_token)
            get_fcm_device.registration_id = fcm_registration_token
            get_fcm_device.type = device_type
            get_fcm_device.name = device_name
            get_fcm_device.device_id = device_id
            get_fcm_device.active = True
            get_fcm_device.save()
        else:
            fcm_instance = FCMDevice(
            registration_id  = fcm_registration_token,
            type  = device_type,
            name = device_name,
            device_id = device_id,
            user_id = user.id,
            # active = True
            )
            
            # print(fcm_instance.__dir__())
            fcm_instance.save()
        context = {
            "detail": "Successfully refreshed token.",
            "status": status.HTTP_200_OK,
            "success": True,
            "erros_status": False,
            }
        return Response(context, status=status.HTTP_200_OK)
        
class TechnicianMultiRoleLoginAPI(TokenObtainPairView):
    serializer_class = TechnicianTokenSerializer
    def post(self, request, *args, **kwargs):
        data = request.data
        print(data)
        email = data.get('email')
        password = data.get('password')
        fcm_registration_token = data.get('fcm_registration_token',None)
        print(fcm_registration_token)
        print(email)
        print(password)
        device_type = data.get('device_type',None)
        device_id = data.get('device_id',None)
        device_name = data.get('device_name',None)
        if fcm_registration_token is None:
            context = {
                "status":status.HTTP_400_BAD_REQUEST,
                "success":False,
                "erros_status":True,
                "response":"fcm_registration_token field may not be empty!"
            }
            return Response(context,status=status.HTTP_400_BAD_REQUEST)
        if device_type is None:
            context = {
                "status":status.HTTP_400_BAD_REQUEST,
                "success":False,
                "erros_status":True,
                "response":"device_type field may not be empty!"
            }
            return Response(context,status=status.HTTP_400_BAD_REQUEST)
        # if User.objects.filter(email__exact =email,is_active=False):
        #     context = {
        #         "status":status.HTTP_400_BAD_REQUEST,
        #         "success":False,
        #         "erros_status":True,
        #         "response":"'Your account is inactive."
        #     }
        #     return Response(context,status=status.HTTP_400_BAD_REQUEST)
        check_user_email = User.objects.filter(email__exact = email,is_active=True)
        if check_user_email.exists():
            from django.contrib.auth import authenticate
            user = authenticate(email = email, password = password)
            print(user)
            role_info = []
            if user is not None:
                if user.role.filter(id__in='3').exists() or user.role.filter(id__in='4').exists()  or user.role.filter(id__in='2').exists():
                    if  user.role.filter(id__in='3'):
                        first_name = user.userinfo.first_name.capitalize()
                        last_name = user.userinfo.last_name.capitalize()
                        username = f"{first_name} {last_name}"
                        job_chat=user.job_chat
                        is_primary=False
                        role_info.append(3)
                        role_id=3
                    if  user.role.filter(id__in='4'):
                        from customer.models import Customer
                        if Customer.objects.filter(email=user.email):
                            customer = Customer.objects.get(email=user.email)
                            if customer.company_name:
                                company_name=customer.company_name.capitalize()
                                is_primary=customer.is_primary

                                username=f"{company_name}"
                                job_chat=user.job_chat
                            else:
                                first_name = customer.first_name.capitalize()
                                last_name = customer.last_name.capitalize()
                                is_primary=customer.is_primary
                                username = f"{first_name} {last_name}"
                                job_chat=user.job_chat
                            role_id = 4
                            role_info.append(4)
                        else:
                            cust = Customer_Info.objects.get(email=user.email)
                            first_name = cust.first_name.capitalize()
                            last_name = cust.last_name.capitalize()
                            is_primary=cust.is_primary
                            username = f"{first_name} {last_name}"
                            job_chat=user.job_chat
                            
                            # if cust.customer.company_name:
                            #     company_name=customer.company_name.capitalize()
                            #     is_primary=cust.is_primary

                            #     username=f"{company_name}"
                            # else:
                            #     first_name = cust.customer.first_name.capitalize()
                            #     last_name = cust.customer.last_name.capitalize()
                            #     is_primary=cust.is_primary
                            #     username = f"{first_name} {last_name}"
                                
                            role_info.append(4)
                            role_id = 4
                    if user.role.filter(id__in='2'):
                        first_name = user.userinfo.first_name.capitalize()
                        last_name = user.userinfo.last_name.capitalize()
                        username = f"{first_name} {last_name}"
                        job_chat=user.job_chat
                        is_primary=False
                        role_info.append(2)
                        role_id=2
                    fcm_device_exists = FCMDevice.objects.filter(user_id=user.id,registration_id=fcm_registration_token)
                    print(fcm_device_exists)
                    print(fcm_device_exists)
                    if fcm_device_exists:
                        print(fcm_registration_token)
                        print("deepak")
                        # print(json.loads(fcm_registration_token))
                        get_fcm_device = FCMDevice.objects.get(user_id=user.id,registration_id=fcm_registration_token)
                        get_fcm_device.registration_id = fcm_registration_token
                        get_fcm_device.type = device_type
                        get_fcm_device.name = device_name
                        get_fcm_device.device_id = device_id
                        get_fcm_device.active = True
                        get_fcm_device.save()
                    else:
                        fcm_instance = FCMDevice(
                        registration_id  = fcm_registration_token,
                        type  = device_type,
                        name = device_name,
                        device_id = device_id,
                        user_id = user.id,
                        # active = True
                        )
                        
                        # print(fcm_instance.__dir__())
                        fcm_instance.save()
                    if len(role_info) == 1:
                        role_ids = role_info[0]
                        multirole = 0
                    else:
                        role_ids = role_info  # list of roles
                        multirole = 1
                    token = self.get_serializer().get_token(user)
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": True,
                        "erros_status": False,
                        "response": "Successfully Logged In!",
                        "refresh": str(token),
                        "access": str(token.access_token),
                        "username": username,
                        "job_chat": job_chat,
                        "useid": user.id,
                        "reset_password": user.reset_password,
                        "email": user.email,
                        "is_primary":is_primary,
                        "role": int(role_id),
                        "roles": role_ids,
                        "multirole":multirole
                        #"roles":role_info
                    }
                    return Response(context, status=status.HTTP_200_OK)
                else:
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": False,
                        "erros_status": True,
                        "response": "You are not authorized to access!"
                    }
                    return Response(context, status=status.HTTP_200_OK)
            else:
                context = {
                    "status":status.HTTP_200_OK,
                    "success":False,
                    "erros_status":True,
                    "response":"Incorrect Password!"
                }
                return Response(context,status=status.HTTP_200_OK)
        else:
            context = {
                "status":status.HTTP_200_OK,
                "success":False,
                "erros_status":True,
                "response":"Email Address Does Not Exist."
            }
            return Response(context, status=status.HTTP_200_OK)
            
class TechnicianLogoutAPI(APIView):
    def post(self, request, *args, **kwargs):
        try:
            # user=request.data["user_id"]
            data = request.data
            fcm_registration_token = data.get('fcm_registration_token',None)
            fcm_device_exists = FCMDevice.objects.filter(registration_id=fcm_registration_token,active = True)
            if fcm_device_exists:
                # Deactivate the FCM device
                fcm_device = FCMDevice.objects.filter(registration_id=fcm_registration_token,active = True)
                for f in fcm_device:
                    f.active = False
                    f.save()
                context = {
                    "detail": "Successfully logged out.",
                    "status": status.HTTP_200_OK,
                    "success": True,
                    "erros_status": False,
                }
                return Response(context, status=status.HTTP_200_OK)
            else:
                context = {
                    "detail": "Successfully logged out.",
                    "status": status.HTTP_200_OK,
                    "success": True,
                    "erros_status": False,
                }
                return Response(context, status=status.HTTP_200_OK)
        except Exception as exception:
            return get_exception_context(exception)

class AssignedOrderListAPI(APIView):
    authentication_classes = []

    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            
            # queryset = Technician_Assigned_Order_Item.objects.filter(Q(technician=get_logged_in_user, order_item__installation_complete=False) | Q(technician=get_logged_in_user, service__service_completed=False))
            queryset = Technician_Assigned_Order_Item.objects.filter((Q(technician=get_logged_in_user)| Q(secondary_technician=get_logged_in_user)) & ( Q(order_item__installation_complete=False) | Q(service__service_completed=False) ))
            serializer = AssignedOrderSerializer(queryset, many=True)
            return get_context(serializer)
        
        except Exception as exception:
            return get_exception_context(exception)
      
class AssignedItemListAPI(APIView):
    authentication_classes = []
    def get(self, request,order_id, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            order= Order.objects.get(id=order_id)
          
            # queryset = Technician_Assigned_Order_Item.objects.filter(Q(order_item__order=order, technician=get_logged_in_user, order_item__installation_complete=False) |Q(order_item__order=order, technician=get_logged_in_user, service__service_completed=False))
            queryset = Technician_Assigned_Order_Item.objects.filter((Q(order_item__order=order, technician=get_logged_in_user) | Q(order_item__order=order, secondary_technician=get_logged_in_user) ) & ~Q(working_status=3))
            
            serializer = AssignedItemSerializer(queryset, many=True)
            return get_context(serializer)
        
        except Exception as exception:
            return get_exception_context(exception)

class ForgotPasswordAPIView(APIView):
    authentication_classes = []
    def post(self, request):
        try:
            serializer = ForgotPasswordSerializer(data=request.data)
            if serializer.is_valid():
                email = serializer.validated_data['email']
                user = User.objects.filter(email=email).first()

                if user:
                    # Generate a random password
                    new_password = ''.join(random.choices(string.ascii_letters + string.digits, k=12))

                    # Update the user's password
                    user.password = make_password(new_password)
                    user.reset_password=1
                    user.save()

                    # Compose the password reset email
                    subject = 'New Password'
                    message = f'Your new password is: {new_password}'
                    from_email = settings.FROM_EMAIL
                    recipient_list = [email]

                    # Send the email
                    send_mail(subject, message, from_email, recipient_list)
                    
                    context = {
                    "status":status.HTTP_200_OK,
                    "success":True,
                    'message':'New password sent to your email.'
                    }

                    return Response(context, status=status.HTTP_200_OK)
                else:

                    context={
                        "status":status.HTTP_200_OK,
                        "success":True,
                        'message': 'Email address does not exist.'
                        }

                    return Response(context, status=status.HTTP_200_OK)
            else:
                context = {
                        'status': status.HTTP_400_BAD_REQUEST,
                        'success':False,
                        'response': serializer.errors
                    }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)
        except Exception as exception:
            return get_exception_context(exception)
            
class ResetPasswordAPIView(generics.UpdateAPIView):
    authentication_classes = []
    serializer_class = PasswordResetSerializer
    def update(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']

            print(get_logged_in_user)

            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            
            new_password = serializer.validated_data['new_password']
            confirm_password = serializer.validated_data['confirm_password']

            if new_password and confirm_password and new_password != confirm_password:
                error_message = "New password and confirm password do not match."
                return Response({"status": 200, "success": False, "response": error_message}, status=status.HTTP_200_OK)
            
            user = User.objects.get(id=get_logged_in_user)
            if user:
                user.set_password(new_password)
                user.reset_password=0
                user.save()

                login(request, user)  
                context = {
                        "status":status.HTTP_200_OK,
                        "success":True,
                        'message': 'Password reset successfully.'
                        }
                return Response(context, status=status.HTTP_200_OK)
            else:
                context={
                        "status":status.HTTP_200_OK,
                        "success":False,
                        'error': 'User not found.'
                        }
                return Response(context, status=status.HTTP_200_OK)
        except Exception as exception:
            return get_exception_context(exception)

class CustomPagination(PageNumberPagination):
    page_size = 50
    page_size_query_param = 'page_size'
    max_page_size = 100  
    
class AssignedNewJobsListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            queryset = Technician_Assigned_Order_Item.objects.filter((Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)) & Q(job_completed=False) & Q(view_by_technician=False) & Q(deleted_at__isnull=True)).order_by('installation_date')
            
            page = self.request.GET.get('page', 1)
            
            print("fff",page)
            # Pagination
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            
            user = User.objects.get(id=get_logged_in_user)
            serializer_data = AssignedJobsSerializer(paginated_queryset, many=True,context={'user': user})
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
                    
            
           
        except Exception as exception:
            return get_exception_context(exception)    

class AssignedChatJobsListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            print('user_id',get_logged_in_user)
            user = User.objects.get(id=get_logged_in_user)
            if user:
                if user.job_chat == 1:
                    # queryset = Technician_Assigned_Order_Item.objects.filter( Q(job_completed=False)  & Q(deleted_at__isnull=True)).order_by('installation_date')
                    queryset = (
                        Technician_Assigned_Order_Item.objects
                        .filter(
                            Q(job_completed=False),
                            Q(deleted_at__isnull=True)
                        )
                        .annotate(
                            last_msg_time=Max('chat_set__created_at')  # latest message for each job
                        )
                        .order_by('-last_msg_time')  # newest chat on top
                    )
                else:
                    context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Access Denied.'
                    }
                    return Response(context, status=status.HTTP_200_OK)
            else:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Access Denied.'
                    }
                return Response(context, status=status.HTTP_200_OK)
            
            page = self.request.GET.get('page', 1)
            
            print("fff",page)
            # Pagination
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            
            
            serializer_data = AssignedJobsSerializer(paginated_queryset, many=True,context={'user': user})
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
                    
            
           
        except Exception as exception:
            return get_exception_context(exception)    
    def post(self, request):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            data=request.data
            job_id=request.data.get('job_id')
            # print(get_logged_in_user)
            if data and get_logged_in_user:
                from service.models import Chat,ChatImage,ChatRead

                job = Technician_Assigned_Order_Item.objects.get(id=job_id)
                chats = Chat.objects.filter(job=job).exclude(sender_id=get_logged_in_user)
                for chat in chats:
                    ChatRead.objects.get_or_create(chat=chat, user_id=get_logged_in_user)
                context = {
                "status":status.HTTP_200_OK,
                "success":True,
                'message':'Marked as read.'
                }

                return Response(context, status=status.HTTP_200_OK)
           
            else:
                context = {
                        'status': status.HTTP_400_BAD_REQUEST,
                        'success':False,
                        'response': serializer.errors
                    }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)
        except Exception as exception:
            return get_exception_context(exception)        
            
class AssignedTodayJobsListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            
            today_date = date.today()
            print(today_date)
            queryset = Technician_Assigned_Order_Item.objects.filter((Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)) & Q(job_completed=False) & Q(view_by_technician=True) & Q(installation_date=today_date) & Q(deleted_at__isnull=True)).order_by('installation_time')
            
            page = self.request.GET.get('page', 1)
            
            print("fff",page)
            # Pagination
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            print('before',paginated_queryset)
            user = User.objects.get(id=get_logged_in_user)
            serializer_data = AssignedJobsSerializer(paginated_queryset, many=True,context={'user': user})
            print('after')
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
           
        
        except Exception as exception:
            return get_exception_context(exception)  
            
# class AssignedAllOtherJobsListAPI(APIView):
#     authentication_classes = []
#     pagination_class = CustomPagination
#     def get(self, request, *args, **kwargs):
#         try:
#             token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
#             valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
#             get_logged_in_user = valid_data['user_id']
#             today_date = date.today()
#             queryset = Technician_Assigned_Order_Item.objects.filter(Q(technician=get_logged_in_user) & Q(job_completed=False) & Q(view_by_technician=True)).exclude(installation_date=today_date).order_by('installation_date')
            
#             page = self.request.GET.get('page', 1)
            
#             print("fff",page)
#             # Pagination
#             paginator = self.pagination_class()
#             paginated_queryset = paginator.paginate_queryset(queryset, request)
#             next_page = paginator.get_next_link() or ''
#             previous_page = paginator.get_previous_link() or ''
#             total_pages = paginator.page.paginator.num_pages or ''
            
#             serializer_data = AssignedJobsSerializer(paginated_queryset, many=True)
#             serializer = {
#                 'results': serializer_data.data,  # Use the serialized data here
#                 'next': next_page,
#                 'previous': previous_page,
#                 'total_pages': total_pages,
#             }
            
#             context ={
#             "status": status.HTTP_200_OK,
#             "success": True,
#             "response": serializer
#             }
#             return Response(context,status=status.HTTP_200_OK)
            
#         except Exception as exception:
#             return get_exception_context(exception)  
class AssignedAllServiceJobsListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            today_date = date.today()
            queryset = Technician_Assigned_Order_Item.objects.filter((Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)) & Q(job_completed=False) & Q(view_by_technician=True) & Q(job_type=2)  & Q(deleted_at__isnull=True)).exclude(installation_date=today_date).order_by('installation_date')
            
            page = self.request.GET.get('page', 1)
            
            print("fff",page)
            # Pagination
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            user = User.objects.get(id=get_logged_in_user)
            serializer_data = AssignedJobsSerializer(paginated_queryset, many=True,context={'user': user})
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
            
        except Exception as exception:
            return get_exception_context(exception)  
            
class AssignedAllInstallJobsListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            today_date = date.today()
            queryset = Technician_Assigned_Order_Item.objects.filter((Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)) & Q(job_completed=False) & Q(view_by_technician=True) & Q(job_type=1)  & Q(deleted_at__isnull=True) ).exclude(installation_date=today_date).order_by('installation_date')
            
            page = self.request.GET.get('page', 1)
            
            print("fff",page)
            # Pagination
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            user = User.objects.get(id=get_logged_in_user)
            serializer_data = AssignedJobsSerializer(paginated_queryset, many=True,context={'user': user})
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
            
        except Exception as exception:
            return get_exception_context(exception)  
            
class AssignedCompletedJobsListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            queryset = Technician_Assigned_Order_Item.objects.filter((Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)) & Q(job_completed=True)  & Q(deleted_at__isnull=True)).order_by('-job_complete_datetime')
            
            page = self.request.GET.get('page', 1)
            
            print("fff",page)
            # Pagination
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            
            print(get_logged_in_user)
            user = User.objects.get(id=get_logged_in_user)
            serializer_data = AssignedJobsSerializer(paginated_queryset, many=True,context={'user': user})
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
                    
            
           
        except Exception as exception:
            return get_exception_context(exception)                
class JobsdetailsAPI(APIView):
    def get(self, request, job_id, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            print(get_logged_in_user)
            print(job_id)
            
            user = User.objects.get(id=get_logged_in_user)
            assigned_order_item = Technician_Assigned_Order_Item.objects.filter(id=job_id)
                
                
            # serializer = CallDetailSerializer(call_details, many=True)
            
            job_details = AssignedJobsSerializer(assigned_order_item,  many=True,context={'user': user})
            
            
            
            serializer = {
                    'job_details': job_details.data,
                    
                }
            
            # Adjust this based on your models
            context = {
                "status": status.HTTP_200_OK,
                "success": True,
                'message': 'Job details retrieved successfully.',
                'response': serializer
                
               
            }

            return Response(context, status=status.HTTP_200_OK)

        except Exception as exception:
            return get_exception_context(exception)    
class AssignedJobsListAPI(APIView):
    authentication_classes = []

    def post(self, request, job_id, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = User.objects.get(id=valid_data['user_id'])  # Ensure you get a User instance

            
         
            # assigned_orderitem = Technician_Assigned_Order_Item.objects.get(id=job_id,technician=get_logged_in_user,)
            assigned_orderitem = Technician_Assigned_Order_Item.objects.get(Q(id=job_id) & (Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)))
            order_item=Order_Item.objects.get(id=assigned_orderitem.order_item.id)

         
            serializer = TechnicianCommentSerializer(data=request.data)

            if serializer.is_valid():
                installation_date = serializer.validated_data.get('installation_date')
                installation_time = serializer.validated_data.get('installation_time')
                comment = serializer.validated_data.get('comment')

                if installation_date and comment:
                    # Use serializer.save() to create the Technician_Comment instance
                    serializer.save(
                        technician_assigend_order_item=assigned_orderitem,
                        installation_date=installation_date,
                        installation_time=installation_time,
                        comment=comment
                    )

                    # Update the assigned_orderitem installation_date
                    assigned_orderitem.installation_date = installation_date
                    assigned_orderitem.installation_time = installation_time
                    # assigned_orderitem.working_status = 1  #Accepted Installation
                    
                    # assigned_orderitem.job_status=0
                    assigned_orderitem.save()
                    
                    
                    # order_item.status=5
                    # order_item.save()
                    
                    # try:
                    #     unique_registration_ids = set()
                    #     get_registration_token = FCMDevice.objects.filter(user_id=assigned_orderitem.order_item.order.invoice.customer.user.id, active=True)
                    #     for i in get_registration_token:
                    #         if i.registration_id not in unique_registration_ids:
                    #             sendPush('Job Reschedule Notification',f'EXCITECH Australia-Job Reschedule For Job Id-{assigned_orderitem.id}',[i.registration_id])
                    #             unique_registration_ids.add(i.registration_id)
                    # except FCMDevice.DoesNotExist:
                    #     print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    # except Exception as e:
                    #     print(f"Error sending push notification: {e}")
                
                    
                    
                    
                    
                    context = {
                        'status': status.HTTP_201_CREATED,
                        'success': True,
                        'response': 'Installation date and comment Update successfully.',
                    }
                    return Response(context, status=status.HTTP_201_CREATED)
            else:
                context = {
                    'status': status.HTTP_400_BAD_REQUEST,
                    'success': False,
                    'response': serializer.errors
                }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)        
            

        except Exception as exception:
            return get_exception_context(exception)
            
class JobsViewByTechnicianAPIView(APIView):
    authentication_classes = []
    def put(self, request, job_id):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
         
            # assigned_order_item=Technician_Assigned_Order_Item.objects.get(id=job_id,technician=get_logged_in_user)
            assigned_order_item = Technician_Assigned_Order_Item.objects.get(Q(id=job_id) & (Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)))
            order_item = Order_Item.objects.get(id=assigned_order_item.order_item.id)
            serializer = JobsViewTechnicianSerializer(assigned_order_item, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                order_item.view_by_technician=serializer.validated_data['view_by_technician']
                # assigned_order_item.working_status=
                order_item.save()
                if assigned_order_item.job_type == 1:
                    assigned_order_item.working_status = 1  #Accepted Installation
                if assigned_order_item.job_type == 2:
                    assigned_order_item.working_status = 5   #Accepted Service 
                assigned_order_item.save()
                
                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response':serializer.data,
                }
                return Response(context, status=status.HTTP_200_OK)
            else:
                context = {
                    'status': status.HTTP_400_BAD_REQUEST,
                    'success': False,
                    'response': serializer.errors
                }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)
        except Exception as exception:
            return get_exception_context(exception)   

class JobStartStopAPIView(APIView):

    authentication_classes = []
    def post(self, request, job_id):
        # try:
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        get_logged_in_user = valid_data['user_id']
        # assigned_order_item=Technician_Assigned_Order_Item.objects.get(id=job_id,technician=get_logged_in_user)
        assigned_order_item = Technician_Assigned_Order_Item.objects.get(Q(id=job_id) & (Q(technician=get_logged_in_user) | Q(secondary_technician=get_logged_in_user)))
        
        order_item = Order_Item.objects.get(id=assigned_order_item.order_item.id)
        
        
        serializer = JobStartStopSerializer(data=request.data)
        if serializer.is_valid():
            action = serializer.validated_data['action']
            if action == 'start':
                # Check if start_time is set for the given job_id
                existing_job = Job_Time.objects.filter(
                    assigned_order_item=job_id,
                    start_time__isnull=False,
                    stop_time__isnull=True,
                    technician_id=get_logged_in_user
                ).first()
                
                
                existing_job1 = Job_Time.objects.filter(
                    assigned_order_item=job_id,
                    technician_id=get_logged_in_user
                    
                ).first()

                if existing_job:
                    # Stop the existing job
                    existing_job.stop_time = timezone.now()
                    existing_job.save()
    
                    new_job = Job_Time.objects.create(
                        start_time=timezone.now(),
                        start_from_distance=request.data.get('start_from_distance'),
                        assigned_order_item_id=job_id,
                        technician_id=get_logged_in_user,
                    )
                    
                    print("gopal chandrawanshi")
                    
                    
                    assigned_order_item.job_status=1
                    
                    if assigned_order_item.job_type == 1:
                        assigned_order_item.working_status=2
                    if assigned_order_item.job_type == 2:
                        assigned_order_item.working_status=6
                    
                    
                    
                    assigned_order_item.save()
                    order_item.status=6  
                    order_item.save()
                    message="Job Start successfully."

                    
                    # try:
                    #     unique_registration_ids = set()
                    #     get_registration_token = FCMDevice.objects.filter(user_id=assigned_order_item.order_item.order.invoice.customer.user.id, active=True)
                    #     for i in get_registration_token:
                    #         if i.registration_id not in unique_registration_ids:
                    #             sendPush(f'EXCITECH Australia - Job #{assigned_order_item.id} Started',f'Job #{assigned_order_item.id} Started',[i.registration_id]) 
                    #             unique_registration_ids.add(i.registration_id)
                    # except FCMDevice.DoesNotExist:
                    #     print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    # except Exception as e:
                    #     print(f"Error sending push notification: {e}")
                    context = {
                        'status': status.HTTP_200_OK,
                        'success': True,
                        'response': message,
                    }
                    return Response(context, status=status.HTTP_200_OK)
                    
                elif existing_job1:
                    new_job = Job_Time.objects.create(
                        start_time=timezone.now(),
                        start_from_distance=request.data.get('start_from_distance'),
                        assigned_order_item_id=job_id,
                        technician_id=get_logged_in_user,
                    )
                    
                    print("deepak chandrawanshi",order_item.status)
                    # assigned_order_item.job_status=1
                    if order_item.status == '3':
                       
                        assigned_order_item.job_status=1
                        if assigned_order_item.job_type==1:
                            assigned_order_item.working_status=2
                        if assigned_order_item.job_type==2:
                            assigned_order_item.working_status=6
                        
                        assigned_order_item.save()
                        order_item.status=6  
                        order_item.save()
                    message="Job Start successfully."
                    

                    # try:
                    #     unique_registration_ids = set()
                    #     get_registration_token = FCMDevice.objects.filter(user_id=assigned_order_item.order_item.order.invoice.customer.user.id, active=True)
                    #     for i in get_registration_token:
                    #         if i.registration_id not in unique_registration_ids:
                    #             sendPush(f'EXCITECH Australia - Job #{assigned_order_item.id} Started',f'Job #{assigned_order_item.id} Started',[i.registration_id])     
                    #             unique_registration_ids.add(i.registration_id)
                    # except FCMDevice.DoesNotExist:
                    #     print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    # except Exception as e:
                    #     print(f"Error sending push notification: {e}")
                

                    context = {
                        'status': status.HTTP_200_OK,
                        'success': True,
                        'response': message,
                    }
                    return Response(context, status=status.HTTP_200_OK)
                    
                    
    
                # If there is no existing job in progress, start a new job
                else:
                    new_job = Job_Time.objects.create(
                        start_time=timezone.now(),
                        start_from_distance=request.data.get('start_from_distance'),
                        assigned_order_item_id=job_id,
                        technician_id=get_logged_in_user,
                    )
                    
                    assigned_order_item.job_status=1
                    if assigned_order_item.job_type==1:
                        assigned_order_item.working_status=2
                    if assigned_order_item.job_type==2:
                        assigned_order_item.working_status=6
                    
                    assigned_order_item.save()
                    
                    order_item.status=6     #  in Progress
                    order_item.save()
                    message="New job started successfully."
                    

                    # try:
                    #     unique_registration_ids = set()
                    #     get_registration_token = FCMDevice.objects.filter(user_id=assigned_order_item.order_item.order.invoice.customer.user.id, active=True)
                    #     for i in get_registration_token:
                    #         if i.registration_id not in unique_registration_ids:
                    #             sendPush(f'EXCITECH Australia - Job #{assigned_order_item.id} Started',f'Job #{assigned_order_item.id} Started',[i.registration_id])     
                    #             unique_registration_ids.add(i.registration_id)
                    # except FCMDevice.DoesNotExist:
                    #     print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    # except Exception as e:
                    #     print(f"Error sending push notification: {e}")
                    
                    
                    context = {
                        'status': status.HTTP_201_CREATED,
                        'success': True,
                        'response': message,
                    }
                    return Response(context, status=status.HTTP_201_CREATED)

        else:
            context = {
                'status': status.HTTP_400_BAD_REQUEST,
                'success': False,
                'response': serializer.errors
            }
            return Response(context, status=status.HTTP_400_BAD_REQUEST)        

class TechnicianUpdateInstallationStatusAPIView(APIView):
    authentication_classes = []
    def put(self, request, order_item_id):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']

            order_item = Order_Item.objects.get(id=order_item_id)
            
            if not order_item:
                context = {
                            "status": status.HTTP_200_OK,
                            "success": False,
                            'message': 'No items found..'
                        }
                return Response(context, status=status.HTTP_200_OK)

          
            serializer = TechnicianUpdateInstallationStatusSerializer(order_item, data=request.data, partial=True)
            
            if serializer.is_valid():
                
                serializer.save()
                order_item.status=7
                order_item.save()

                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response': 'Items Installed Successfully .',
                }
                return Response(context, status=status.HTTP_200_OK)
                
            else:
                context = {
                    'status': status.HTTP_400_BAD_REQUEST,
                    'success': False,
                    'response': serializer.errors
                }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)

        except Order_Item.DoesNotExist:
            return Response({'status': status.HTTP_200_OK, 'detail': 'Order item not found.'}, status=status.HTTP_200_OK)
        except PermissionDenied as e:
            return Response({'status': status.HTTP_403_FORBIDDEN, 'detail': str(e)}, status=status.HTTP_403_FORBIDDEN)
        except Exception as exception:
            return get_exception_context(exception) 
            
class NotificationListAPIView(APIView):
    authentication_classes = []
    print('1005')
    def get(self, request, *args, **kwargs):
        print('get')
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            notifications = Notification.objects.filter(technician=get_logged_in_user,viewed=False)
            print(notifications)
            serializer = NotificationSerializer(notifications, many=True)
            return get_context(serializer)
        
        except Order_Item.DoesNotExist:
            return Response({'status': status.HTTP_200_OK, 'detail': 'Order item not found.'}, status=status.HTTP_200_OK)
        except PermissionDenied as e:
            return Response({'status': status.HTTP_403_FORBIDDEN, 'detail': str(e)}, status=status.HTTP_403_FORBIDDEN)
        except Exception as exception:
            return get_exception_context(exception) 

    def put(self, request, id ):
        print('put')
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            notification = Notification.objects.get(id=id, technician=get_logged_in_user)
            notification.viewed = True
            notification.save()
            serializer = NotificationSerializer(notification)
            return get_context(serializer)
        except Notification.DoesNotExist:
            return Response({'error': 'Notification not found'}, status=200)
        except Exception as exception:
            return get_exception_context(exception) 

# class NotificationListAPIView(APIView):
#     authentication_classes = []
#     print('1040')
#     def get(self, request, *args, **kwargs):

#         try:
#             token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
#             valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
#             get_logged_in_user = valid_data['user_id']
#             notifications = Notification.objects.filter(technician=get_logged_in_user,viewed=False)
#             serializer = NotificationSerializer(notifications, many=True)
#             return get_context(serializer)
        
#         except Order_Item.DoesNotExist:
#             return Response({'status': status.HTTP_200_OK, 'detail': 'Order item not found.'}, status=status.HTTP_200_OK)
#         except PermissionDenied as e:
#             return Response({'status': status.HTTP_403_FORBIDDEN, 'detail': str(e)}, status=status.HTTP_403_FORBIDDEN)
#         except Exception as exception:
#             return get_exception_context(exception) 

#     def put(self, request, id ):
#         try:
#             token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
#             valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
#             get_logged_in_user = valid_data['user_id']
#             notification = Notification.objects.get(id=id, technician=get_logged_in_user)
#             notification.viewed = True
#             notification.save()
#             serializer = NotificationSerializer(notification)
#             return get_context(serializer)
#         except Notification.DoesNotExist:
#             return Response({'error': 'Notification not found'}, status=404)
#         except Exception as exception:
#             return get_exception_context(exception) 
   
        
# class CustomerOrderListAPI(APIView):
#     authentication_classes = []
#     pagination_class = CustomPagination
#     def get(self, request, *args, **kwargs):
#         try:
#             token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
#             valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
#             get_logged_in_user = valid_data['user_id']
#             # customer=Customer.objects.get(id=get_logged_in_user)
#             user=User.objects.get(id=get_logged_in_user)
#             if  user.isprimary == 1:
#                 queryset = Order.objects.filter(invoice__customer__user__id = get_logged_in_user )
#                 print('primary customer')
#                 print(queryset)
#             else:
#                 # additional contact
#                 # cust_info=Customer_Info.objects.get(user__id = get_logged_in_user)
#                 cust_info = Customer_Info.objects.filter(user__id=get_logged_in_user).select_related('customer__user').first()
#                 if cust_info and cust_info.customer and cust_info.customer.user:
#                     queryset = Order.objects.filter(
#                         invoice__customer__user__id=cust_info.customer.user.id
#                     )
#                 else:
#                     queryset = Order.objects.none()

#                 # if cust_info:
#                 #     print('if not primary customer')
#                 #     queryset = Order.objects.filter(invoice__customer__user__id = cust_info.customer.user.id)
#                 # else:
#                 #     queryset = []
#                 #     print('else not primary customer')
#                 # print(queryset)
        
#             paginator = self.pagination_class()
#             paginated_queryset = paginator.paginate_queryset(queryset, request)
#             next_page = paginator.get_next_link() or ''
#             previous_page = paginator.get_previous_link() or ''
#             total_pages = paginator.page.paginator.num_pages or ''
            
#             serializer_data = CustomerOrderSerializer(paginated_queryset, many=True)
#             serializer = {
#                 'results': serializer_data.data,  # Use the serialized data here
#                 'next': next_page,
#                 'previous': previous_page,
#                 'total_pages': total_pages,
#             }
            
#             context ={
#             "status": status.HTTP_200_OK,
#             "success": True,
#             "response": serializer
#             }
#             return Response(context,status=status.HTTP_200_OK)

#         except Exception as exception:
#             return get_exception_context(exception)
class CustomerOrderListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            # customer=Customer.objects.get(id=get_logged_in_user)
            user=User.objects.get(id=get_logged_in_user)
            if  user.isprimary == 1:
                queryset = Order.objects.filter(invoice__customer__user__id = get_logged_in_user ,deleted_at__isnull=True)
                print('primary customer')
                print(queryset)
            else:
                # additional contact
                cust_info=Customer_Info.objects.get(user__id = get_logged_in_user)
                if cust_info:
                    print('if not primary customer')
                    queryset = Order.objects.filter(invoice__customer__user__id = cust_info.customer.user.id,deleted_at__isnull=True)
                else:
                    queryset = Order.objects.none()
                    print('else not primary customer')
            print(queryset)
        
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            print("Paginated Orders IDs:", [obj.id for obj in paginated_queryset])
            print(next_page)
            print(total_pages)
            print('total pages')
            print("Page Data:")
            for o in paginated_queryset:
                print(o, type(o), getattr(o, 'id', None))
            serializer_data = CustomerOrderSerializer(paginated_queryset, many=True)
            # print(serializer_data.data)
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer,#list(queryset.values()),#
            }
            return Response(context,status=status.HTTP_200_OK)

        except Exception as exception:
            print('having Exception')
            return get_exception_context(exception)
            
# class CustomerOrderItemListAPI(APIView):
#     authentication_classes = []
#     pagination_class = CustomPagination
#     def get(self, request,order_id, *args, **kwargs):
#         try:
#             token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
#             valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
#             get_logged_in_user = valid_data['user_id']
#             print(get_logged_in_user)
           
            
            
#             user=User.objects.get(id=get_logged_in_user)
#             if  user.isprimary == 1:
#                 queryset = Order_Item.objects.filter(order=order_id,order__invoice__customer__user__id = get_logged_in_user)
#             else:
#                 cust_info=Customer_Info.objects.get(user__id = get_logged_in_user)
#                 queryset = Order_Item.objects.filter(order=order_id,order__invoice__customer__user__id = cust_info.customer.user.id)
              
            
#             paginator = self.pagination_class()
#             paginated_queryset = paginator.paginate_queryset(queryset, request)
#             next_page = paginator.get_next_link() or ''
#             previous_page = paginator.get_previous_link() or ''
#             total_pages = paginator.page.paginator.num_pages or ''
            
#             serializer_data = CustomerOrderItemSerializer(paginated_queryset, many=True)
#             serializer = {
#                 'results': serializer_data.data,  # Use the serialized data here
#                 'next': next_page,
#                 'previous': previous_page,
#                 'total_pages': total_pages,
#             }
            
#             context ={
#             "status": status.HTTP_200_OK,
#             "success": True,
#             "response": serializer
#             }
#             return Response(context,status=status.HTTP_200_OK)
            
        
#         except Exception as exception:
#             return get_exception_context(exception)           

class CustomerOrderItemListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request,order_id, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            print(get_logged_in_user)
            user=User.objects.get(id=get_logged_in_user)
            if  user.isprimary == 1:
                queryset = Order_Item.objects.filter(order=order_id,order__invoice__customer__user__id = get_logged_in_user)
            else:
                cust_info=Customer_Info.objects.get(user__id = get_logged_in_user)
                queryset = Order_Item.objects.filter(order=order_id,order__invoice__customer__user__id = cust_info.customer.user.id)
                
            # with open("/home/portalexcitechau/public_html/api_debug.log", "a") as f:
            #     f.write(f"User hit API: {queryset}\n")  
            
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            
            serializer_data = CustomerOrderItemSerializer(paginated_queryset, many=True)
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
            
        
        except Exception as exception:
            return get_exception_context(exception)                    

class CustomerWarrantyOrderListAPI(APIView):
    authentication_classes = []
    def get(self, request, *args, **kwargs):
        
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            today = timezone.now().date()
            queryset = Order_Item.objects.filter(
              order__invoice__customer__user__id = get_logged_in_user,warranty_end_date__gte=today
                
            )
            serializer = CustomerWarrantyOrderSerializer(queryset, many=True)
            return get_context(serializer)
        except Exception as exception:
            return get_exception_context(exception) 

class CustomerServiceOrderListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
            get_logged_in_user = valid_data['user_id']
            today = timezone.now().date()
            # queryset = Order_Item.objects.filter(
            #   order__invoice__customer__user__id = get_logged_in_user #warranty_end_date__lt=today
            # )
            u=User.objects.filter(id=get_logged_in_user).first()
            if u.isprimary != 1:
                cust=Customer_Info.objects.filter(user_id=u.id).first()
                queryset = Technician_Assigned_Order_Item.objects.filter(order_item__order__invoice__customer=cust.customer.id,job_type=2)
            else:    
                queryset = Technician_Assigned_Order_Item.objects.filter(order_item__order__invoice__customer__user__id=get_logged_in_user,job_type=2)
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            
            serializer_data = AssignedOrderItemDetailSerializer(paginated_queryset, many=True)
            # TechnicianAssignedOrderItemSerializer(paginated_queryset, many=True)
            #TechnicianServiceAssignedOrderItemSerializer(paginated_queryset, many=True)#
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
            # serializer = CustomerServiceOrderSerializer(queryset, many=True)
            # return get_context(serializer)
        except Exception as exception:
            return get_exception_context(exception) 
# class CustomerServiceOrderListAPI(APIView):
#     authentication_classes = []
#     pagination_class = CustomPagination
#     def get(self, request, *args, **kwargs):
        
#         try:
#             token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
#             valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
#             get_logged_in_user = valid_data['user_id']
#             today = timezone.now().date()
#             queryset = Order_Item.objects.filter(
#               order__invoice__customer__user__id = get_logged_in_user #warranty_end_date__lt=today
                
#             )
#             paginator = self.pagination_class()
#             paginated_queryset = paginator.paginate_queryset(queryset, request)
#             next_page = paginator.get_next_link() or ''
#             previous_page = paginator.get_previous_link() or ''
#             total_pages = paginator.page.paginator.num_pages or ''
            
#             serializer_data = CustomerServiceOrderSerializer(paginated_queryset, many=True)
#             serializer = {
#                 'results': serializer_data.data,  # Use the serialized data here
#                 'next': next_page,
#                 'previous': previous_page,
#                 'total_pages': total_pages,
#             }
            
#             context ={
#             "status": status.HTTP_200_OK,
#             "success": True,
#             "response": serializer
#             }
#             return Response(context,status=status.HTTP_200_OK)
            
            
            
#             # serializer = CustomerServiceOrderSerializer(queryset, many=True)
#             # return get_context(serializer)
#         except Exception as exception:
#             return get_exception_context(exception) 


class ServiceRequestAPIView(APIView):
    authentication_classes = []
    def post(self, request, order_item_id, *args, **kwargs):
        
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        get_logged_in_user = valid_data['user_id']
        user = User.objects.get(id=get_logged_in_user)
        order_item = Order_Item.objects.get(id=order_item_id)
        assigned_order_item=Technician_Assigned_Order_Item.objects.filter(order_item=order_item).first()
       
        # title = request.data.get('title')
        is_selected_warranty = request.data.get('is_selected_warranty')
        description= request.data.get('description')
        # comment = request.data.get('comment')
        service_request_images = request.FILES.getlist('service_request_images')
        service_request_videos = request.FILES.getlist('service_request_videos')
        # service_request_date = request.data.get('service_request_date')
        # service_request_time = request.data.get('service_request_time')
        service_request_date=datetime.now().date()
        service_request_time=datetime.now().time()
         
        # if not title:
        #     context = {
        #         "status": status.HTTP_200_OK,
        #         "success": False,
        #         'message': 'No title provided.'
        #     }
        #     return Response(context, status=status.HTTP_200_OK)
        if not is_selected_warranty:
            context = {
                "status": status.HTTP_200_OK,
                "success": False,
                'message': 'Please provide is it in warranty or in service.'
            }
            return Response(context, status=status.HTTP_200_OK)
            
            
            
        if not description:
            context = {
                "status": status.HTTP_200_OK,
                "success": False,
                'message': 'No description provided.'
            }
            return Response(context, status=status.HTTP_200_OK)
            
    

        # if not service_request_images:
        #     context = {
        #         "status": status.HTTP_200_OK,
        #         "success": False,
        #         'message': 'No service request images provided.'
        #     }
        #     return Response(context, status=status.HTTP_200_OK)

        service = Service.objects.create(order_item=order_item,description=description,is_selected_warranty=is_selected_warranty)
        # service = Service.objects.create(order_item=order_item,title=title,description=description,is_selected_warranty=is_selected_warranty)
        
        order_item.status=8
        order_item.service_type = 2
        order_item.save()
        assignment=Technician_Assigned_Order_Item.objects.create(
                order_item=order_item,
                technician=assigned_order_item.technician,
                secondary_technician=assigned_order_item.secondary_technician,
                service_request_date=service_request_date,
                service_request_time=service_request_time,
                service=service,
                job_type=2,
                created_by=user
      
                
                )
        assignment.working_status= 4  #Request Service
        assignment.save()
        subject = f'EXCITECH Australia-Job Assigned Notification (Service)-{assignment.id}'
        # formatted_date = assignment.installation_date.strftime('%d-%m-%Y')
        # formatted_time = assignment.installation_time.strftime('%I:%M %p') 
        
        
        template_data = {'assignment': assignment}
        message = render_to_string('pages/quotation/job_assigned_email_temp.html', template_data)
        

        from_email = settings.FROM_EMAIL # Replace with your email
        recipient_email = assignment.technician.email
        email = EmailMessage(subject, message, from_email, [recipient_email])
        email.content_subtype = 'html'
        email.send()
        try:
            unique_registration_ids = set()
            get_registration_token = FCMDevice.objects.filter(user_id=assignment.technician.id,active=True)
            for i in get_registration_token:
                print('notification send')
                if i.registration_id not in unique_registration_ids:
                    sendPush(f'EXCITECH Australia - Job #{assignment.id} Assigned for Service',f'Job #{assignment.id} Assigned for Service',[i.registration_id],{"job_id": assignment.id,"type": "job","tech_ids":assignment.technician.id,"customer_ids":'',"additional_cust_ids":[],"sec_tech_ids":[],"job_chat_allow":[]})     
                    unique_registration_ids.add(i.registration_id)
        except FCMDevice.DoesNotExist:
            
            print("FCMDevice not found for the specified conditions. Push notification not sent.")
        except Exception as e:
            print(f"Error sending push notification: {e}")
                
        print(service_request_images)

        for image_data, video_data in zip_longest(service_request_images, service_request_videos, fillvalue=None):
            
      
            data = {'service_request_image': image_data,
            'service_request_video':video_data
            }
            

            serializer = ServiceRequestImageSerializer(data=data)

            if serializer.is_valid():
                serializer.save(service=service)
                
                
            else:
               return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

      
        context = {
            "status": status.HTTP_201_CREATED,
            "success": True,
            'message': 'Customer service request successfully.'
        }
        return Response(context, status=status.HTTP_201_CREATED)

class CallDetailCreateView(APIView):
    authentication_classes = []

    def post(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            user = User.objects.get(id=get_logged_in_user)
            job_id = request.data.get('job_id')
            phone=request.data.get('phone')
            if not job_id:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Job id is required.'
                }
                return Response(context, status=status.HTTP_200_OK)
            if not phone:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Phone number is required.'
                }
                return Response(context, status=status.HTTP_200_OK)
        
            # if user.get_role == '3':
            if '3' in user.get_role:
                # assigned_order_item = Technician_Assigned_Order_Item.objects.get(id=job_id, technician=user)
                assigned_order_item = Technician_Assigned_Order_Item.objects.get(Q(id=job_id) & (Q(technician=user) | Q(secondary_technician=user)))
                call_details = CallDetail.objects.filter(assigned_order_item=assigned_order_item)
                caller_type=1
            elif user.get_role == '4':
                if Customer.objects.filter(email=user.email,is_primary=True):
                    customer = Customer.objects.get(email=user.email)
                    assigned_order_item = Technician_Assigned_Order_Item.objects.get(id=job_id, order_item__order__invoice__customer=customer)
                    call_details = CallDetail.objects.filter(assigned_order_item=assigned_order_item)
                    caller_type=2
                else:
                    cust = Customer_Info.objects.get(email=user.email)
                    assigned_order_item = Technician_Assigned_Order_Item.objects.get(id=job_id, order_item__order__invoice__customer__id=cust.customer.id)
                    call_details = CallDetail.objects.filter(assigned_order_item=assigned_order_item)
                    caller_type=2 

            else:
                return Response({'error': 'Invalid sender'}, status=200)
            call_details = request.data.get('call_details', [])
            print(call_details)
            if not call_details:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'No call details provided.'
                }
                return Response(context, status=status.HTTP_200_OK)
            call_details = json.loads(call_details)
            created_call_details = []
            result=False
            
            for call_detail_data in call_details:
                call_time_str=call_detail_data.get('call_time')
                call_time = datetime.strptime(call_time_str, "%b %d, %Y %I:%M %p")
                print(caller_type)
                call_data = {
                            'assigned_order_item': assigned_order_item.id,
                            'call_time':call_time ,
                            'phone':phone ,
                            'call_duration': call_detail_data.get('call_duration'),
                            'caller_type':caller_type
                        }
                try:
                           
                    call_data_instance= CallDetail.objects.get(
                        assigned_order_item=assigned_order_item.id,
                        call_time=call_data.get('call_time'),
                        phone=phone,
                        caller_type=caller_type
                    )
                    serializer = CallDetailPostSerializer(call_data_instance, data=call_data, partial=True)
                    if serializer.is_valid():
                        serializer.save()
                        created_call_details.append(serializer.data)
                        context = {
                            "status": status.HTTP_200_OK,
                            "success": True,
                            'message': 'Call details created successfully.',
                            
                            }
                        result=True
                        
                except CallDetail.DoesNotExist:
                    # If the object doesn't exist, create a new one
                    serializer = CallDetailPostSerializer(data=call_data)
                    if serializer.is_valid():
                        serializer.save()
                        created_call_details.append(serializer.data)
                        
                        context = {
                            "status": status.HTTP_200_OK,
                            "success": True,
                            'message': 'Call details created successfully.',
                            }
                        result=True
            if result:
                return Response(context, status=status.HTTP_201_CREATED)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as exception:
             return get_exception_context(exception)
   
   
    def get(self, request, job_id, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            print(get_logged_in_user)
            print(job_id)
            
            user = User.objects.get(id=get_logged_in_user)
           
            # if user.get_role == '3':
            if '3' in user.get_role:
                # assigned_order_item = Technician_Assigned_Order_Item.objects.get(id=job_id, technician=user)
                assigned_order_item = Technician_Assigned_Order_Item.objects.get(Q(id=job_id) & (Q(technician=user) | Q(secondary_technician=user)))
                print('**123**')
                print(assigned_order_item)
                call_details = CallDetail.objects.filter(assigned_order_item=assigned_order_item,caller_type=1).order_by('-call_time')
                print('123')
                print(call_details)
                 
            elif user.get_role == '4':
                if Customer.objects.filter(email=user.email,is_primary=True):
                    customer = Customer.objects.get(email=user.email)
                    assigned_order_item = Technician_Assigned_Order_Item.objects.get(id=job_id, order_item__order__invoice__customer=customer)
                    call_details = CallDetail.objects.filter(assigned_order_item=assigned_order_item,caller_type=2).order_by('-call_time')
                else:
                    cust = Customer_Info.objects.get(email=user.email)
                    assigned_order_item = Technician_Assigned_Order_Item.objects.get(id=job_id, order_item__order__invoice__customer__id=cust.customer.id)
                    call_details = CallDetail.objects.filter(assigned_order_item=assigned_order_item,caller_type=2).order_by('-call_time')
            else:
                return Response({'error': 'Invalid sender'}, status=200)
                
            # serializer = CallDetailSerializer(call_details, many=True)
            activity_data = Technician_Comment.objects.filter(technician_assigend_order_item=assigned_order_item)
            call_detail_serializer = CallDetailSerializer(call_details, many=True)
            activity_serializer = ActivitySerializer(activity_data, many=True) 
            
            
            serializer = {
                    'call_details': call_detail_serializer.data,
                    'activity': activity_serializer.data,
                }
            
            # Adjust this based on your models
            context = {
                "status": status.HTTP_200_OK,
                "success": True,
                'message': 'Call details retrieved successfully.',
                'response': serializer
                
               
            }

            return Response(context, status=status.HTTP_200_OK)

        except Exception as exception:
            return get_exception_context(exception)

class QuestionAnswerListAPIView(APIView):
    authentication_classes = []
    def getold(self, request, *args,job_id, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            answers = Answer.objects.filter(
                technician_assigned_job__technician=get_logged_in_user, is_active=True,technician_assigned_job=job_id
            )

            grouped_data = {}
            for answer in answers:
                checklist_name = answer.question.checklist.checklist_name
                type = answer.question.checklist.get_type()
                is_part = answer.question.checklist.is_part
                heading = answer.question.heading.heading
                subheading = answer.question.subheading.subheading

                question_data = {
                    "job_id": answer.technician_assigned_job.id,
                    "question_id": answer.id,
                    "question": answer.question.question,
                    "answer": answer.get_answer_display(),
                    "comment": answer.comment,
                    "is_parts":answer.is_parts,
                }
                
                

                key = (checklist_name, type, is_part)
                if key not in grouped_data:
                    grouped_data[key] = {"headings": {}}

                if heading not in grouped_data[key]["headings"]:
                    grouped_data[key]["headings"][heading] = {"subheadings": {}}

                if subheading not in grouped_data[key]["headings"][heading]["subheadings"]:
                    grouped_data[key]["headings"][heading]["subheadings"][subheading] = {"questions": []}

                grouped_data[key]["headings"][heading]["subheadings"][subheading]["questions"].append(question_data)
                
                if answer.is_parts:
                    question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                
                
                

            result = []
            for key, data in grouped_data.items():
                checklist_name, type, is_part = key
                checklist_data = {
                    "checklist_name": checklist_name,
                    "type": type,
                    "is_part": is_part,
                    "headings": [],
                }

                for heading, subheading_data in data["headings"].items():
                    heading_data = {
                        "heading": heading,
                        "subheadings": [],
                    }

                    for subheading, questions_data in subheading_data["subheadings"].items():
                        subheading_data = {
                            "subheading": subheading,
                            "questions": questions_data["questions"],
                        }

                        heading_data["subheadings"].append(subheading_data)

                    checklist_data["headings"].append(heading_data)

                result.append(checklist_data)

            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': result,
            }

            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def get(self, request, *args,job_id, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            answers = Answer.objects.filter(
                technician_assigned_job__technician=get_logged_in_user, is_active=True,technician_assigned_job=job_id,
                is_parts=0,is_warrenty=0,is_installation=1
            )

            grouped_data = {}
            for answer in answers:
                checklist_name = answer.question.checklist.checklist_name
                type = answer.question.checklist.get_type()
                is_part = answer.question.checklist.is_part
                heading = answer.question.heading.heading
                if answer.question.subheading:
                    subheading = answer.question.subheading.subheading
                else:
                    subheading = ''
                    

                question_data = {
                    "job_id": answer.technician_assigned_job.id,
                    "question_id": answer.id,
                    "question": answer.question.question,
                    "answer": answer.get_answer_display(),
                    "comment": answer.comment,
                    "is_parts":answer.is_parts,
                    "subheading":subheading
                }
                
                

                key = (checklist_name, type, is_part)
                if key not in grouped_data:
                    grouped_data[key] = {"headings": {}}

                if heading not in grouped_data[key]["headings"]:
                    grouped_data[key]["headings"][heading] ={"questions": []}

                # if subheading not in grouped_data[key]["headings"][heading]["subheadings"]:
                #     grouped_data[key]["headings"][heading]["subheadings"][subheading] = {"questions": []}

                grouped_data[key]["headings"][heading]["questions"].append(question_data)
                
                if answer.is_parts:
                    question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                    
          
                    
                    
                
            answers = Answer.objects.filter(
                technician_assigned_job__technician=get_logged_in_user, is_active=True,technician_assigned_job=job_id,
            ).filter(Q(question__id=137) | Q(question__id=178))    
            for answer in answers:
                checklist_name = ''
                type = ' '
                is_part = True
                heading = 'Service Question'
                subheading = ''

                question_data = {
                    "job_id": answer.technician_assigned_job.id,
                    "question_id": answer.id,
                    "question": answer.question.question,
                    "answer": answer.get_answer_display(),
                    "comment": answer.comment,
                    "is_parts":answer.is_parts,
                    
                    "subheading":subheading
                }
                key = (checklist_name, type, is_part)
                if key not in grouped_data:
                    grouped_data[key] = {"headings": {}}

                if heading not in grouped_data[key]["headings"]:
                    grouped_data[key]["headings"][heading] ={"questions": []}

                grouped_data[key]["headings"][heading]["questions"].append(question_data)
                
                if answer.is_parts:
                    question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                   

            result = []
            for key, data in grouped_data.items():
                checklist_name, type, is_part = key
                checklist_data = {
                    "checklist_name": checklist_name,
                    "type": type,
                    "is_part": is_part,
                    "headings": [],
                }

                for heading ,questions_data in data["headings"].items():
                    heading_data = {
                        "heading": heading,
                        "questions": questions_data["questions"],
                        # "subheadings": [],
                    }

                    # for questions_data in subheading_data["subheadings"].items():
                    #     subheading_data = {
                    #         "subheading": subheading,
                    #         "questions": questions_data["questions"],
                    #     }

                    # heading_data["headings"].append(heading_data)

                    checklist_data["headings"].append(heading_data)

                result.append(checklist_data)
           
            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': result,
            }

            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                    
            
    def get_parts_detail(self, job_id):
            try:
                   
                parts_details = Parts_Request.objects.filter(technician_assigned_job_id=job_id).values()
                return parts_details
            except Exception as e:
                print(f"Error in get_parts_detail: {e}")
                return None
    def change_signature_status(job_id):
        technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
        questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
        if questionsrow == 0 :
            technician_assigned_job_row.is_signature=True
            technician_assigned_job_row.save()
            
    def post(self, request, format=None):
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        get_logged_in_user = valid_data['user_id']

        question_id = request.data.get('question_id')
        serviceJobPartsRequested = request.data.get('serviceJobPartsRequested')
        is_parts = request.data.get('is_parts', False)
        print(is_parts)
        
        job_id = request.data.get('job_id')
        if not job_id:
            context = {
                "status": status.HTTP_200_OK,
                "success": False,
                'message': 'Job id is required.'
            }
            return Response(context, status=status.HTTP_200_OK)
        if serviceJobPartsRequested == 0:   
            if not question_id:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Question id is required.'
                }
                return Response(context, status=status.HTTP_200_OK)

        
        
        technician_assigned_job = Technician_Assigned_Order_Item.objects.get(id=job_id)
        order_item=Order_Item.objects.get(id=technician_assigned_job.order_item.id)

        try:
            
            if is_parts == '1'  and serviceJobPartsRequested == '0':
            # if  Answer.objects.filter(id=question_id,technician_assigned_job=technician_assigned_job):
                try:
                    job_time=Job_Time.objects.get(assigned_order_item=technician_assigned_job,assigned_order_item__technician=get_logged_in_user,stop_time__isnull=True)
                except:
                    job_time = Job_Time.objects.create(assigned_order_item=technician_assigned_job)
                    job_time.start_time = timezone.now()  # Set the start time to the current time
                    job_time.save() 
                    technician_assigned_job.job_status=1
                    if technician_assigned_job.job_type==1:
                        technician_assigned_job.working_status=2
                    if technician_assigned_job.job_type==2:
                        technician_assigned_job.working_status=6
                    technician_assigned_job.save()
                    order_item.status=6
                    order_item.save()
                question=Answer.objects.get(id=question_id)
                answer = request.data.get('answer')
                if not answer:
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": False,
                        'message': 'answer is required.'
                    }
                    return Response(context, status=status.HTTP_200_OK)
                if answer == '1':
                    comment = request.data.get('comment')
                    if not comment:
                        context = {
                            "status": status.HTTP_200_OK,
                            "success": False,
                            'message': 'comment is required.'
                        }
                        return Response(context, status=status.HTTP_200_OK)
                    parts_data = request.data.get('parts_data')
                    print(parts_data)
                    print("deepak")
                    if not parts_data:
                        context = {
                            "status": status.HTTP_200_OK,
                            "success": False,
                            'message': 'parts_data is required.'
                        }
                        return Response(context, status=status.HTTP_200_OK)
                    parts_data = json.loads(parts_data)
                    question.answer =answer
                    question.comment =comment
                    question.is_parts=is_parts
                    created_parts_requests = []
                    result=False
                    for part_data in parts_data:
                        part_id = part_data.get('id')
                        parts_request_data = {
                            'technician_assigned_job': technician_assigned_job.id,
                            'question': question.question.id,
                            'parts_name': part_data.get('parts_name'),
                            'qty': part_data.get('qty')
                        }
                        if part_id:
                            try:
                                parts_request_instance = Parts_Request.objects.get(id=part_id)
                                serializer = PartsRequestSerializer(parts_request_instance, data=parts_request_data, partial=True)
                                context = {
                                    "status": status.HTTP_200_OK,
                                    "success": True,
                                    'message': 'Technician parts request successfully.',
                                 }
                                result=True
                            except Parts_Request.DoesNotExist:
                                parts_request_instance = None
        
                        if not part_id or not parts_request_instance:
                            serializer = PartsRequestSerializer(data=parts_request_data)
        
                        if serializer.is_valid():
                            serializer.save()
                            technician_assigned_job.job_status = 2  # part_needed
                            
                            if technician_assigned_job.job_type==2:
                                 technician_assigned_job.working_status = 8 #Part Needed
                            
                            technician_assigned_job.save()
                            created_parts_requests.append(serializer.data)
                            context = {
                                "status": status.HTTP_200_OK,
                                "success": True,
                                'message': 'Technician parts request successfully.',
                            }
                            result=True
                        else:
                            context = {
                                "status": status.HTTP_400_BAD_REQUEST,
                                "success": False,
                                'message': 'Invalid data provided for parts request.',
                                'errors': serializer.errors
                            }
                            return Response(context, status=status.HTTP_400_BAD_REQUEST)

                    if result:
                        # question.is_active=False  
                        job_time.stop_time = timezone.now()
                        job_time.save()
                        question.save()
                        order_item.status=9
                        order_item.save()
                        technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
                        questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
                        if questionsrow == 0 :
                            technician_assigned_job_row.is_signature=True
                            technician_assigned_job_row.save()
                        return Response(context, status=status.HTTP_201_CREATED)
                    else:
                        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
                elif  answer == '2':
                     question.answer =answer
                     question.save()
                     technician_assigned_job.job_status=1
                     if technician_assigned_job.job_type==1:
                        technician_assigned_job.working_status=2
                     if technician_assigned_job.job_type==2:
                        technician_assigned_job.working_status=6
                     
                     technician_assigned_job.save()
                     order_item.status=6
                     order_item.save()
                     context = {
                            "status": status.HTTP_200_OK,
                            "success": True,
                            'message': 'Technician not applicable.'
                            }
                     technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
                     questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
                     if questionsrow == 0 :
                         technician_assigned_job_row.is_signature=True
                         technician_assigned_job_row.save()
                     return Response(context, status=status.HTTP_200_OK)
                else:
                    comment = request.data.get('comment')  
                    question.answer =answer
                    question.comment =comment
                    question.save()
                    technician_assigned_job.job_status=1
                    if technician_assigned_job.job_type==1:
                        technician_assigned_job.working_status=2
                    if technician_assigned_job.job_type==2:
                        technician_assigned_job.working_status=6
                    technician_assigned_job.save()
                    
                    order_item.status=6
                    order_item.save()
                    
                    
                    context = {
                            "status": status.HTTP_200_OK,
                            "success": True,
                            'message': 'Technician submit the answer successfully..'
                            }
                    technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
                    questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
                    if questionsrow == 0 :
                        technician_assigned_job_row.is_signature=True
                        technician_assigned_job_row.save()
                    return Response(context, status=status.HTTP_200_OK)
                # dd('out')
            elif is_parts == '1' and serviceJobPartsRequested == '1': 
                # dd('here')
                try:
                    job_time=Job_Time.objects.get(assigned_order_item=technician_assigned_job,assigned_order_item__technician=get_logged_in_user,stop_time__isnull=True)
                except:
                    job_time = Job_Time.objects.create(assigned_order_item=technician_assigned_job)
                    job_time.start_time = timezone.now()  # Set the start time to the current time
                    job_time.save() 
                    technician_assigned_job.job_status=1
                    if technician_assigned_job.job_type==1:
                        technician_assigned_job.working_status=2
                    if technician_assigned_job.job_type==2:
                        technician_assigned_job.working_status=6
                    technician_assigned_job.save()
                    order_item.status=6
                    order_item.save()
                question=Answer.objects.get(question_id=137,technician_assigned_job_id=technician_assigned_job.id)
                # if not question:
                #     question=Answer
                answer = request.data.get('answer')
                if not answer:
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": False,
                        'message': 'answer is required.'
                    }
                    return Response(context, status=status.HTTP_200_OK)
                if answer == '1':
                    comment = request.data.get('comment')
                    if not comment:
                        context = {
                            "status": status.HTTP_200_OK,
                            "success": False,
                            'message': 'comment is required.'
                        }
                        return Response(context, status=status.HTTP_200_OK)
                    parts_data = request.data.get('parts_data')
                    print(parts_data)
                    print("deepak")
                    if not parts_data:
                        context = {
                            "status": status.HTTP_200_OK,
                            "success": False,
                            'message': 'parts_data is required.'
                        }
                        return Response(context, status=status.HTTP_200_OK)
                    parts_data = json.loads(parts_data)
                    question.answer =answer
                    question.comment =comment
                    question.is_parts=is_parts
                    created_parts_requests = []
                    result=False
                    for part_data in parts_data:
                        part_id = part_data.get('id')
                        parts_request_data = {
                            'technician_assigned_job': technician_assigned_job.id,
                            'question': question.question.id,
                            'parts_name': part_data.get('parts_name'),
                            'qty': part_data.get('qty')
                        }
                        if part_id:
                            try:
                                parts_request_instance = Parts_Request.objects.get(id=part_id)
                                serializer = PartsRequestSerializer(parts_request_instance, data=parts_request_data, partial=True)
                                context = {
                                    "status": status.HTTP_200_OK,
                                    "success": True,
                                    'message': 'Technician parts request successfully.',
                                 }
                                result=True
                            except Parts_Request.DoesNotExist:
                                parts_request_instance = None
        
                        if not part_id or not parts_request_instance:
                            serializer = PartsRequestSerializer(data=parts_request_data)
        
                        if serializer.is_valid():
                            serializer.save()
                            technician_assigned_job.job_status = 2  # part_needed
                            
                            if technician_assigned_job.job_type==2:
                                 technician_assigned_job.working_status = 8 #Part Needed
                            
                            technician_assigned_job.save()
                            created_parts_requests.append(serializer.data)
                            context = {
                                "status": status.HTTP_200_OK,
                                "success": True,
                                'message': 'Technician parts request successfully.',
                            }
                            result=True
                        else:
                            context = {
                                "status": status.HTTP_400_BAD_REQUEST,
                                "success": False,
                                'message': 'Invalid data provided for parts request.',
                                'errors': serializer.errors
                            }
                            return Response(context, status=status.HTTP_400_BAD_REQUEST)

                    if result:
                        # question.is_active=False  
                        job_time.stop_time = timezone.now()
                        job_time.save()
                        question.save()
                        order_item.status=9
                        order_item.save()
                        technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
                        questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
                        if questionsrow == 0 :
                            technician_assigned_job_row.is_signature=True
                            technician_assigned_job_row.save()
                        return Response(context, status=status.HTTP_201_CREATED)
                    else:
                        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
                elif  answer == '2':
                     question.answer =answer
                     question.save()
                     technician_assigned_job.job_status=1
                     if technician_assigned_job.job_type==1:
                        technician_assigned_job.working_status=2
                     if technician_assigned_job.job_type==2:
                        technician_assigned_job.working_status=6
                     
                     technician_assigned_job.save()
                     order_item.status=6
                     order_item.save()
                     context = {
                            "status": status.HTTP_200_OK,
                            "success": True,
                            'message': 'Technician not applicable.'
                            }
                     technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
                     questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
                     if questionsrow == 0 :
                         technician_assigned_job_row.is_signature=True
                         technician_assigned_job_row.save()
                     return Response(context, status=status.HTTP_200_OK)
                else:
                    comment = request.data.get('comment')  
                    question.answer =answer
                    question.comment =comment
                    question.save()
                    technician_assigned_job.job_status=1
                    if technician_assigned_job.job_type==1:
                        technician_assigned_job.working_status=2
                    if technician_assigned_job.job_type==2:
                        technician_assigned_job.working_status=6
                    technician_assigned_job.save()
                    
                    order_item.status=6
                    order_item.save()
                    
                    
                    context = {
                            "status": status.HTTP_200_OK,
                            "success": True,
                            'message': 'Technician submit the answer successfully..'
                            }
                    technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
                    questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
                    if questionsrow == 0 :
                        technician_assigned_job_row.is_signature=True
                        technician_assigned_job_row.save()
                    return Response(context, status=status.HTTP_200_OK)
            else:
                instance = Answer.objects.get(id=question_id,technician_assigned_job__technician=get_logged_in_user,technician_assigned_job=technician_assigned_job)
                serializer = AnswerSerializer(instance, data=request.data)
                if serializer.is_valid():
                    serializer.save()
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": True,
                        'message': 'Technician submit the answer successfully.'
                    }
                    
                    technician_assigned_job_row = Technician_Assigned_Order_Item.objects.get(id=job_id)
                    questionsrow=Answer.objects.filter(technician_assigned_job=technician_assigned_job_row,answer__isnull=True).count()
                    if questionsrow == 0 :
                        technician_assigned_job_row.is_signature=True
                        technician_assigned_job_row.save()
                    return Response(context, status=status.HTTP_200_OK)
                else:
                    context = {
                        'status': status.HTTP_400_BAD_REQUEST,
                        'success': False,
                        'response': serializer.errors
                    }
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)

        except Question.DoesNotExist:
            return Response({'error': 'Invalid question ID'}, status=status.HTTP_400_BAD_REQUEST)

class UpdateJobStartStopFlagAPI(APIView):
    def post(self, request, *args, **kwargs):
        try:
      
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            
            user = User.objects.get(id=get_logged_in_user)
            # userinfo = UserInfo.objects.get(user=user).
            # print(userinfo.get_role)

            user_role_ids = user.role.values_list('id', flat=True)
             
            job_id = request.data.get('job_id')
            
            if not job_id:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Job id is required.'
                }
                return Response(context, status=status.HTTP_200_OK)
                
            flag = request.data.get('flag')
            print(request.data)
            job = Technician_Assigned_Order_Item.objects.get(id=job_id)
            job.start_stop_job=flag
            job.save()
            context = {
                'status': status.HTTP_201_CREATED,
                'success': True,
                'response':'Job status updated successfully',
            }

            return Response(context,  status=status.HTTP_201_CREATED)
        except Exception as exception:
            return get_exception_context(exception) 

class CreateChatAPIView(APIView):
    def post(self, request, *args, **kwargs):
        try:
      
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            
            user = User.objects.get(id=get_logged_in_user)
            # userinfo = UserInfo.objects.get(user=user).
            # print(userinfo.get_role)

            user_role_ids = user.role.values_list('id', flat=True)
             
            job_id = request.data.get('job_id')
            content = request.data.get('content')
            
            chat_images = request.FILES.getlist('chat_image')

            if not job_id:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Job id is required.'
                }
                return Response(context, status=status.HTTP_200_OK)

            job = Technician_Assigned_Order_Item.objects.get(id=job_id)
            
            is_visible = request.data.get('is_visible')
            
            # if user.get_role == '3':
            if '3' in user.get_role:
                recipient = job.order_item.order.invoice.customer.user.id
                sender=user
                if not is_visible:
                    context = {
                        "status": status.HTTP_400_BAD_REQUEST,
                        "success": False,
                        'message': 'Is visible required.'
                    }
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)

            elif user.get_role == '4':
                recipient = job.technician.userinfo.user.id
                sender=job.order_item.order.invoice.customer.user
                
                if  user.isprimary == 1:
                    sender=job.order_item.order.invoice.customer.user
                    
                else:
                    cust_info=Customer_Info.objects.get(user__id = get_logged_in_user)
                    # user=cust_info.customer.user.id
                    sender=cust_info.user
             
            else:
                return Response({'error': 'Invalid sender'}, status=400)
                
            print(recipient)   
            recipient_user=User.objects.get(id=recipient)
            chat = Chat.objects.create(
                job=job,
                sender=sender,
                recipient=recipient_user,
                content=content,
                is_visible=is_visible,
                is_sent=0
            )
            
            if chat_images:
                for chat_image_data in chat_images:
                    chat_image_data = {'chat_image': chat_image_data}
                    chat_image_serializer = ChatImageSerializer(data=chat_image_data)
    
                    if chat_image_serializer.is_valid():
                        chat_image_serializer.save(chat=chat)
                    else:
                        return Response(chat_image_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
                        
            try:
                techuser = User.objects.get(id=job.technician.id)
                tech_id = techuser.id
                
                st_id=[]
                if job.secondary_technician:
                    st=User.objects.get(id=job.secondary_technician.id)
                    st_id=st.id
                cust=job.order_item.order.invoice.customer.user.id
                
                
                cust_info_ids= list(
                        Customer_Info.objects.filter(customer__id=job.order_item.order.invoice.customer.id, user__app_access=1)
                        .values_list("user_id", flat=True)
                    )
                all_other= list(
                    User.objects.filter(job_chat=1)
                    .values_list("id", flat=True)
                )
                query = Q(user__job_chat=1)
            
                if tech_id:
                    query |= Q(user_id=tech_id)
                if cust:
                    query |= Q(user_id=cust)
                if st_id:
                    query |= Q(user_id=st_id)
                
                
                if cust_info_ids:
                    query |= Q(user_id__in=cust_info_ids)
                print(query)
                registration_ids = list(
                    FCMDevice.objects.filter(active=True)
                    .filter(query)
                    .exclude(user_id=get_logged_in_user)
                    .values_list("registration_id", flat=True)
                    .distinct()
                )
                job_data = {
                    'id':job.id,
                    'customercompanyname':job.order_item.order.invoice.customer.company_name,
                    'customerlastname':job.order_item.order.invoice.customer.last_name,
                    'customerfirstname':job.order_item.order.invoice.customer.first_name,
                    'is_individual':job.order_item.order.invoice.customer.is_individual
                    }
                if registration_ids:
                    sendPush(
                        f"EXCITECH Australia - Job #{job_id} Chat",
                        f"New Chat For Job #{job_id}",
                        list(registration_ids),{"job_id": job_id,"type": "chat","job_details": json.dumps(job_data),"tech_ids":tech_id,"customer_ids":cust,"additional_cust_ids":cust_info_ids,"sec_tech_ids":st_id,"job_chat_allow":all_other}
                    )
            except FCMDevice.DoesNotExist:
                print("FCMDevice not found for the specified conditions. Push notification not sent.")
            except Exception as e:
                print(f"Error sending push notification: {e}")

            context = {
                'status': status.HTTP_201_CREATED,
                'success': True,
                'response':'Chat message created successfully',
            }

            return Response(context,  status=status.HTTP_201_CREATED)  
        except Exception as exception:
            return get_exception_context(exception)  
            
            
    def get(self, request, job_id, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            user = User.objects.get(id=get_logged_in_user) 
          
            if '3' in user.get_role:
                sender=[]
                # sender.append(user)
                job = Technician_Assigned_Order_Item.objects.get(id=job_id)
                if job.secondary_technician:
                    st=User.objects.get(id=job.secondary_technician.id) 
                    sender.append(st)
                if job.technician:
                    st=User.objects.get(id=job.technician.id) 
                    sender.append(st)
            else:
                sender=[]
                if  user.isprimary == 1:
                    sender.append(user)   #append
                    cust=Customer.objects.get(user__id=get_logged_in_user)
                    cust_info=Customer_Info.objects.filter(customer__id = cust.id)
                    if cust_info:
                        for u in cust_info:
                            sender.append(u.user)  #append
                        
                else:
                    cust_info=Customer_Info.objects.get(user__id = get_logged_in_user)
                    cust=Customer.objects.get(id=cust_info.customer.id)
                    sender.append(cust.user) #append
                    cust_info=Customer_Info.objects.filter(customer__id = cust.id)
                    if cust_info:
                        for u in cust_info:
                            sender.append(u.user)  #append
                   
            
            # chats = Chat.objects.filter(
            #     Q(sender__in =sender, job__id=job_id) | Q(recipient__in=sender, job__id=job_id)
            # )
            chats = Chat.objects.filter(
               job__id=job_id
            )
            Chat.objects.filter( Q(recipient__in=sender) & Q(job__id=job_id) ).update(is_read=1)
            print(chats)
            serializer = ChatSerializer(chats, many=True)
            print(serializer)
            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response':serializer.data,
            }
            
            return Response(context, status=status.HTTP_200_OK)

        except Exception as exception:
          
            return get_exception_context(exception)
            
class ServiceSignatureAPIView(APIView):
    def post(self, request, *args, **kwargs):
        
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']  
            
            job_id = request.data.get('job')
                    
            job = Technician_Assigned_Order_Item.objects.get(id=job_id)
            
            print(job)
           
            order_item=Order_Item.objects.get(id=job.order_item.id)
            print(order_item)
            job_time=Job_Time.objects.get(assigned_order_item=job,assigned_order_item__technician=get_logged_in_user,stop_time__isnull=True)
            print(job_time)
            
            serializer = ServiceSignatureSerializer(data=request.data)
            
            print(serializer)
            if serializer.is_valid():
                serializer.save()
                
                if job.job_type==1:
                    job.working_status = 3  #Completed Installation
                if job.job_type==2:
                    job.working_status = 7  #Completed Service  
                
                job.job_status=4
                job.job_completed=True
                job.is_signature=False
                job.save()
                
                if order_item.service_type == 1:
                    
                    order_item.installation_complete=True
                    order_item.status=10
                    p=Product.object.get(id=order_item.product.id)
                    p.is_product=0
                    p.save()
                    
                elif order_item.service_type == 2:   
                    order_item.installation_complete=True
                    order_item.status=11
                    p=Product.object.get(id=order_item.product.id)
                    p.is_product=0
                    p.save()
                 
                job_time.stop_time = timezone.now()
                job_time.save()
                
            
                order_item.save()
                
                print(order_item)
                try:
                    unique_registration_ids = set()
                    get_registration_token = FCMDevice.objects.filter(user_id=get_logged_in_user, active=True) 
                    for i in get_registration_token:
                        if i.registration_id not in unique_registration_ids:
                            sendPush(f'EXCITECH Australia - Job #{job.id} Completed',f'Signature Done By The Customer',[i.registration_id],{"job_id": job.id,"type": "job","tech_ids":get_logged_in_user,"customer_ids":'',"additional_cust_ids":[],"sec_tech_ids":[],"job_chat_allow":[]})     
                            unique_registration_ids.add(i.registration_id)
                except FCMDevice.DoesNotExist:
                    print("FCMDevice not found for the specified conditions. Push notification not sent.")
                except Exception as e:
                    print(f"Error sending push notification: {e}")
                
                # try:
                #     unique_registration_ids = set()
                #     get_registration_token = FCMDevice.objects.filter(user_id=job.order_item.order.invoice.customer.user.id, active=True)
                #     for i in get_registration_token:
                #         if i.registration_id not in unique_registration_ids:
                #             sendPush(f'EXCITECH Australia - Job #{job.id} Completed Notification',f'Signature Done By The Customer',[i.registration_id])    
                #             unique_registration_ids.add(i.registration_id)
                # except FCMDevice.DoesNotExist:
                #     print("FCMDevice not found for the specified conditions. Push notification not sent.")
                # except Exception as e:
                #     print(f"Error sending push notification: {e}")
                

                context = {
                    'status': status.HTTP_201_CREATED,
                    'success': True,
                    'response':'Submit signature successfully',
                }
                return Response(context,  status=status.HTTP_201_CREATED)  
                
            else:
                context = {
                    'status': status.HTTP_400_BAD_REQUEST,
                    'success': False,
                    'response': serializer.errors
                }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)
                
        except Exception as exception:
            return get_exception_context(exception)
            
class CustomerSendSignatureMail(APIView):
    def post(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']  
            job_id = request.data.get('job')
            print(job_id)
            job = Technician_Assigned_Order_Item.objects.get(id=job_id)
            # print(job_d)
            subject = f'EXCITECH Australia -Service Job Signature For Job Id: {job.id}'
            # message = f"Hi {job.order_item.order.invoice.customer},<br>"
            # message += "Please find link to make sign."
            token = base64.urlsafe_b64encode(str(job_id).encode()).decode()
            link = f'http://ea.stagingstorm.com:8000/job-signature/{token}/'
            # link='http://ea.stagingstorm.com:8000/job-signature/<int:job_id>/'
            template_data = {'job_id': job_id,'job':job,'link':link}
            message = render_to_string('pages/quotation/servicesignature_email.html', template_data)
            from_email = settings.FROM_EMAIL #job.technician.email # Replace with your email address
            recipient_email ='kiran@beedev.co.in' #job.order_item.order.invoice.customer.email  # Use the customer's email address
            email = EmailMessage(subject, message, from_email, [recipient_email])
            email.content_subtype = "html"
            email.send()
            job.sign_email_cust = 1
            job.sign_email_cust_by = get_logged_in_user
            job.save()
            # ci = Customer_Info.objects.filter(customer__id = job.order_item.order.invoice.customer.id,user__is_communication = 1)
            # if ci:
            #     for additional_email in  ci:
            #         email = EmailMessage(subject, message, from_email, [additional_email.user.email])
            #         email.content_subtype = "html"
            #         email.attach_file(pdf_file_path, 'application/pdf')
            #         email.content_subtype = 'html'
            #         email.send()
            context = {
                    'status': status.HTTP_201_CREATED,
                    'success': True,
                    'response':'Email sent successfully',
                }
            return Response(context,  status=status.HTTP_201_CREATED)
        except Exception as exception:
            return get_exception_context(exception)
            
class CustomerServiceSignatureAPIViewByCustomer(APIView):
    def post(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']  
            job_id = request.data.get('job')
            
            question_data = request.data.get('question_answer')
            if not job_id:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'Job id is required.'
                }
                return Response(context, status=status.HTTP_200_OK)
                    
            if not question_data:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'question and answer is required.'
                }
                return Response(context, status=status.HTTP_200_OK)
             
            question_data = json.loads(question_data)
            job = Technician_Assigned_Order_Item.objects.get(id=job_id)
           
            for item in question_data:
                question_id = item.get('question_id')
                answer_text = item.get('answer')
                ans=Answer.objects.get(id=question_id,technician_assigned_job=job_id)
                ans.answer=answer_text
                ans.save()
            order_item=Order_Item.objects.get(id=job.order_item.id)
            # job_time=Job_Time.objects.get(assigned_order_item=job,stop_time__isnull=True)
            technician_assigned_job = Technician_Assigned_Order_Item.objects.get(id=job_id,order_item=order_item)
            accepted_images = request.FILES.getlist('accepted_images')
            serializer = ServiceSignatureSerializer(data=request.data)
            if serializer.is_valid():
                service_signature=serializer.save()
                service_signature_id = service_signature
                if job.job_type==1:
                    job.working_status = 3  #Completed Installation
                if job.job_type==2:
                    job.working_status = 7  #Completed Service 
                job.job_status=4
                job.job_complete_datetime=timezone.now()
                job.job_completed=True
                job.is_signature=True
                job.customer_signature_required=False
                job.save()
                if order_item.service_type == 1:
                    order_item.installation_complete=True
                    order_item.status=10
                elif order_item.service_type == 2:   
                    order_item.installation_complete=True
                    order_item.status=11
                # if order_item.product.is_trade == 1:
                #     Product.objects.filter(id=order_item.product.id).update(is_product=0)
                # job_time.stop_time = timezone.now()
                
                # job_time.save()
                order_item.save()
                try:
                    unique_registration_ids = set()
                    get_registration_token = FCMDevice.objects.filter(user_id=get_logged_in_user, active=True) 
                    for i in get_registration_token:
                        if i.registration_id not in unique_registration_ids:
                            sendPush(f'EXCITECH Australia - Job #{job.id} Completed','Job Completed',[i.registration_id],{"job_id": job.id,"type": "job",
                                "tech_ids":'',"customer_ids":get_logged_in_user,"additional_cust_ids":[],"sec_tech_ids":[],"job_chat_allow":[]
                            })     
                            unique_registration_ids.add(i.registration_id)
                except FCMDevice.DoesNotExist:
                    print("FCMDevice not found for the specified conditions. Push notification not sent.")
                except Exception as e:
                    print(f"Error sending push notification: {e}")
                
                try:
                    unique_registration_ids = set()
                    get_registration_token = FCMDevice.objects.filter(user_id=job.technician.id, active=True)
                    for i in get_registration_token:
                        if i.registration_id not in unique_registration_ids:
                            sendPush(f'EXCITECH Australia - Job #{job.id} Completed',f'Signature Done By The Customer',[i.registration_id],{"job_id": job.id,"type": "job",
                                "tech_ids":job.technician.id,"customer_ids":'',"additional_cust_ids":[],"sec_tech_ids":[],"job_chat_allow":[]
                            })     
                            unique_registration_ids.add(i.registration_id)
                except FCMDevice.DoesNotExist:
                    print("FCMDevice not found for the specified conditions. Push notification not sent.")
                except Exception as e:
                    print(f"Error sending push notification: {e}")
        
             
                if accepted_images:
                    print(accepted_images)
                    for image_data in accepted_images:
                        data = {'accepted_image': image_data}
                        serializer = Accepted_ImageSerializer(data=data)
                        if serializer.is_valid():
                            serializer.save(service_signature=service_signature_id)
                        else:
                           return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
                answer = Answer.objects.filter(technician_assigned_job=job,answer__isnull = False) 
                signature=Service_Signature.objects.get(job=job)
                accepted_images = Accepted_Image.objects.filter(service_signature=signature)
                if answer:
                    pdf_data = generate_pdf(job, answer,signature,accepted_images)
                    if pdf_data:
                        job.pdf_file.save(f'job_{job.id}.pdf', pdf_data, save=True)
                        
                        subject = f'EXCITECH Australia -Job Checklist Details For Job Id: {job.id}'
                        message = f"Hi {job.order_item.order.invoice.customer},<br>"
                        message += "Please find technician attached checklist."
                        from_email = settings.FROM_EMAIL #job.technician.email # Replace with your email address
                        recipient_email =job.order_item.order.invoice.customer.email  # Use the customer's email address
                        email = EmailMessage(subject, message, from_email, [recipient_email])
                        
                        
                        pdf_file_path = job.pdf_file.path 
                        email.attach_file(pdf_file_path, 'application/pdf')
                        email.content_subtype = 'html'
                        email.send()
                        
                        ci = Customer_Info.objects.filter(customer__id = job.order_item.order.invoice.customer.id,user__is_communication = 1)
                        if ci:
                            for additional_email in  ci:
                                email = EmailMessage(subject, message, from_email, [additional_email.user.email])
                                email.attach_file(pdf_file_path, 'application/pdf')
                                email.content_subtype = 'html'
                                email.send()
        
                context = {
                    'status': status.HTTP_201_CREATED,
                    'success': True,
                    'response':'Submit signature successfully',
                }
                return Response(context,  status=status.HTTP_201_CREATED)   
            else:
                context = {
                        'status': status.HTTP_400_BAD_REQUEST,
                        'success': False,
                        'response': serializer.errors
                }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)
               
        except Exception as exception:
            return get_exception_context(exception)            
        
class ServiceSignatureAPIViewByCustomer(APIView):
    def post(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']  
            job_id = request.data.get('job')
            request_customer = request.data.get('request_customer')
            print(request_customer)
            if request_customer == 0 or request_customer == '0':
                question_data = request.data.get('question_answer')
                if not job_id:
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": False,
                        'message': 'Job id is required.'
                    }
                    return Response(context, status=status.HTTP_200_OK)
                        
                if not question_data:
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": False,
                        'message': 'question and answer is required.'
                    }
                    return Response(context, status=status.HTTP_200_OK)
                 
                question_data = json.loads(question_data)
                job = Technician_Assigned_Order_Item.objects.get(id=job_id)
               
                for item in question_data:
                    question_id = item.get('question_id')
                    answer_text = item.get('answer')
                    ans=Answer.objects.get(id=question_id,technician_assigned_job=job_id)
                    ans.answer=answer_text
                    ans.save()
                order_item=Order_Item.objects.get(id=job.order_item.id)
                job_time=Job_Time.objects.get(assigned_order_item=job,stop_time__isnull=True)
                technician_assigned_job = Technician_Assigned_Order_Item.objects.get(order_item=order_item, is_signature=False)
                accepted_images = request.FILES.getlist('accepted_images')
                serializer = ServiceSignatureSerializer(data=request.data)
                if serializer.is_valid():
                    service_signature=serializer.save()
                    service_signature_id = service_signature
                    if job.job_type==1:
                        job.working_status = 3  #Completed Installation
                    if job.job_type==2:
                        job.working_status = 7  #Completed Service 
                    job.job_status=4
                    job.job_complete_datetime=timezone.now()
                    job.job_completed=True
                    job.is_signature=True
                    job.customer_signature_required=False
                    job.save()
                    if order_item.service_type == 1:
                        order_item.installation_complete=True
                        order_item.status=10
                    elif order_item.service_type == 2:   
                        order_item.installation_complete=True
                        order_item.status=11
                    # if order_item.product.is_trade == 1:
                    #     Product.objects.filter(id=order_item.product.id).update(is_product=0)
                    job_time.stop_time = timezone.now()
                    
                    job_time.save()
                    order_item.save()
                    try:
                        unique_registration_ids = set()
                        get_registration_token = FCMDevice.objects.filter(user_id=get_logged_in_user, active=True) 
                        for i in get_registration_token:
                            if i.registration_id not in unique_registration_ids:
                                sendPush(f'EXCITECH Australia - Job #{job.id} Completed','Signature Done By The Customer',[i.registration_id],{"job_id": job.id,"type": "job",
                                    "tech_ids":'',"customer_ids":get_logged_in_user,"additional_cust_ids":[],"sec_tech_ids":[],"job_chat_allow":[]
                                })     
                                unique_registration_ids.add(i.registration_id)
                    except FCMDevice.DoesNotExist:
                        print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    except Exception as e:
                        print(f"Error sending push notification: {e}")
                    
                    try:
                        unique_registration_ids = set()
                        get_registration_token = FCMDevice.objects.filter(user_id=job.technician.id, active=True)
                        for i in get_registration_token:
                            if i.registration_id not in unique_registration_ids:
                                sendPush(f'EXCITECH Australia - Job #{job.id} Completed',f'Signature Done By The Customer',[i.registration_id],{"job_id": job.id,"type": "job",
                                    "tech_ids":job.technician.id,"customer_ids":'',"additional_cust_ids":[],"sec_tech_ids":[],"job_chat_allow":[]
                                })     
                                unique_registration_ids.add(i.registration_id)
                    except FCMDevice.DoesNotExist:
                        print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    except Exception as e:
                        print(f"Error sending push notification: {e}")
    
                 
                    if accepted_images:
                        print(accepted_images)
                        for image_data in accepted_images:
                            data = {'accepted_image': image_data}
                            serializer = Accepted_ImageSerializer(data=data)
                            if serializer.is_valid():
                                serializer.save(service_signature=service_signature_id)
                            else:
                               return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
                    answer = Answer.objects.filter(technician_assigned_job=job,answer__isnull = False) 
                    signature=Service_Signature.objects.get(job=job)
                    accepted_images = Accepted_Image.objects.filter(service_signature=signature)
                    if answer:
                        pdf_data = generate_pdf(job, answer,signature,accepted_images)
                        if pdf_data:
                            job.pdf_file.save(f'job_{job.id}.pdf', pdf_data, save=True)
                            
                            subject = f'EXCITECH Australia -Job Checklist Details For Job Id: {job.id}'
                            message = f"Hi {job.order_item.order.invoice.customer},<br>"
                            message += "Please find technician attached checklist."
                            from_email = settings.FROM_EMAIL #job.technician.email # Replace with your email address
                            recipient_email =job.order_item.order.invoice.customer.email  # Use the customer's email address
                            email = EmailMessage(subject, message, from_email, [recipient_email])
                            
                            
                            pdf_file_path = job.pdf_file.path 
                            email.attach_file(pdf_file_path, 'application/pdf')
                            email.content_subtype = 'html'
                            email.send()
                            
                            ci = Customer_Info.objects.filter(customer__id = job.order_item.order.invoice.customer.id,user__is_communication = 1)
                            if ci:
                                for additional_email in  ci:
                                    email = EmailMessage(subject, message, from_email, [additional_email.user.email])
                                    email.attach_file(pdf_file_path, 'application/pdf')
                                    email.content_subtype = 'html'
                                    email.send()
    
                    context = {
                        'status': status.HTTP_201_CREATED,
                        'success': True,
                        'response':'Submit signature successfully',
                    }
                    return Response(context,  status=status.HTTP_201_CREATED)   
                else:
                    context = {
                            'status': status.HTTP_400_BAD_REQUEST,
                            'success': False,
                            'response': serializer.errors
                    }
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)
            if request_customer == 1 or request_customer == '1':
                # question_data = request.data.get('question_answer')
                if not job_id:
                    context = {
                        "status": status.HTTP_200_OK,
                        "success": False,
                        'message': 'Job id is required.'
                    }
                    return Response(context, status=status.HTTP_200_OK)
                        
                # if not question_data:
                #     context = {
                #         "status": status.HTTP_200_OK,
                #         "success": False,
                #         'message': 'question and answer is required.'
                #     }
                #     return Response(context, status=status.HTTP_200_OK)
                 
                # question_data = json.loads(question_data)
                job = Technician_Assigned_Order_Item.objects.get(id=job_id)
               
                # for item in question_data:
                #     question_id = item.get('question_id')
                #     answer_text = item.get('answer')
                #     ans=Answer.objects.get(id=question_id,technician_assigned_job=job_id)
                #     ans.answer=answer_text
                #     ans.save()
                order_item=Order_Item.objects.get(id=job.order_item.id)
                job_time=Job_Time.objects.get(assigned_order_item=job,stop_time__isnull=True)
                technician_assigned_job = Technician_Assigned_Order_Item.objects.get(order_item=order_item, is_signature=False)
                accepted_images = request.FILES.getlist('accepted_images')
                serializer = ServiceSignatureSerializer(data=request.data)
                print(serializer)
                if serializer.is_valid():
                    service_signature=serializer.save()
                    service_signature_id = service_signature
                    if job.job_type==1:
                        job.working_status = 3  #Completed Installation
                    if job.job_type==2:
                        job.working_status = 7  #Completed Service 
                    job.job_status=4
                    job.customer_signature_required=True
                    job.job_complete_datetime=timezone.now()
                    job.job_completed=True
                    job.is_signature=True
                    job.save()
                    if order_item.service_type == 1:
                        order_item.installation_complete=True
                        order_item.status=10
                    elif order_item.service_type == 2:   
                        order_item.installation_complete=True
                        order_item.status=11
                    # if order_item.product.is_trade == 1:
                    #     Product.objects.filter(id=order_item.product.id).update(is_product=0)
                    job_time.stop_time = timezone.now()
                    job_time.save()
                    order_item.save()
                    # try:
                    #     unique_registration_ids = set()
                    #     get_registration_token = FCMDevice.objects.filter(user_id=get_logged_in_user, active=True) 
                    #     for i in get_registration_token:
                    #         if i.registration_id not in unique_registration_ids:
                    #             sendPush(f'EXCITECH Australia - Job #{job.id} Completed','Signature Done By The Customer',[i.registration_id])     
                    #             unique_registration_ids.add(i.registration_id)
                    # except FCMDevice.DoesNotExist:
                    #     print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    # except Exception as e:
                    #     print(f"Error sending push notification: {e}")
                    
                    # try:
                    #     unique_registration_ids = set()
                    #     get_registration_token = FCMDevice.objects.filter(user_id=job.technician.id, active=True)
                    #     for i in get_registration_token:
                    #         if i.registration_id not in unique_registration_ids:
                    #             sendPush(f'EXCITECH Australia - Job #{job.id} Completed',f'Signature Done By The Customer',[i.registration_id])     
                    #             unique_registration_ids.add(i.registration_id)
                    # except FCMDevice.DoesNotExist:
                    #     print("FCMDevice not found for the specified conditions. Push notification not sent.")
                    # except Exception as e:
                    #     print(f"Error sending push notification: {e}")
    
                 
                    if accepted_images:
                        print(accepted_images)
                        for image_data in accepted_images:
                            data = {'accepted_image': image_data}
                            serializer = Accepted_ImageSerializer(data=data)
                            if serializer.is_valid():
                                serializer.save(service_signature=service_signature_id)
                            else:
                               return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
                    # answer = Answer.objects.filter(technician_assigned_job=job,answer__isnull = False) 
                    signature=Service_Signature.objects.get(job=job)
                    accepted_images = Accepted_Image.objects.filter(service_signature=signature)
                    # if answer:
                    #     pdf_data = generate_pdf(job, answer,signature,accepted_images)
                    #     if pdf_data:
                    #         job.pdf_file.save(f'job_{job.id}.pdf', pdf_data, save=True)
                            
                    #         subject = f'EXCITECH Australia -Job Checklist Details For Job Id: {job.id}'
                    #         message = f"Hi {job.order_item.order.invoice.customer},<br>"
                    #         message += "Please find technician attached checklist."
                    #         from_email = settings.FROM_EMAIL #job.technician.email # Replace with your email address
                    #         recipient_email =job.order_item.order.invoice.customer.email  # Use the customer's email address
                    #         email = EmailMessage(subject, message, from_email, [recipient_email])
                            
                            
                    #         pdf_file_path = job.pdf_file.path 
                    #         email.attach_file(pdf_file_path, 'application/pdf')
                    #         email.content_subtype = 'html'
                    #         email.send()
                            
                    #         ci = Customer_Info.objects.filter(customer__id = job.order_item.order.invoice.customer.id,user__is_communication = 1)
                    #         if ci:
                    #             for additional_email in  ci:
                    #                 email = EmailMessage(subject, message, from_email, [additional_email.user.email])
                    #                 email.attach_file(pdf_file_path, 'application/pdf')
                    #                 email.content_subtype = 'html'
                    #                 email.send()
    
                    context = {
                        'status': status.HTTP_201_CREATED,
                        'success': True,
                        'response':'Submit signature successfully',
                    }
                    return Response(context,  status=status.HTTP_201_CREATED)   
                else:
                    context = {
                            'status': status.HTTP_400_BAD_REQUEST,
                            'success': False,
                            'response': serializer.errors
                    }
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)
            context = {
                        'status': status.HTTP_400_BAD_REQUEST,
                        'success': False,
                        'response': serializer.errors
                }
            return Response(context, status=status.HTTP_400_BAD_REQUEST)
        except Exception as exception:
            return get_exception_context(exception)            

class PDFAPIView(APIView):
    def get(self, request, job_id, *args, **kwargs):
        job = get_object_or_404(Technician_Assigned_Order_Item, id=job_id)
        # Assuming job.pdf is the PDF file associated with the job
        # Replace 'pdf' with the actual field name in your model if needed
        pdf_file = job.pdf_file
        if pdf_file:
            response = FileResponse(pdf_file, as_attachment=True, filename=f'job_{job_id}.pdf')
            return response
        else:
            return Response({'error': 'PDF not found'}, status=status.HTTP_404_NOT_FOUND)

def generate_pdf(job, answer,signature,accepted_images):

    template = get_template('pages/check_list/checklist_pdf.html')
    context = {
        'job': job,
        'answer': answer,
        'signature':signature,
        'accepted_images':accepted_images,
    }
    html_content = template.render(context)

    pdf_buffer = BytesIO()
    result = pisa.CreatePDF(html_content, dest=pdf_buffer)

    if result.err:
       
        return None

    pdf_buffer.seek(0)
    return pdf_buffer
    
class SignatureUpdateAPIView(APIView):
    def put(self, request, pk):
        try:
            order_item = Technician_Assigned_Order_Item.objects.get(pk=pk)
            serializer = TechnicianAssignedOrderItemSerializer(order_item, data=request.data)

            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        except Technician_Assigned_Order_Item.DoesNotExist:
            return Response({'error': 'Technician_Assigned_Order_Item not found.'}, status=status.HTTP_404_NOT_FOUND)
    
class CustomerQuestionAnswerListAPIView(APIView):
    authentication_classes = []
    def getold(self, request,order_item_id, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            
            order_item=Order_Item.objects.get(id=order_item_id)
            print(order_item)
            technician_assigned_job = Technician_Assigned_Order_Item.objects.filter(order_item=order_item,is_signature=True,deleted_at__isnull=True).first()

            answers = Answer.objects.filter(
                technician_assigned_job__order_item__order__invoice__customer__user__id=get_logged_in_user,technician_assigned_job=technician_assigned_job)
          

            grouped_data = {}
            for answer in answers:
                
                
                checklist_name = answer.question.checklist.checklist_name if answer.question and answer.question.checklist else ''
                type = answer.question.checklist.get_type() if answer.question and answer.question.checklist and hasattr(answer.question.checklist, 'get_type') else ''
                is_part = answer.question.checklist.is_part if answer.question and answer.question.checklist else ''

                heading = answer.question.heading.heading if answer.question.heading else ''
                subheading = answer.question.subheading.subheading if answer.question.subheading else ''

                question_data = {
                    "job_id": answer.technician_assigned_job.id,
                    "question_id": answer.id,
                    "question": answer.question.question,
                    "answer": answer.get_answer_display(),
                    "comment": answer.comment,
                    "is_parts":answer.is_parts,
                }
                
                

                key = (checklist_name, type, is_part)
                if key not in grouped_data:
                    grouped_data[key] = {"headings": {}}

                if heading not in grouped_data[key]["headings"]:
                    grouped_data[key]["headings"][heading] = {"subheadings": {}}

                if subheading not in grouped_data[key]["headings"][heading]["subheadings"]:
                    grouped_data[key]["headings"][heading]["subheadings"][subheading] = {"questions": []}

                grouped_data[key]["headings"][heading]["subheadings"][subheading]["questions"].append(question_data)
                
                if answer.is_parts:
                    question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                
                
                

            result = []
            for key, data in grouped_data.items():
                checklist_name, type, is_part = key
                checklist_data = {
                    "checklist_name": checklist_name ,
                    "type": type,
                    "is_part": is_part,
                    "headings": [],
                }

                for heading, subheading_data in data["headings"].items():
                    heading_data = {
                        "heading": heading,
                        "subheadings": [],
                    }

                    for subheading, questions_data in subheading_data["subheadings"].items():
                        subheading_data = {
                            "subheading": subheading,
                            "questions": questions_data["questions"],
                        }

                        heading_data["subheadings"].append(subheading_data)

                    checklist_data["headings"].append(heading_data)

                result.append(checklist_data)

            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': result,
            }

            return Response(context, status=status.HTTP_200_OK)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
            
    def get_parts_detail(self, job_id):
            try:
                   
                parts_details = Parts_Request.objects.filter(technician_assigned_job_id=job_id).values()
                return parts_details
            except Exception as e:
                print(f"Error in get_parts_detail: {e}")
                return None
    
    def get(self, request, *args,job_id, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            answers = Answer.objects.filter(
                technician_assigned_job__order_item__order__invoice__customer__user__id=get_logged_in_user,technician_assigned_job=job_id,
                is_parts=0,is_warrenty=0
            )
            print(answers)
            grouped_data = {}
            for answer in answers:
                checklist_name = answer.question.checklist.checklist_name
                type = answer.question.checklist.get_type()
                is_part = answer.question.checklist.is_part
                heading = answer.question.heading.heading
                if answer.question.subheading:
                    subheading = answer.question.subheading.subheading
                else:
                    subheading = ''
                    

                question_data = {
                    "job_id": answer.technician_assigned_job.id,
                    "question_id": answer.id,
                    "question": answer.question.question,
                    "answer": answer.get_answer_display(),
                    "comment": answer.comment,
                    "is_parts":answer.is_parts,
                    "subheading":subheading
                }
                
                

                key = (checklist_name, type, is_part)
                if key not in grouped_data:
                    grouped_data[key] = {"headings": {}}

                if heading not in grouped_data[key]["headings"]:
                    grouped_data[key]["headings"][heading] ={"questions": []}

                # if subheading not in grouped_data[key]["headings"][heading]["subheadings"]:
                #     grouped_data[key]["headings"][heading]["subheadings"][subheading] = {"questions": []}

                grouped_data[key]["headings"][heading]["questions"].append(question_data)
                
                if answer.is_parts:
                    question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                    
          
                    
                    
                
            answers = Answer.objects.filter(
                technician_assigned_job__order_item__order__invoice__customer__user__id=get_logged_in_user,technician_assigned_job=job_id,
            ).filter(Q(question__id=137) | Q(question__id=178))
            
            print("deepak",answers)
            for answer in answers:
                checklist_name = ''
                type = ' '
                is_part = True
                heading = 'Service Question'
                subheading = ''

                question_data = {
                    "job_id": answer.technician_assigned_job.id,
                    "question_id": answer.id,
                    "question": answer.question.question,
                    "answer": answer.get_answer_display(),
                    "comment": answer.comment,
                    "is_parts":answer.is_parts,
                    "subheading":subheading
                }
                key = (checklist_name, type, is_part)
                if key not in grouped_data:
                    grouped_data[key] = {"headings": {}}

                if heading not in grouped_data[key]["headings"]:
                    grouped_data[key]["headings"][heading] ={"questions": []}

                grouped_data[key]["headings"][heading]["questions"].append(question_data)
                
                if answer.is_parts:
                    question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                   

            result = []
            for key, data in grouped_data.items():
                checklist_name, type, is_part = key
                checklist_data = {
                    "checklist_name": checklist_name,
                    "type": type,
                    "is_part": is_part,
                    "headings": [],
                }

                for heading ,questions_data in data["headings"].items():
                    heading_data = {
                        "heading": heading,
                        "questions": questions_data["questions"],
                        # "subheadings": [],
                    }

                    # for questions_data in subheading_data["subheadings"].items():
                    #     subheading_data = {
                    #         "subheading": subheading,
                    #         "questions": questions_data["questions"],
                    #     }

                    # heading_data["headings"].append(heading_data)

                    checklist_data["headings"].append(heading_data)

                result.append(checklist_data)
           
            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': result,
            }

            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    # def get(self, request, *args,order_item_id, **kwargs):
    #     try:
    #         token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
    #         valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
    #         get_logged_in_user = valid_data['user_id']
            
    #         order_item=Order_Item.objects.get(id=order_item_id)
           
    #         technician_assigned_job = Technician_Assigned_Order_Item.objects.filter(order_item=order_item,is_signature=True).first()


    #         answers = Answer.objects.filter(
    #           technician_assigned_job__order_item__order__invoice__customer__id=get_logged_in_user,technician_assigned_job=technician_assigned_job,
                
    #         )
            

    #         grouped_data = {}
    #         for answer in answers:
    #             checklist_name = answer.question.checklist.checklist_name
    #             type = answer.question.checklist.get_type()
    #             is_part = answer.question.checklist.is_part
    #             heading = answer.question.heading.heading
    #             if answer.question.subheading:
    #                 subheading = answer.question.subheading.subheading
    #             else:
    #                 subheading = ''
                    

    #             question_data = {
    #                 "job_id": answer.technician_assigned_job.id,
    #                 "question_id": answer.id,
    #                 "question": answer.question.question,
    #                 "answer": answer.get_answer_display(),
    #                 "comment": answer.comment,
    #                 "is_parts":answer.is_parts,
    #                 "subheading":subheading
    #             }
                
                

    #             key = (checklist_name, type, is_part)
    #             if key not in grouped_data:
    #                 grouped_data[key] = {"headings": {}}

    #             if heading not in grouped_data[key]["headings"]:
    #                 grouped_data[key]["headings"][heading] ={"questions": []}

    #             # if subheading not in grouped_data[key]["headings"][heading]["subheadings"]:
    #             #     grouped_data[key]["headings"][heading]["subheadings"][subheading] = {"questions": []}

    #             grouped_data[key]["headings"][heading]["questions"].append(question_data)
                
    #             if answer.is_parts:
    #                 question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                
    #         answers = Answer.objects.filter(
                
    #             technician_assigned_job__order_item__order__invoice__customer__user__id=get_logged_in_user,technician_assigned_job=technician_assigned_job,question__id=137
    #             )    
    #         for answer in answers:
    #             checklist_name = ''
    #             type = ' '
    #             is_part = True
    #             heading = ''
    #             subheading = ''

    #             question_data = {
    #                 "job_id": answer.technician_assigned_job.id,
    #                 "question_id": answer.id,
    #                 "question": answer.question.question,
    #                 "answer": answer.get_answer_display(),
    #                 "comment": answer.comment,
    #                 "is_parts":answer.is_parts,
    #                 "subheading":subheading
    #             }
    #             key = (checklist_name, type, is_part)
    #             if key not in grouped_data:
    #                 grouped_data[key] = {"headings": {}}

    #             if heading not in grouped_data[key]["headings"]:
    #                 grouped_data[key]["headings"][heading] ={"questions": []}

    #             grouped_data[key]["headings"][heading]["questions"].append(question_data)
                
    #             if answer.is_parts:
    #                 question_data["parts_detail"] = self.get_parts_detail(answer.technician_assigned_job.id)
                   

    #         result = []
    #         for key, data in grouped_data.items():
    #             checklist_name, type, is_part = key
    #             checklist_data = {
    #                 "checklist_name": checklist_name,
    #                 "type": type,
    #                 "is_part": is_part,
    #                 "headings": [],
    #             }

    #             for heading ,questions_data in data["headings"].items():
    #                 heading_data = {
    #                     "heading": heading,
    #                     "questions": questions_data["questions"],
    #                     # "subheadings": [],
    #                 }

    #                 # for questions_data in subheading_data["subheadings"].items():
    #                 #     subheading_data = {
    #                 #         "subheading": subheading,
    #                 #         "questions": questions_data["questions"],
    #                 #     }

    #                 # heading_data["headings"].append(heading_data)

    #                 checklist_data["headings"].append(heading_data)

    #             result.append(checklist_data)
           
    #         context = {
    #             'status': status.HTTP_200_OK,
    #             'success': True,
    #             'response': result,
    #         }

    #         return Response(context, status=status.HTTP_200_OK)

    #     except ObjectDoesNotExist as e:
    #         return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

    #     except Exception as e:
    #         return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                    
            
    def get_parts_detail(self, job_id):
            try:
                   
                parts_details = Parts_Request.objects.filter(technician_assigned_job_id=job_id).values()
                return parts_details
            except Exception as e:
                print(f"Error in get_parts_detail: {e}")
                return None  
  
class PartDetailListAPIView(APIView):
    authentication_classes = []
    def get(self, request, *args,job_id, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            part_request = Parts_Request.objects.filter(
                technician_assigned_job__technician=get_logged_in_user,technician_assigned_job_id=job_id
            )
            serializer=PartsRequestSerializer(part_request,many=True)
            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': serializer.data,
            }
            return Response(context, status=status.HTTP_200_OK)

        except Exception as exception:
          
            return get_exception_context(exception)
            
            
     
    def post(self, request, *args,job_id, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']

            part_delete_id = request.data.get('part_delete_id')

            if not part_delete_id:
                context = {
                    "status": status.HTTP_200_OK,
                    "success": False,
                    'message': 'part delete id  is required.'
                }
                return Response(context, status=status.HTTP_200_OK)
     
            # parts_data = json.loads(parts_data)

            if part_delete_id:
        
                    part_request = Parts_Request.objects.filter(id=part_delete_id,
                            technician_assigned_job__technician=get_logged_in_user,technician_assigned_job_id=job_id
                        ).delete()
                    context = {
                        'status': status.HTTP_200_OK,
                        'success': True,
                        'response': 'successfully',
                    }

            return Response(context, status=status.HTTP_200_OK)

        except Exception as exception:
          
            return get_exception_context(exception)

class CustomerInvoiceListAPI(APIView):
    authentication_classes = []
    pagination_class = CustomPagination
    def get(self, request, *args, **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
            # customer=Customer.objects.get(id=get_logged_in_user)
            queryset = Invoice.objects.filter(customer__user__id= get_logged_in_user )
            print(queryset)
            
        
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(queryset, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''
            
            serializer_data = CustomerInvoiceSerializer(paginated_queryset, many=True)
            serializer = {
                'results': serializer_data.data,  # Use the serialized data here
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
            
            context ={
            "status": status.HTTP_200_OK,
            "success": True,
            "response": serializer
            }
            return Response(context,status=status.HTTP_200_OK)
            
        except Exception as exception:
            return get_exception_context(exception)
           
class ViewChecklist(APIView):
    def get(self, request, *args, job_id, **kwargs):
       
        try:
            token = request.META.get('HTTP_AUTHORIZATION', "").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']
            
            technician_assigned_job = Technician_Assigned_Order_Item.objects.get(
                id=job_id
            )
            print(technician_assigned_job)
            answers = Answer.objects.filter(
                Q(technician_assigned_job=technician_assigned_job),
                Q(is_parts=0),
                Q(question__checklist__type=3)
            )
            question_data = []
            for answer in answers:
                question_data.append({
                    "job_id": answer.technician_assigned_job.id,
                    "question_id": answer.id,
                    "question": answer.question.question,
                    "answer": answer.get_answer_display(),
                })
        
            if technician_assigned_job.order_item.product.is_product :
                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response': [],
                }
            else:
                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response': question_data,
                }

            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    
   
                    
            
# class JobTimerAPIView(APIView):
  
#     authentication_classes = []
#     def post(self, request, job_id):
#         # return HttpResponse('hello')
#         try:
#             token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
#             valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
#             get_logged_in_user = valid_data['user_id']
#             assigned_order_item=Technician_Assigned_Order_Item.objects.get(id=job_id,technician=get_logged_in_user)
            
            
            
#             serializer = JobTimerSerializer(assigned_order_item,data=request.data)
            
#             if serializer.is_valid():
#                 serializer.save()
                
#                 context = {
#                         "status": status.HTTP_201_CREATED,
#                         "success": True,
#                         'message': 'Successfully Submit Timer Time.'
                    
#                 }
          
#                 return Response(context, status=status.HTTP_201_CREATED)
                
#             else:
#                 context = {
#                         'status': status.HTTP_400_BAD_REQUEST,
#                         'success': False,
#                         'response': serializer.errors
#                 }
#                 return Response(context, status=status.HTTP_400_BAD_REQUEST)           
            
#         except Exception as e:
#             return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)    
            
            
      

 
class JobIntervalStartStopAPIView(APIView):
    authentication_classes = []
    def post(self, request):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            get_logged_in_user = valid_data['user_id']
           
            serializer = JobIntervalTimeSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save(technician_id=get_logged_in_user)
                        
                context = {
                    'status': status.HTTP_201_CREATED,
                    'success': True,
                    'response': 'Successfully Submit Timer Time.',
                }
                return Response(context, status=status.HTTP_201_CREATED)
            else:
                context = {
                    'status': status.HTTP_400_BAD_REQUEST,
                    'success': False,
                    'response': serializer.errors
                }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)      
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)        

class AssignedLeadListWithoutPaginationAPI(APIView):    
    pagination_class = CustomPagination
    def get(self, request, *args,  **kwargs):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', "").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']
            # search_key = request.GET.get('search_key', '').strip()
            leads = Lead.objects.filter(deleted_at__isnull=True)
            
            # serializer = LeadSerializer(leads, many=True)
            # if search_key:
            #     leads = leads.filter(
            #         Q(first_name__icontains=search_key) |
            #         Q(last_name__icontains=search_key) |
            #         Q(company_name__icontains=search_key) |
            #         Q(work_phone__icontains=search_key) |
            #         Q(mobile__icontains=search_key) |
            #         Q(email__icontains=search_key)
            #     )
            # leads = leads.order_by('-id')
            search_fields = ['lead_id','first_name', 'last_name', 'company_name', 'work_phone', 'mobile', 'email','lead_source','business_type','address','products','status']

            # Dynamically build Q object based on provided params
            search_filters = Q()
            for field in search_fields:
                value = request.GET.get(field)
                if value:
                    print(value)
                    value = value.strip()
                    
                    if field == 'products':
                        product_list = [p.strip() for p in value.split(',')]  # assume comma-separated product names or IDs
                        search_filters &= Q(products__in=product_list)
                    if field == 'status':
                        search_filters &= Q(status=value)
                    elif field == 'lead_id':
                        if value.isdigit():  # extra safety check
                            search_filters &= Q(id=int(value))
                    
                    elif field == 'address':
                        # Check multiple address subfields using OR logic
                        address_filter = (
                            Q(post_code__icontains=value) |
                            Q(street__icontains=value) |
                            Q(city__icontains=value) |
                            Q(country__icontains=value)
                        )
                        search_filters &= address_filter
                    
                    else:
                        # Default to icontains
                        kwargs = {f"{field}__icontains": value}
                        search_filters &= Q(**kwargs)
            if search_filters:
                leads = leads.filter(search_filters)
            leads = leads.prefetch_related(  Prefetch('notes', queryset=Leadnote.objects.order_by('-created_at')) ).order_by('-created_at')
          
            
            
            serializer_data = LeadSerializer(leads, many=True)

            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': {
                    'results': serializer_data.data,
                    'next': None,
                    'previous': None,
                    'total_pages': 1,
                },
            }
            
            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                  
class AssignedLeadListAPI(APIView):
    pagination_class = CustomPagination

    def _get_user_id_from_auth(self, request):
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        parts = auth_header.split()
        if len(parts) != 2:
            return None, 'Missing or malformed Authorization header'
        token = parts[1]
        try:
            data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            return data.get('user_id'), None
        except Exception as e:
            return None, f'Invalid token: {e}'

    def get(self, request, *args, **kwargs):
        try:
            user_id, err = self._get_user_id_from_auth(request)
            if err:
                return Response({'error': err}, status=drf_status.HTTP_401_UNAUTHORIZED)
    
            leads = Lead.objects.filter(deleted_at__isnull=True)
            print(f">>> Found {leads.count()} leads", flush=True)
    
            # Build search filters
            search_fields = [
                'lead_id', 'first_name', 'last_name', 'company_name', 'work_phone',
                'mobile', 'email', 'lead_source', 'business_type', 'address','assigned_to',
                'products', 'status'
            ]
            print(request.GET)
            q = Q()
            any_filter = False
    
            for field in search_fields:
                raw = request.GET.get(field)
                if not raw:
                    continue
                value = raw.strip()
    
                if field == 'products':
                    ids = [int(p) for p in value.split(',') if p.strip().isdigit()]
                    if ids:
                        q &= Q(products__id__in=ids)
                        any_filter = True
                elif field == 'status':
                    try:
                        q &= Q(status=int(value))
                    except ValueError:
                        q &= Q(status=value)
                    any_filter = True
                elif field == 'lead_id':
                    if value.isdigit():
                        q &= Q(id=int(value))
                        any_filter = True
                elif field == 'assigned_to':
                    if value.isdigit():
                        q &= Q(assigned_to=int(value))
                        any_filter = True
                elif field == 'address':
                    q &= (
                        Q(post_code__icontains=value) |
                        Q(street__icontains=value) |
                        Q(city__icontains=value) |
                        Q(country__icontains=value)
                    )
                    any_filter = True
                else:
                    q &= Q(**{f"{field}__icontains": value})
                    any_filter = True
            start_date = request.GET.get('start_date')
            end_date = request.GET.get('end_date')
            date_field = request.GET.get('date_field')  # created_at OR demo_date
            
            if start_date or end_date or date_field:
                if start_date or end_date:
                    if not date_field:
                        return Response({"message": "date_field is required if start_date or end_date is provided"}, status=400)
                
                    try:
                        start = datetime.strptime(start_date, "%d-%m-%Y") if start_date else None
                        end = datetime.strptime(end_date, "%d-%m-%Y") if end_date else None
                        # If field is DateTimeField, make end inclusive
                        if end:
                            end = end + timedelta(days=1) - timedelta(seconds=1)
                    except ValueError:
                        return Response({"message": "Invalid date format, should be DD-MM-YYYY"}, status=400)
                    print(start)
                    print(end)
                    # if start and end:
                    #     q &= Q(**{f"{date_field}__range": [start, end]})
                    # elif start:
                    #     q &= Q(**{f"{date_field}__gte": start})
                    # else:  # only end
                    #     q &= Q(**{f"{date_field}__lte": end})
                
                    
                    
                    if start and end:
                        print(start,end)
                        if date_field == "note_date": 
                            end = datetime.strptime(end_date, "%d-%m-%Y").date()# only leads with notes in range
                            start = datetime.strptime(start_date, "%d-%m-%Y").date()# only leads with notes in range
                            print(start,end)
                            leads = leads.filter(
                                notes__reminder_date__isnull=False,
                                notes__deleted_at__isnull=True,
                                notes__reminder_date__range=[start, end]
                            ).distinct()
                        else:
                            filter_kwargs = {f"{date_field}__range": [start, end]}
                            leads = leads.filter(**filter_kwargs)
                        print('both')
                    elif start:
                        if date_field == "note_date":
                            # end = datetime.strptime(end_date, "%d-%m-%Y").date()# only leads with notes in range
                            start = datetime.strptime(start_date, "%d-%m-%Y").date()# only leads with notes in range
                            leads = leads.filter(
                                notes__reminder_date__isnull=False,
                                notes__deleted_at__isnull=True,
                                notes__reminder_date__gte=start
                            ).distinct()
                        else:
                            filter_kwargs = {f"{date_field}__gte": start}
                            leads = leads.filter(**filter_kwargs)
                        print('start')
                    elif end:
                        if date_field == "note_date":
                            end = datetime.strptime(end_date, "%d-%m-%Y").date()# only leads with notes in range
                            # start = datetime.strptime(start_date, "%d-%m-%Y").date()# only leads with notes in range
                            leads = leads.filter(
                                notes__reminder_date__isnull=False,
                                notes__deleted_at__isnull=True,
                                notes__reminder_date__lte=end
                            ).distinct()
                        else:
                            filter_kwargs = {f"{date_field}__lte": end}
                            leads = leads.filter(**filter_kwargs)
                    any_filter = True
                else:
                    return Response({"message": "start_date or end_date is required if date_field  is provided"}, status=400)        
                            
                            
            if any_filter:
                leads = leads.filter(q)
                print(f">>> After filtering: {leads.count()} leads", flush=True)
    
            # Prefetch safely
            try:
                # leads = leads.prefetch_related(
                #     Prefetch('notes', queryset=Leadnote.objects.order_by('-created_at'))
                # ).order_by('-created_at')
                
                leads = (
                leads
                .annotate(latest_note=Max('notes__updated_at'))
                .annotate(
                    last_updated=Case(
                        When(latest_note__gt=F('updated_at'), then=F('latest_note')),
                        default=F('updated_at'),
                        output_field=DateTimeField()
                    )
                )
                    .order_by('-last_updated')
                )
                leads = leads.prefetch_related(
                    Prefetch('notes', queryset=Leadnote.objects.order_by('-created_at'))
                )
            except Exception as pf_err:
                print(f"!!! Prefetch error: {pf_err}", flush=True)
                # leads = leads.order_by('-created_at')
                leads = (
                leads
                .annotate(latest_note=Max('notes__updated_at'))
                .annotate(
                    last_updated=Case(
                        When(latest_note__gt=F('updated_at'), then=F('latest_note')),
                        default=F('updated_at'),
                        output_field=DateTimeField()
                    )
                )
                    .order_by('-last_updated')
                )
    
            # Pagination
            paginator = self.pagination_class()
            try:
                page_qs = paginator.paginate_queryset(leads, request)
            except Exception as pg_err:
                print(f"!!! Pagination error: {pg_err}", flush=True)
                page_qs = leads[:20]  # fallback to first 20
    
            print(f">>> Page queryset size: {len(page_qs)}", flush=True)
    
            # Serialize safely
            try:
                serializer_data = LeadSerializer(page_qs, many=True).data
            except Exception as s_err:
                print(f"!!! Serialization error: {s_err}", flush=True)
                serializer_data = []  # fallback
    
            next_page = paginator.get_next_link() if hasattr(paginator, 'get_next_link') else None
            previous_page = paginator.get_previous_link() if hasattr(paginator, 'get_previous_link') else None
            total_pages = 0
            if hasattr(paginator, 'page') and hasattr(paginator.page, 'paginator'):
                total_pages = paginator.page.paginator.num_pages
    
            payload = {
                'results': serializer_data,
                'next': next_page,
                'previous': previous_page,
                'total_pages': total_pages,
            }
    
            return Response({'status': drf_status.HTTP_200_OK, 'success': True, 'response': payload},
                            status=drf_status.HTTP_200_OK)
    
        except Exception as e:
            import traceback
            print(">>> GET exception:", e, flush=True)
            print(traceback.format_exc(), flush=True)
            return Response({'error': str(e), 'traceback': traceback.format_exc()},
                            status=drf_status.HTTP_500_INTERNAL_SERVER_ERROR)

    def post(self, request):
        try:
            qd = request.data.copy()
            user_id, err = self._get_user_id_from_auth(request)
            email = qd.get("email")
            print(qd)
            if email:  # only check if email is provided
                if Lead.objects.filter(email=email, deleted_at__isnull=True).exists():
                    return Response({'success': False, 'message': 'A lead with this email already exists'}, status=status.HTTP_200_OK)
                if User.objects.filter(email=email, deleted_at__isnull=True).exists():
                    return Response({'success': False, 'message': 'A Customer with this email already exists.'}, status=status.HTTP_200_OK)
            if err:
                return Response({'error': err}, status=drf_status.HTTP_401_UNAUTHORIZED)

            assigned_user = get_object_or_404(User, id=user_id)
            

            raw_products = request.data.getlist('products[]') or request.data.getlist('products')
            products = []
            for p in raw_products or []:
                try:
                    products.append(int(p))
                except (TypeError, ValueError):
                    pass
            qd.setlist('products', [str(i) for i in products])
            qd['created_by_id'] = str(assigned_user.id)
            # qd['assigned_to_id'] = str(assigned_user.id)

            # Normalize booleans and ints
            qd['is_individual'] = str(qd.get('is_individual')).lower() in ('true', '1', 'on')
            qd['is_active'] = str(qd.get('is_active')).lower() in ('true', '1', 'on')
            for k in ('status', 'business_type', 'lead_source'):
                if qd.get(k) in ('', None):
                    qd[k] = None
                else:
                    try:
                        qd[k] = int(qd[k])
                    except ValueError:
                        pass

            if qd.get('status') in (None, ''):
                qd['status'] = 1

            if str(qd['status']) == '5':
                demo_date = request.data.get('demo_date')
                if demo_date:
                    qd['demo_date'] = datetime.strptime(demo_date, "%d-%m-%Y").strftime("%Y-%m-%d")
                demo_time = request.data.get('demo_time')
                if demo_time:
                    qd['demo_time'] = demo_time
            qd['assigned_to_id']=int(qd.get("assigned_to_id"))
            print(qd)
            serializer = LeadSerializer(data=qd)
            if serializer.is_valid():
                obj = serializer.save()
                print(">>> CREATED LEAD:", obj.id, flush=True)
                # Return a minimal safe JsonResponse (bypasses DRF renderer)
                return JsonResponse({"success": True, "id": obj.id}, status=201)
    
            print(">>> VALIDATION FAILED:", serializer.errors, flush=True)
            return JsonResponse({"success": False, "errors": serializer.errors}, status=400)
        
        except Exception as e:
            import traceback
            print(">>> CRASH:", e, traceback.format_exc(), flush=True)
            raise  # Let Django show full error page since DEBUG=True
            
class SendProductPDFsAPIView(APIView):

    def post(self, request):

        lead_id = request.data.get("lead_id")

        if not lead_id:
            return Response(
                {"error": "lead_id is required"},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            customer = Lead.objects.get(id=lead_id)
        except Lead.DoesNotExist:
            return Response(
                {"error": "Lead not found"},
                status=status.HTTP_404_NOT_FOUND
            )

        products = (
            Product.objects
            .filter(deleted_at__isnull=True)
            .prefetch_related('specification_pdfs', 'manual_pdfs')
        )

        selected_products = []
        is_spec = set()
        is_user_manual = set()

        email = EmailMessage(
            subject="EXCITECH Australia - Product Specification",
            body="",
            from_email=settings.FROM_EMAIL,
            to=['hari@beedev.co.in'],
            # to=[customer.email] if customer.email else [],
        )

        # 🔹 SAME LOGIC AS WEB (just using request.data)
        for product in products:

            send_spec = request.data.get(f"send_spec_{product.id}")
            send_manual = request.data.get(f"send_manual_{product.id}")

            is_product = False

            # --------- SPEC PDFs ----------
            if send_spec:
                for i, spec_pdf in enumerate(product.specification_pdfs.all(), start=1):
                    if spec_pdf.file and os.path.exists(spec_pdf.file.path):
                        is_product = True
                        with open(spec_pdf.file.path, "rb") as f:
                            email.attach(
                                f"{product.product_name}_Spec_{i}.pdf",
                                f.read(),
                                "application/pdf"
                            )
                        is_spec.add(product.id)

            # --------- MANUAL PDFs ----------
            if send_manual:
                for i, manual_pdf in enumerate(product.manual_pdfs.all(), start=1):
                    if manual_pdf.file and os.path.exists(manual_pdf.file.path):
                        is_product = True
                        with open(manual_pdf.file.path, "rb") as f:
                            email.attach(
                                f"{product.product_name}_Manual_{i}.pdf",
                                f.read(),
                                "application/pdf"
                            )
                        is_user_manual.add(product.id)

            if is_product:
                selected_products.append(product.product_name)

        if not selected_products:
            return Response(
                {"error": "No Products selected to send."},
                status=status.HTTP_400_BAD_REQUEST
            )

        # Render Email Template
        message = render_to_string(
            'pages/leads/productdetailsemail.html',
            {'lead': customer, 'selected_products': selected_products}
        )

        email.body = message
        email.content_subtype = 'html'

        # 🔹 DB Save (Atomic)
        try:
            with transaction.atomic():

                if is_user_manual:
                    ProductUserManualPDFSent.objects.bulk_create([
                        ProductUserManualPDFSent(product_id=pid, lead_id=lead_id)
                        for pid in is_user_manual
                    ])

                if is_spec:
                    ProductSpecificationPDFSent.objects.bulk_create([
                        ProductSpecificationPDFSent(product_id=pid, lead_id=lead_id)
                        for pid in is_spec
                    ])

        except Exception as e:
            return Response(
                {"error": f"Database Error: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

        # Send Email
        try:
            email.send(fail_silently=False)
        except Exception as e:
            return Response(
                {"error": f"Email sending failed: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

        return Response(
            {
                "success": True,
                "message": "Mail Sent Successfully",
                "sent_products": selected_products
            },
            status=status.HTTP_200_OK
        )

class LeadDetailAPI(APIView):
    def put(self, request, lead_id):
        try:
            lead = get_object_or_404(Lead, id=lead_id)
            data = request.data.copy()
            email = data.get("email")
            if email:  # only check if email is provided
                if Lead.objects.filter(email=email, deleted_at__isnull=True).exclude(id=lead_id).exists():
                    return Response({'success': False, 'message': 'A lead with this email already exists'}, status=status.HTTP_200_OK)
                if User.objects.filter(email=email, deleted_at__isnull=True).exists():
                    return Response({'success': False, 'message': 'A Customer with this email already exists.'}, status=status.HTTP_200_OK)
           # --- Normalize products ---
            raw_products = request.data.getlist('products[]') or request.data.getlist('products')
            if raw_products:
                cleaned_products = [int(p) for p in raw_products if str(p).isdigit()]
                data.setlist('products', [str(p) for p in cleaned_products])
            else:
                # Explicitly clear products if empty list is sent
                data.setlist('products', [])

            # --- Normalize status ---
            if not data.get('status'):
                data['status'] = 1
            else:
                try:
                    data['status'] = int(data['status'])
                except (TypeError, ValueError):
                    pass  # let serializer validate

            # --- Handle demo fields only if status == 5 ---
            lead_status = data.get("status")
            if str(lead_status) == '5':
                demo_date = request.data.get("demo_date")
                demo_time = request.data.get("demo_time")
                if demo_date:
                    try:
                        parsed_date = datetime.strptime(demo_date, "%d-%m-%Y")
                        data['demo_date'] = parsed_date.strftime("%Y-%m-%d")
                    except ValueError:
                        return Response({'error': 'Invalid date format. Use DD-MM-YYYY.'},
                                        status=status.HTTP_400_BAD_REQUEST)
                if demo_time:
                    data['demo_time'] = demo_time

            # --- Normalize booleans ---
            def to_bool(v): return str(v).lower() in ('true', '1', 'on', 'yes')
            if 'is_individual' in data:
                data['is_individual'] = to_bool(data['is_individual'])
            if 'is_active' in data:
                data['is_active'] = to_bool(data['is_active'])
            data['assigned_to_id']=int(request.data.get("assigned_to_id"))
            # --- Empty strings -> None for nullable fields ---
            for k in ('company_name', 'last_name', 'first_name', 'street', 'city', 'post_code',
                      'country', 'work_phone', 'email', 'abn'):
                if data.get(k) == '':
                    data[k] = None

            print(">>> Normalized data for update:", data, flush=True)

            serializer = LeadSerializer(lead, data=data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response({'success': True, 'message': 'Lead updated'}, status=status.HTTP_200_OK)

            print(">>> Serializer errors:", serializer.errors, flush=True)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            import traceback
            print(">>> PUT exception:", e, flush=True)
            print(traceback.format_exc(), flush=True)
            return Response({'error': str(e), 'traceback': traceback.format_exc()},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class listCustomerNoteAPI(APIView):
    pagination_class = CustomPagination

    def get_note_history(self, lead_id):
        # Get latest created_at for each groupid for this lead
        latest_notes = (
            Leadnote.objects.filter(
                groupid=lead_id,
                deleted_at__isnull=True
            )
            .values('groupid')
            .annotate(latest_created=Max('created_at'))
        )

        # Build filters for groupid and created_at
        filters = Q()
        for item in latest_notes:
            filters |= Q(groupid=item['groupid'], created_at=item['latest_created'])

        return Leadnote.objects.filter(
            groupid=lead_id,
            deleted_at__isnull=True
        ).order_by('-created_at')

    def get(self, request, *args, **kwargs):
        try:
            # Get JWT token and decode
            auth_header = request.META.get('HTTP_AUTHORIZATION', '')
            parts = auth_header.split(' ')
            if len(parts) != 2 or parts[0] != 'Bearer':
                return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)

            token = parts[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']

            # Get today's notes assigned to user
            # print(logged_in_user_id)
            # today = date.today()
            # leads = Leadnote.objects.filter(
            #     deleted_at__isnull=True,
            #     assigned_to__id=logged_in_user_id,
            #     reminder_date__isnull=False,
            #     reminder_date__lte=today,
            #     is_read=0,
            # ).order_by('-reminder_date') 
            today = date.today()
            tomorrow = today + timedelta(days=1)
            day_after_tomorrow = today + timedelta(days=2)
            
            leads = Leadnote.objects.filter(
                deleted_at__isnull=True,
                assigned_to__id=logged_in_user_id,
                reminder_date__isnull=False,
                is_read=0,
            ).filter(
                Q(is_it_lead_demo=0, reminder_date__lte=today) |
                Q(is_it_lead_demo=1, reminder_date__range=[today, day_after_tomorrow])
            ).order_by('-reminder_date', '-meeting_time')

            # Paginate
            paginator = self.pagination_class()
            paginated_queryset = paginator.paginate_queryset(leads, request)
            next_page = paginator.get_next_link() or ''
            previous_page = paginator.get_previous_link() or ''
            total_pages = paginator.page.paginator.num_pages or ''

            # Serialize main notes
            serializer_data = LeadNoteCreateSerializer(paginated_queryset, many=True)

            # Add note history for each note's lead
            full_response = []
            for note_data in serializer_data.data:
                lead_id = note_data.get('lead')
                history_qs = self.get_note_history(note_data.get('groupid'))
                history_serialized = LeadNoteCreateSerializer(history_qs, many=True).data

                note_data['note_history'] = history_serialized
                full_response.append(note_data)

            context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': {
                    'results': full_response,
                    'next': next_page,
                    'previous': previous_page,
                    'total_pages': total_pages,
                }
            }
            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
class LeadNoteAPI(APIView):
    def get_note_history(self, lead_id):
        # Get latest created_at for each groupid for this lead
        latest_notes = (
            Leadnote.objects.filter(
                groupid=lead_id,
                deleted_at__isnull=True
            )
            .values('groupid')
            .annotate(latest_created=Max('created_at'))
        )

        # Build filters for groupid and created_at
        filters = Q()
        for item in latest_notes:
            filters |= Q(groupid=item['groupid'], created_at=item['latest_created'])

        return Leadnote.objects.filter(
            groupid=lead_id,
            deleted_at__isnull=True
        ).order_by('-created_at')
    def get(self, request, *args,  **kwargs):
        try:
            lead_id = kwargs.get('lead_id')
            auth_header = request.META.get('HTTP_AUTHORIZATION', '')
            parts = auth_header.split(' ')
            if len(parts) != 2 or parts[0] != 'Bearer':
                return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
            
            token = parts[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']
            
            # leads = Leadnote.objects.filter(deleted_at__isnull=True,lead__id=lead_id)
            latest_notes = (
                Leadnote.objects.filter(
                    lead_id=lead_id,
                    deleted_at__isnull=True
                )
                .values('groupid')
                .annotate(latest_created=Max('created_at'))
            )

            filters = Q()
            for item in latest_notes:
                filters |= Q(groupid=item['groupid'], created_at=item['latest_created'])

            # STEP 2: Get the latest notes only (per group)
            latest_notes_qs = Leadnote.objects.filter(
                deleted_at__isnull=True,
                lead_id=lead_id
            ).filter(filters).order_by('-created_at')

            # STEP 3: Serialize latest notes
            serializer = LeadNoteCreateSerializer(latest_notes_qs, many=True)
            # print(technician_assigned_job)
            # serializer = LeadNoteCreateSerializer(leads, many=True)
            full_response = []
            for note_data in serializer.data:
                lead_id = note_data.get('lead')
                history_qs = self.get_note_history(note_data.get('groupid'))
                history_serialized = LeadNoteCreateSerializer(history_qs, many=True).data

                note_data['note_history'] = history_serialized
                full_response.append(note_data)
            if not latest_notes_qs :
                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response': [],
                }
            else:
                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response': full_response, #serializer.data,
                }

            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
class AddCustomerNoteAPI(APIView):
    def post(self, request, lead_id):
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        get_logged_in_user = valid_data['user_id']
        lead = get_object_or_404(Lead, id=lead_id)
        logged_in_user_id = valid_data['user_id']
        data = request.data.copy()
        # print(data)
        # userid = data.get('userid')
        # assigned_user = get_object_or_404(User, id=get_logged_in_user) if get_logged_in_user else None
        assigned_user = get_object_or_404(User, id=logged_in_user_id) if logged_in_user_id else None
        if data.get("assigned_to"):
            assigned_user = get_object_or_404(User, id=data.get("assigned_to"))
        last_group = Leadnote.objects.order_by('-groupid').first()
        next_group_id = (last_group.groupid + 1) if last_group else 1
        # userid = request.POST.get("assigned_to") or None
        # meeting_time =request.data.get('meeting_time') or None
        input_date = data.get('reminder_date')  # e.g., "30-05-2025"
        # reminder_date = None
        
        # if input_date:
        #     try:
        #         parsed_date = datetime.strptime(input_date, "%d-%m-%Y")
        #         reminder_date = parsed_date.strftime("%Y-%m-%d")
        #         meeting_time =meeting_time
        #     except ValueError:
        #         return Response({'error': 'Invalid date format. Use DD-MM-YYYY.'}, status=400)
        reminder_date = None
        if input_date:
            try:
                parsed_date = datetime.strptime(input_date, "%d-%m-%Y")
                reminder_date = parsed_date.date()  # ✅ return date object, not string
            except ValueError:
                return Response({'error': 'Invalid date format. Use DD-MM-YYYY.'}, status=400)
        meeting_time_str = request.POST.get('meeting_time')

        meeting_time = None
        # if meeting_time_str:
        #     try:
        #         meeting_time = datetime.strptime(meeting_time_str, "%H:%M").time()
        #     except ValueError:
        #         meeting_time = None  # fallback if invalid
        if meeting_time_str:
            for fmt in ("%H:%M:%S", "%H:%M"):
                try:
                    meeting_time = datetime.strptime(meeting_time_str, fmt).time()
                    break
                except ValueError:
                    continue
        # if not userid == None:
        #     assigned_user = get_object_or_404(User, id=userid)
        note_instance = Leadnote(
            lead=lead,
            note=data.get('note'),
            reminder_date= reminder_date,
            created_by=assigned_user, #request.user,
            assigned_to=assigned_user,
            groupid=next_group_id,
            meeting_invitation=int(data.get('meeting_invitation', 0)),
            meeting_time =meeting_time,
            meet_link=data.get('meet_link'),
        )
        note_instance.save()
        return Response({'message': 'Note added successfully'}, status=status.HTTP_201_CREATED)
        
class updateCustomerNoteAPI(APIView):
    def put(self, request, lead_id, note_id):
        return self._handle_note_save(request, lead_id, note_id)

    def _handle_note_save(self, request, lead_id, note_id=None):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']

            lead = get_object_or_404(Lead, id=lead_id)
            data = request.data.copy()

            print(data)
            if request.data.get("assigned_to"):
                assigned_user = get_object_or_404(User, id=request.data.get("assigned_to"))
            else:
                assigned_user = get_object_or_404(User, id=logged_in_user_id) if logged_in_user_id else None

            # input_date = data.get('reminder_date')  # e.g., "30-05-2025"
            # reminder_date = None
            # meeting_time =request.data.get('meeting_time') or None
            meeting_time_str = request.POST.get('meeting_time')
            meeting_time = None
            if meeting_time_str:
                for fmt in ("%H:%M:%S", "%H:%M"):
                    try:
                        meeting_time = datetime.strptime(meeting_time_str, fmt).time()
                        break
                    except ValueError:
                        continue
            # if meeting_time_str:
            #     try:
            #         meeting_time = datetime.strptime(meeting_time_str, "%H:%M").time()
            #     except ValueError:
            #         meeting_time = None  # fallback if invalid
            input_date = data.get('reminder_date')  # e.g., "30-05-2025"
            reminder_date = None
            if input_date:
                try:
                    parsed_date = datetime.strptime(input_date, "%d-%m-%Y")
                    reminder_date = parsed_date.date()  # ✅ return date object, not string
                except ValueError:
                    return Response({'error': 'Invalid date format. Use DD-MM-YYYY.'}, status=400)
            # if input_date:
            #     try:
            #         parsed_date = datetime.strptime(input_date, "%d-%m-%Y")
            #         reminder_date = parsed_date.strftime("%Y-%m-%d")
            #     except ValueError:
            #         return Response({'error': 'Invalid date format. Use DD-MM-YYYY.'}, status=400)
            
            if note_id:
                note_instance = get_object_or_404(Leadnote, id=note_id, lead_id=lead_id)
            else:
                last_group = Leadnote.objects.order_by('-groupid').first()
                next_group_id = (last_group.groupid + 1) if last_group else 1
                note_instance = Leadnote(groupid=next_group_id)

            note_instance.lead = lead
            note_instance.note = data.get('note')
            note_instance.reminder_date = reminder_date
            note_instance.created_by = assigned_user  # or use `logged_in_user_id`
            note_instance.assigned_to = assigned_user
            note_instance.meeting_invitation = int(data.get('meeting_invitation', 0))
            note_instance.meeting_time =meeting_time
            note_instance.meet_link = data.get('meet_link')
            note_instance.save()

            return Response({'message': 'Note saved successfully'}, status=status.HTTP_200_OK if note_id else status.HTTP_201_CREATED)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    def delete(self, request, lead_id, note_id):
        try:
            # Optional: verify token
            token = request.META.get('HTTP_AUTHORIZATION', ' ').split(' ')[1]
            TokenBackend(algorithm='HS256').decode(token, verify=False)

            note = get_object_or_404(Leadnote, id=note_id, lead_id=lead_id)

            # Soft delete if using `deleted_at`
            note.deleted_at = timezone.now()
            note.save()

            # Hard delete (optional):
            # note.delete()

            return Response({'message': 'Note deleted successfully'}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class LeadDeleteAPI(APIView):
    def delete(self, request, lead_id):
        try:
            lead = get_object_or_404(Lead, id=lead_id)
            lead.delete()
            return Response({'message': 'Lead deleted successfully.'}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class UpdatereadNoteAPI(APIView):
    def post(self, request, note_id):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']
            data = request.data.copy()
            if note_id:
                note_instance = get_object_or_404(Leadnote, id=note_id)
                note_instance.is_read = 1
                note_instance.save()
    
            return Response({'message': 'Note Read successfully'}, status=status.HTTP_200_OK if note_id else status.HTTP_201_CREATED)
    
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class ProductListAPI(APIView):
    def get(self, request):
        products = Product.objects.filter(deleted_at__isnull=True ,is_active=1 ).order_by('category__category_name')
        serializer = ProductSerializer(products, many=True)
        return Response(serializer.data)

class SalesUserListAPI(APIView):
    def get(self, request):
        # excluded_role_ids = [1, 3, 4, 5]
        # users = User.objects.filter(deleted_at__isnull=True, is_superuser=0).exclude(role__id__in=excluded_role_ids)
        # users = User.objects.filter( deleted_at__isnull=True, is_superuser=0, role__id=2 ) #.distinct()
        excluded_role_ids = [1,4,5]  #
        users = User.objects.filter(deleted_at__isnull=True,role__id=2) #.exclude(role__id__in=excluded_role_ids)
       
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

class CustomersListAPI(APIView):
    pagination_class = CustomPagination
    def get(self, request):
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        parts = auth_header.split(' ')
        if len(parts) != 2 or parts[0] != 'Bearer':
            return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
        
        token = parts[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        
        customers = Customer.objects.filter(deleted_by__isnull=True)
        allcustomers = Customer.objects.filter(deleted_by__isnull=True)
        customer_id=request.GET.get('customer_id')
        if customer_id:
            customers =  customers.filter(Q(id=customer_id) )
        email=request.GET.get('email')
        if email:
            email = request.GET.get('email').strip()
            customers = customers.filter(email__icontains=email)
        phone=request.GET.get('phone')
        if phone:
            phone = request.GET.get('phone').strip()
            customers = customers.filter(phone1__icontains=phone)
        customer_status=request.GET.get('status')
        if customer_status:
            customers = customers.filter(is_active=customer_status)
        address = request.GET.get('address')
        if address:
            address = address.strip()
            customers = customers.filter(
                Q(state__icontains=address) |
                Q(city__icontains=address) |
                Q(street__icontains=address) |
                Q(country__icontains=address) |
                Q(post_code__icontains=address)
            )
        paginator = self.pagination_class()
        paginated_queryset = paginator.paginate_queryset(customers, request)
        next_page = paginator.get_next_link() or ''
        previous_page = paginator.get_previous_link() or ''
        total_pages = paginator.page.paginator.num_pages or ''
        
        serializer = CustomerSerializer(paginated_queryset, many=True)
        allcustomersserializer = CustomerSerializer(allcustomers, many=True)
        context = {
                'status': status.HTTP_200_OK,
                'success': True,
                'response': {
                    'results': serializer.data,
                    'all_customers': allcustomersserializer.data, 
                    'next': next_page,
                    'previous': previous_page,
                    'total_pages': total_pages,
                }
            }
        return Response(context, status=status.HTTP_200_OK)
        
class CustomersAPI(APIView):
    def put(self, request, customer_id):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']
            customer = get_object_or_404(Customer, id=customer_id)
            data = request.data.copy()

            # Basic fields
            print(data)
            customer_type = data.get('customer_type')
            is_active = data.get('is_active', False)

            # Lists
            first_names = data.getlist('first_name') if hasattr(data, 'getlist') else data.get('first_name', [])
            last_names = data.getlist('last_name') if hasattr(data, 'getlist') else data.get('last_name', [])
            emails = data.getlist('email[]') if hasattr(data, 'getlist') else data.get('email', [])
            phone_numbers = data.getlist('phone1') if hasattr(data, 'getlist') else data.get('phone1', [])
            is_primary = data.getlist('is_primary') if hasattr(data, 'getlist') else data.get('is_primary', [])
            customer_info_ids = data.getlist('customer_info_id[]') if hasattr(data, 'getlist') else data.get('customer_info_id', [])
            app_access = data.getlist('app_access[]') if hasattr(data, 'getlist') else data.get('app_access', [])
            send_credentials = data.getlist('send_credentials[]') if hasattr(data, 'getlist') else data.get('send_credentials', [])
            receive_emails = data.getlist('receive_emails[]') if hasattr(data, 'getlist') else data.get('receive_emails', [])
            delete_list =  data.getlist('deleted[]') if hasattr(data, 'getlist') else data.get('deleted', [])
            
            print(first_names)
            # Primary email
            primary_email = emails[0] if emails else None
            # try:
            # Update main customer User
            user = customer.user
            if user.email != primary_email:
                if User.objects.filter(email=primary_email).exclude(id=user.id).exists():
                    return Response({'success': True, 'message': 'Email already exists in the system.'}, status=status.HTTP_200_OK)
                    return Response(
                        {"error": "Email already exists in the system."},
                        status=400
                    )
            
            user.email = primary_email
            user.username = primary_email
            user.is_active = is_active
            user.app_access = 1
            user.isprimary = 1
            user.deleted_at = None
            user.is_communication = 1
            print(user)
            user.save()
            # except Exception as e:
            #     import traceback
            #     print("❌ Error:", str(e))
            #     print(traceback.format_exc())   # full stack trace
            #     return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            print('user')
            # Update main Customer record
            customer.first_name = first_names[0] if first_names else customer.first_name
            customer.last_name = last_names[0] if last_names else customer.last_name
            customer.company_name = data.get('company_name') if customer_type != "1" else None
            customer.is_individual = int(customer_type)
            customer.primary_mail = primary_email
            customer.is_primary = True if is_primary else False
            customer.is_active = is_active
            customer.updated_by_id = logged_in_user_id
            # Other fields
            customer.street = data.get('street')
            customer.city = data.get('city')
            customer.state = data.get('state')
            customer.post_code = data.get('post_code')
            customer.country = data.get('country')
            customer.phone1 = phone_numbers[0] if phone_numbers else None
            customer.phone2 = data.get('phone2')
            customer.phone3 = data.get('phone3')
            customer.fax = data.get('fax')
            customer.email = primary_email
            customer.website = data.get('website')
            customer.contact_name = data.get('contact_name')
            customer.salutation = data.get('salutation')
            customer.abn = data.get('abn')
            print(customer)
            customer.save()
            print('last')
            # Update/add Customer_Info
            if  delete_list:
            # dd(delete_list)
                for i in range(len(delete_list)):
                    deleted_value =delete_list[i]
                    if deleted_value == 0   or   deleted_value =='' :
                        pass
                    else:
                        c=Customer_Info.objects.filter(id=deleted_value).first()
                        # dd(c)
                        if c:
                            u=User.objects.get(id=c.user.id)
                            u.deleted_at = timezone.now()
                            u.save()
                            customerdetail = Customer_Info.objects.filter(id=deleted_value).delete()
            for i, email in enumerate(emails[1:], start=1):
                ci_id = customer_info_ids[i] if i < len(customer_info_ids) else None
                if ci_id and ci_id != '0':
                    ci = Customer_Info.objects.get(id=ci_id)
                else:
                    ci_user = User.objects.filter(email=email).first()
                    if not ci_user:
                        ci_user = User.objects.create(
                            username=email,
                            email=email,
                            app_access=app_access[i] if i < len(app_access) else 1,
                            is_communication=receive_emails[i] if i < len(receive_emails) else 1
                        )
                        ci_user.role.set('4')
                        ci_user.set_password('Excitech@123')
                        ci_user.save()
                    ci = Customer_Info(customer=customer, user=ci_user)
                # Update Customer_Info fields
                ci.email = email
                ci.first_name = first_names[i] if i < len(first_names) else ""
                ci.last_name = last_names[i] if i < len(last_names) else ""
                ci.phone1 = phone_numbers[i] if i < len(phone_numbers) else ""
                ci.position = data.getlist('position')[i-1] if 'position' in data else ""
                ci.is_primary = False
                ci.save()

                # Send credentials if requested
                if send_credentials[i] == '1':
                    subject = 'EXCITECH Australia - Your Account Credentials'
                    password = 'Excitech@123'
                    template_data = {'username': email, 'password': password}
                    message = render_to_string('pages/customer/cust_email_temp.html', template_data)
                    email_obj = EmailMessage(subject, message, settings.FROM_EMAIL, [email])
                    email_obj.content_subtype = 'html'
                    email_obj.send()
                    ci.user.is_sent_creadentials = 1
                    ci.user.reset_password = 1
                    ci.user.save()

            # TODO: MYOB integration (same logic as in your web view)
            
            return Response({'success': True, 'message': 'Customer updated successfully'}, status=status.HTTP_200_OK)
        
        except Exception as e:
            import traceback
            print("❌ Error:", str(e))
            print(traceback.format_exc())   # full stack trace
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            # return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    # def put(self, request, customer_id):
    #     try:
    #         auth_header = request.META.get('HTTP_AUTHORIZATION', '')
    #         parts = auth_header.split(' ')
    #         if len(parts) != 2 or parts[0] != 'Bearer':
    #             return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
            
    #         token = parts[1]
    #         valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
    #         token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
    #         lead = get_object_or_404(Customer, id=customer_id)
    #         data = request.data.copy()
    #         print(data)
    #         serializer = CustomerSerializer(lead, data=data, partial=True)
    #         if serializer.is_valid():
    #             serializer.save()
    #             return Response({'success': True, 'message': 'customer updated'}, status=status.HTTP_200_OK)
    #         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    #     except Exception as e:
    #         return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    def get(self, request, customer_id):
        customers = Customer.objects.filter(deleted_by__isnull=True,id=customer_id)
        serializer = CustomerSerializer(customers, many=True)
        return Response(serializer.data)

class UserListAPI(APIView):
    
    def get(self, request,user_id):
        # excluded_role_ids = [1, 3, 4, 5]
        # users = User.objects.filter(deleted_at__isnull=True, is_superuser=0).exclude(role__id__in=excluded_role_ids)
        # users = User.objects.filter( deleted_at__isnull=True, is_superuser=0, role__id=2 ) #.distinct()
        # excluded_role_ids = [1,4,5]  #
        users = User.objects.filter(deleted_at__isnull=True,id=user_id)
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

class CreateLeadQuotationAPI(APIView):
    
    def post(self, request):
        try:
            auth_header = request.META.get('HTTP_AUTHORIZATION', '')
            parts = auth_header.split(' ')
            if len(parts) != 2 or parts[0] != 'Bearer':
                return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
            
            token = parts[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        
            get_logged_in_user = valid_data['user_id']
            lead_id = request.data.get('lead')
            lead = get_object_or_404(Lead, id=lead_id)
            attachment = request.FILES.get('attachment')
            existing_quotes_count = Lead_Quote.objects.filter(lead=lead).count()
            version_number = existing_quotes_count + 1
            assigned_user = get_object_or_404(User, id=get_logged_in_user) if get_logged_in_user else None
            leadquote = Lead_Quote.objects.create(
                lead=lead,
                mailstatus=0,
                version=version_number,
                created_by=assigned_user,
           )
    
            if attachment:
                filename = f'Excitech-Australia-Quotation-{leadquote.id}-{leadquote.version}.pdf'
                leadquote.attachment.save(filename, attachment)
                # leadquote.attachment.save(f'{leadquote.id}-attachment.pdf', attachment)
   
            return Response({'message': 'Lead Quote Added Successfully'}, status=status.HTTP_201_CREATED)
        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    def get(self, request):
        try:
            leadquotes = Lead_Quote.objects.filter(deleted_at__isnull=True) #.order_by('-id')
            serializer = LeadQuoteListSerializer(leadquotes, many=True)
            return Response({
                'status': status.HTTP_200_OK,
                'success': True,
                'data': serializer.data
            }, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class AllLeadQuotationAPI(APIView):
    def get(self, request,lead_id, *args,  **kwargs):
        try:
            # lead_id = kwargs.get('lead_id')
            auth_header = request.META.get('HTTP_AUTHORIZATION', '')
            parts = auth_header.split(' ')
            if len(parts) != 2 or parts[0] != 'Bearer':
                return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
            
            token = parts[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            logged_in_user_id = valid_data['user_id']
            
            leads = Lead_Quote.objects.filter(deleted_at__isnull=True,lead__id=lead_id)
            # print(technician_assigned_job)
            serializer = LeadQuoteListSerializer(leads, many=True)
            if not leads :
                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response': [],
                }
            else:
                context = {
                    'status': status.HTTP_200_OK,
                    'success': True,
                    'response': serializer.data,
                }

            return Response(context, status=status.HTTP_200_OK)

        except ObjectDoesNotExist as e:
            return Response({'error': 'Object does not exist'}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class LeadAttachmentPhotosListCreateAPIView(generics.GenericAPIView):
    serializer_class = LeadAttachmentPhotosSerializer

    # def get(self, request, lead_id):
    #     attachments = LeadAttachmentPhotos.objects.filter(lead_id=lead_id)
    #     serializer = self.get_serializer(attachments, many=True)
    #     return Response(serializer.data)
    def get(self, request, lead_id):
        photos = LeadAttachmentPhotos.objects.filter(lead_id=lead_id)
        files = LeadAttachmentFiles.objects.filter(lead_id=lead_id)
    
        photos_serializer = LeadAttachmentPhotosSerializer(photos, many=True)
        files_serializer = LeadAttachmentFilesSerializer(files, many=True)
    
        return Response({
            'photos': photos_serializer.data,
            'files': files_serializer.data,
        }, status=status.HTTP_200_OK)

    def post(self, request, lead_id):
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        parts = auth_header.split(' ')
        if len(parts) != 2 or parts[0] != 'Bearer':
            return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
        
        token = parts[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
    
        get_logged_in_user = valid_data['user_id']
        assigned_user = get_object_or_404(User, id=get_logged_in_user) if get_logged_in_user else None
        lead = get_object_or_404(Lead, id=lead_id)

        images = request.FILES.getlist('images')
        files = request.FILES.getlist('files')
        created_attachments=[]
        for img in images:
            photo_serializer = LeadAttachmentPhotosSerializer(data={
                'lead': lead.id,
                'attachment': img,
            })
            photo_serializer.is_valid(raise_exception=True)
            photo_serializer.save(created_by=assigned_user, updated_by=assigned_user)
            created_attachments.append(photo_serializer.data)

        # Handle file uploads
        for file in files:
            file_serializer = LeadAttachmentFilesSerializer(data={
                'lead': lead.id,
                'attachment': file,
            })
            file_serializer.is_valid(raise_exception=True)
            file_serializer.save(created_by=assigned_user, updated_by=assigned_user)
            created_attachments.append(file_serializer.data)

        return Response(created_attachments, status=status.HTTP_201_CREATED)

class SendLeadQuotationEmailAPI(APIView):
    def post(self, request, id):
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        parts = auth_header.split(' ')
        if len(parts) != 2 or parts[0] != 'Bearer':
            return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
        
        token = parts[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
    
        get_logged_in_user = valid_data['user_id']
        try:
            leadquote = get_object_or_404(Lead_Quote, id=id)
            lead = get_object_or_404(Lead, id=leadquote.lead.id)

            # subject = f'EXCITECH Australia - EXCITECH Australia - Quotation for {leadquote.company_name} {leadquote.first_name} {leadquote.last_name}'
            if lead.company_name:
                name_part = lead.company_name
            else:
                name_part = f"{lead.first_name} {lead.last_name}"
            
            subject = f"EXCITECH Australia - Quotation for {name_part}"
            print(subject)
            from_email = settings.FROM_EMAIL
            recipient_email = lead.email

            template_data = {'quotation': leadquote}
            message = render_to_string('pages/leads/quote_email_temp.html', template_data)

            email = EmailMessage(subject, message, from_email, [recipient_email])

            if leadquote.attachment:
                pdf_file_path = leadquote.attachment.path
                email.attach_file(pdf_file_path, 'application/pdf')

            email.content_subtype = 'html'
            email.send()

            leadquote.mailstatus = 1
            leadquote.save()

            return Response({'message': 'Mail sent successfully'}, status=status.HTTP_200_OK)

        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class SendLeadNoteEmailAPI(APIView):
    def post(self, request, lead_id, note_id):
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        parts = auth_header.split(' ')
        if len(parts) != 2 or parts[0] != 'Bearer':
            return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)
        
        token = parts[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
    
        get_logged_in_user = valid_data['user_id']
        try:
            lead = get_object_or_404(Lead, id=lead_id)
            note = get_object_or_404(Leadnote, id=note_id, lead=lead)

            subject = f'EXCITECH Australia - Meeting Scheduled for {lead.first_name } {lead.last_name}'
            context = {
                'lead': lead,
                'note': note,
            }
            message = render_to_string('pages/leads/lead_note_email.html', context)

            recipient_email = lead.email
            from_email = settings.FROM_EMAIL

            email = EmailMessage(subject, message, from_email, [recipient_email,'kiran@beedev.co.in'])
            email.content_subtype = 'html'
            email.send()
            note.mail_status=1
            note.save()
            return Response({'message': 'Note email sent successfully'}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class RefreshUserInfoAPI(APIView):
    def post(self, request):
        userid=request.data.get("userid")
        userrole=request.data.get("role")
        user = User.objects.get(id=userid)
        if  userrole == 4 or userrole == '4':
            from customer.models import Customer
            if Customer.objects.filter(user_id=userid):
                customer = Customer.objects.get(user_id=userid)
                if customer.company_name:
                    company_name=customer.company_name.capitalize()
                    is_primary=customer.is_primary
                    job_chat=int(user.job_chat) if user.job_chat is not None else 0
                    username=f"{company_name}"
                else:
                    first_name = customer.first_name.capitalize()
                    last_name = customer.last_name.capitalize()
                    is_primary=customer.is_primary
                    username = f"{first_name} {last_name}"
                    job_chat=int(user.job_chat) if user.job_chat is not None else 0
                # role_id = 4
                # role_info.append(4)
            else:
                cust = Customer_Info.objects.get(user_id=userid)
                first_name = cust.first_name.capitalize()
                last_name = cust.last_name.capitalize()
                is_primary=cust.is_primary
                username = f"{first_name} {last_name}"
                job_chat=int(user.job_chat) if user.job_chat is not None else 0
                
                # if cust.customer.company_name:
                #     company_name=customer.company_name.capitalize()
                #     is_primary=cust.is_primary
    
                #     username=f"{company_name}"
                # else:
                #     first_name = cust.customer.first_name.capitalize()
                #     last_name = cust.customer.last_name.capitalize()
                #     is_primary=cust.is_primary
                #     username = f"{first_name} {last_name}"
                    
                # role_info.append(4)
                # role_id = 4
            context = {
                "status": status.HTTP_200_OK,
                "success": True,
                "erros_status": False,
                "response": "Successfully refreshed User!",
                # "refresh": str(token),
                # "access": str(token.access_token),
                "username": username,
                'job_chat':job_chat,
                "useid": user.id,
                "reset_password": user.reset_password,
                "email": user.email,
                "is_primary":is_primary,
                # "role": int(role_id),
                # "roles": role_ids,
                # "multirole":multirole
                #"roles":role_info
            }
            return Response(context, status=status.HTTP_200_OK)
        else:
            user = User.objects.get(id=userid)
            if user is not None:
                userinfo=UserInfo.objects.get(user=user)
                first_name = userinfo.first_name.capitalize()
                last_name = userinfo.last_name.capitalize()
                job_chat=int(user.job_chat) if user.job_chat is not None else 0
                username = f"{first_name} {last_name}"
                is_primary=False
                        
                context = {
                    "status": status.HTTP_200_OK,
                    "success": True,
                    "erros_status": False,
                    "response": "Successfully refreshed User!",
                    # "refresh": str(token),
                    # "access": str(token.access_token),
                    "username": username,
                    'job_chat':job_chat,
                    "useid": user.id,
                    "reset_password": user.reset_password,
                    "email": user.email,
                    "is_primary":is_primary,
                    # "role": int(role_id),
                    # "roles": role_ids,
                    # "multirole":multirole
                    #"roles":role_info
                }
                return Response(context, status=status.HTTP_200_OK)
                # return Response({}, status=status.HTTP_200_OK)
        return Response({}, status=status.HTTP_200_OK)
    # return Response({}, status=status.HTTP_200_OK)

class ProcessNoteActionAPI(APIView):
    # permission_classes = [IsAuthenticated]
    def post(self, request, note_id):
        serializer = NoteActionSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        # Get JWT user manually (if needed), otherwise use request.user
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        parts = auth_header.split(' ')
        if len(parts) != 2 or parts[0] != 'Bearer':
            return Response({'error': 'Invalid or missing token'}, status=status.HTTP_401_UNAUTHORIZED)

        token = parts[1]
        try:
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        except Exception as e:
            return Response({'error': 'Invalid token'}, status=status.HTTP_401_UNAUTHORIZED)

        user_id = valid_data.get("user_id")

        # Use request.user instead of manually fetching user
        note = get_object_or_404(Leadnote, id=note_id)
        data = serializer.validated_data
        print(data)
        action_type = data["action_type"]
        logged_in_user_id = user_id #valid_data['user_id']
        
        if request.data.get("assigned_to"):
            assigned_user = get_object_or_404(User, id=request.data.get("assigned_to"))
        else:
            assigned_user = get_object_or_404(User, id=logged_in_user_id) if logged_in_user_id else None
        print(assigned_user)
        if action_type == "mark_read":
            note.is_read = True
            note.updated_by_id = user_id
            note.save()
            return Response({"message": "Note marked as read."}, status=status.HTTP_200_OK)

        elif action_type == "update_log":
            log_note = data.get("log_note")
            groupid = data.get("groupid")

            if not log_note:
                return Response({"error": "log_note is required."}, status=status.HTTP_400_BAD_REQUEST)

            note.is_read = True
            note.updated_by_id = user_id
            note.save()
            # reschedule_date = data.get("reschedule_date")
            # meeting_time =request.data.get('meeting_time') or None
            meeting_time_str = request.POST.get('meeting_time')
            meeting_time = None
            # if meeting_time_str:
            #     try:
            #         meeting_time = datetime.strptime(meeting_time_str, "%H:%M").time()
            #     except ValueError:
            #         meeting_time = None  # fallback if invalid
            if meeting_time_str:
                for fmt in ("%H:%M:%S", "%H:%M"):
                    try:
                        meeting_time = datetime.strptime(meeting_time_str, fmt).time()
                        break
                    except ValueError:
                        continue
            reschedule_date = data.get("reschedule_date")
            input_date = data.get('reschedule_date')  # e.g., "30-05-2025"
            formatted_date = None
            if isinstance(reschedule_date, date):
                parsed_date = reschedule_date  # already a date
            elif isinstance(reschedule_date, str):
                parsed_date = datetime.strptime(reschedule_date, "%d-%m-%Y").date()
            else:
                parsed_date = None
            reschedule_date =parsed_date
            # reschedule_date = None
            # if input_date:
            #     try:
            #         parsed_date = datetime.strptime(input_date, "%d-%m-%Y")
            #         reschedule_date = parsed_date.date()  # ✅ return date object, not string
            #     except ValueError:
            #         return Response({'error': 'Invalid date format. Use DD-MM-YYYY.'}, status=400)
            # Leadnote.objects.create(
            #     lead=note.lead,
            #     groupid=groupid,
            #     note=log_note,
            #     reminder_date = data.get("reminder_date"),
            #     created_by_id=user_id,
            #     assigned_to_id=user_id,
            #     # created_at=now(),
            # )
            create_data = {
                "lead": note.lead,
                "groupid": groupid,
                "note": log_note,
                "created_by_id": user_id,
                "assigned_to": assigned_user,
            }
            
            if reschedule_date:
                create_data["reminder_date"] = reschedule_date
                create_data["meeting_time"] = meeting_time
            
            Leadnote.objects.create(**create_data)
            return Response({"message": "New log added successfully."}, status=status.HTTP_201_CREATED)

        elif action_type == "reschedule":
            # meeting_time =request.data.get('meeting_time') or None
            reschedule_date = data.get("reschedule_date")
            meeting_time_str = request.POST.get('meeting_time')
            meeting_time = None
            # if meeting_time_str:
            #     try:
            #         meeting_time = datetime.strptime(meeting_time_str, "%H:%M").time()
            #     except ValueError:
            #         meeting_time = None  # fallback if invalid
            if meeting_time_str:
                for fmt in ("%H:%M:%S", "%H:%M"):
                    try:
                        meeting_time = datetime.strptime(meeting_time_str, fmt).time()
                        break
                    except ValueError:
                        continue
            input_date = data.get('reschedule_date')  # e.g., "30-05-2025"
            # reschedule_date = None
            # if input_date:
            #     try:
            #         parsed_date = datetime.strptime(input_date, "%d-%m-%Y")
            #         reschedule_date = parsed_date.date()  # ✅ return date object, not string
            #     except ValueError:
            #         return Response({'error': 'Invalid date format. Use DD-MM-YYYY.'}, status=400)
            groupid = data.get("groupid")
            formatted_date = None
            if isinstance(reschedule_date, date):
                parsed_date = reschedule_date  # already a date
            elif isinstance(reschedule_date, str):
                parsed_date = datetime.strptime(reschedule_date, "%d-%m-%Y").date()
            else:
                parsed_date = None
            reschedule_date =parsed_date
            # if reschedule_date:
            #     try:
            #         # Parse the input (d-m-Y)
            #         parsed_date = datetime.strptime(reschedule_date, "%d-%m-%Y")
            #         # Convert to ISO 8601 string
            #         iso_datetime_str = parsed_date.isoformat()  # Gives '2025-06-05T00:00:00'
            #         formatted_date = iso_datetime_str
            #     except ValueError:
            #         return Response({"error": "Invalid date format. Use DD-MM-YYYY."}, status=400)
            note.is_read = False
            note.updated_by_id = user_id
            note.reminder_date=reschedule_date
            note.meeting_time =meeting_time
            note.assigned_to =assigned_user
            # note.
            note.save()
            # create_data = {
            #     "lead": note.lead,
            #     "groupid": groupid,
            #     "note": 'Rescheduled',
            #     "created_by_id": user_id,
            #     "assigned_to_id": user_id,
            #     "reminder_date" : reschedule_date,
            # }
            # Leadnote.objects.create(**create_data)
            return Response({"message": "Rescheduled successfully."}, status=status.HTTP_200_OK)

        return Response({"error": "Unknown action type."}, status=status.HTTP_400_BAD_REQUEST)
        
class TechnicianListAPI(APIView):
    def get(self, request):
        exclude_id = request.GET.get("exclude_id")
    
        techs = User.objects.filter(
            role__id=Role.TECHNICIAN,
            is_active=True
        ).select_related('userinfo')
    
        if exclude_id:
            techs = techs.exclude(id=exclude_id)
    
        data = []
        for tech in techs:
            data.append({
                'id': tech.id,
                'name': tech.userinfo.get_full_name(),  # <-- here
                'email': tech.email,
            })
    
        return Response(data)

class Customersdetail(APIView):
    def get(self, request):
        orders = Order.objects.filter(deleted_at__isnull=True).select_related('invoice__customer__user')
        technicians=User.objects.filter(role=3,deleted_at__isnull=True)
        orders = Order.objects.filter(
            invoice__customer=OuterRef('pk'),
            deleted_at__isnull=True
        )
        
        allcustomers = Customer.objects.filter(
            deleted_by__isnull=True,
            is_primary=True
        ).annotate(
            has_order=Exists(orders)
        ).filter(has_order=True)
        # allcustomers = Customer.objects.filter(deleted_by__isnull=True)
        data = []
        for customer in allcustomers:
            data.append({
                'id': customer.user.id,
                'name': f"{customer.first_name} {customer.last_name}",
                'email': customer.email,
            })
        return Response(data)

class OrdersByCustomer(APIView):

    def get(self, request, customer_id):
        try:
            user = User.objects.get(id=customer_id)
            if user.isprimary == 1:
                queryset = Order.objects.filter(
                    invoice__customer__user__id=customer_id,
                    deleted_at__isnull=True
                )
            else:
                cust_info = Customer_Info.objects.filter(user__id=customer_id).first()
                if cust_info:
                    queryset = Order.objects.filter(
                        invoice__customer__user__id=cust_info.customer.user.id,
                        deleted_at__isnull=True
                    )
                else:
                    queryset = Order.objects.none()
            
            queryset = queryset.prefetch_related(
                'orderset__product',
            )
            orders_data = [
                {
                    'id': order.id,
                    'items': [
                        {
                            'order_item_id': item.id,
                            'product': {
                                'id': item.product.id,
                                'product_name': item.product.product_name,
                                'sku': item.product.sku,
                            },
                            'installation_date': item.installation_date,
                            'installation_time': item.installation_time,
                            'view_by_technician': item.view_by_technician,
                            'installation_complete': item.installation_complete,
                            'warranty_end_date': item.warranty_end_date,
                            'get_status': item.get_status,
                            'installed_date': item.installed_date,
                            'serial_number': item.serial_number.serial_number if item.serial_number else None,
                        }
                        for item in order.orderset.all()
                    ]
                }
                for order in queryset
            ]

            return Response(
                {
                    'success': True,
                    'orders': orders_data
                },
                status=status.HTTP_200_OK
            )

        except User.DoesNotExist:
            return Response(
                {
                    'success': False,
                    'error': 'User not found'
                },
                status=status.HTTP_404_NOT_FOUND
            )

        except Exception as e:
            return Response(
                {
                    'success': False,
                    'error': str(e)
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
            
class CustomerCompletedOrderItems(APIView):
    def get(self, request):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            customer_id = valid_data['user_id']
            user = User.objects.get(id=customer_id)
            if user.isprimary == 1:
                queryset = Order.objects.filter(
                    invoice__customer__user__id=customer_id,
                    deleted_at__isnull=True
                )
            else:
                cust_info = Customer_Info.objects.filter(user__id=customer_id).first()
                if cust_info:
                    queryset = Order.objects.filter(
                        invoice__customer__user__id=cust_info.customer.user.id,
                        deleted_at__isnull=True
                    )
                else:
                    queryset = Order.objects.none()
            filtered_items = Prefetch(
                'orderset',
                queryset=Order_Item.objects.filter(
                    status__in=[
                        Order_Item.INSTALLED,
                        Order_Item.SERVICE_COMPLETED
                    ]
                ).select_related('product', 'serial_number'),
            )
            
            queryset = queryset.prefetch_related(filtered_items)
            # queryset = queryset.prefetch_related(
            #     'orderset__product',
            # )
            orders_data = []
            for order in queryset:
                items = [
                    {
                        'order_item_id': item.id,
                        'product': {
                            'id': item.product.id,
                            'product_name': item.product.product_name,
                            'sku': item.product.sku,
                        },
                        'installation_date': item.installation_date,
                        'installation_time': item.installation_time,
                        'view_by_technician': item.view_by_technician,
                        'installation_complete': item.installation_complete,
                        'warranty_end_date': item.warranty_end_date,
                        'get_status': item.get_status,
                        'installed_date': item.installed_date,
                        'serial_number': item.serial_number.serial_number if item.serial_number else None,
                    }
                    for item in order.orderset.all()
                ]
            
                if items:
                    orders_data.append({
                        'id': order.id,
                        'items': items
                    })

            return Response(
                {
                    'success': True,
                    'orders': orders_data
                },
                status=status.HTTP_200_OK
            )

        except User.DoesNotExist:
            return Response(
                {
                    'success': False,
                    'error': 'User not found'
                },
                status=status.HTTP_404_NOT_FOUND
            )

        except Exception as e:
            return Response(
                {
                    'success': False,
                    'error': str(e)
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
            
class CustomerAllOrderItems(APIView):
    def get(self, request):
        try:
            token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
            valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
            customer_id = valid_data['user_id']
            user = User.objects.get(id=customer_id)
            if user.isprimary == 1:
                queryset = Order.objects.filter(
                    invoice__customer__user__id=customer_id,
                    deleted_at__isnull=True
                )
            else:
                cust_info = Customer_Info.objects.filter(user__id=customer_id).first()
                if cust_info:
                    queryset = Order.objects.filter(
                        invoice__customer__user__id=cust_info.customer.user.id,
                        deleted_at__isnull=True
                    )
                else:
                    queryset = Order.objects.none()
            # filtered_items = Prefetch(
            #     'orderset',
            #     queryset=Order_Item.objects.filter(
            #         status__in=[
            #             Order_Item.INSTALLED,
            #             Order_Item.SERVICE_COMPLETED
            #         ]
            #     ).select_related('product', 'serial_number'),
            # )
            filtered_items = Prefetch(
                'orderset',
                queryset=Order_Item.objects.select_related(
                    'product',
                    'serial_number'
                ),
            )
            queryset = queryset.prefetch_related(filtered_items)
            # queryset = queryset.prefetch_related(
            #     'orderset__product',
            # )
            orders_data = []
            for order in queryset:
                items = [
                    {
                        'order_item_id': item.id,
                        'product': {
                            'id': item.product.id,
                            'product_name': item.product.product_name,
                            'sku': item.product.sku,
                        },
                        'installation_date': item.installation_date,
                        'installation_time': item.installation_time,
                        'view_by_technician': item.view_by_technician,
                        'installation_complete': item.installation_complete,
                        'warranty_end_date': item.warranty_end_date,
                        'get_status': item.get_status,
                        'installed_date': item.installed_date,
                        'serial_number': item.serial_number.serial_number if item.serial_number else None,
                    }
                    for item in order.orderset.all()
                ]
            
                if items:
                    orders_data.append({
                        'id': order.id,
                        'items': items
                    })

            return Response(
                {
                    'success': True,
                    'orders': orders_data
                },
                status=status.HTTP_200_OK
            )

        except User.DoesNotExist:
            return Response(
                {
                    'success': False,
                    'error': 'User not found'
                },
                status=status.HTTP_404_NOT_FOUND
            )

        except Exception as e:
            return Response(
                {
                    'success': False,
                    'error': str(e)
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
   
class TechnicianServiceRequestAPIView(APIView):
    authentication_classes = []

    def post(self, request, *args, **kwargs):
        
        token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
        valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
        get_logged_in_user = valid_data['user_id']
        user=User.objects.get(id=get_logged_in_user)
        order_item_id = request.data.get('order_item_id')
        order_item = Order_Item.objects.get(id=order_item_id)
        assigned_order_item=Technician_Assigned_Order_Item.objects.filter(order_item=order_item).first()
        is_selected_warranty = request.data.get('is_selected_warranty')
        description= request.data.get('description')
        service_request_images = request.FILES.getlist('service_request_images')
        service_request_videos = request.FILES.getlist('service_request_videos')
        date_str = request.data.get('date')
        if date_str:
            service_request_date = datetime.strptime(date_str, "%Y-%m-%d").date()
        else:
            service_request_date = None
        if not is_selected_warranty:
            context = {
                "status": status.HTTP_200_OK,
                "success": False,
                'message': 'Please provide is it in warranty or in service.'
            }
            return Response(context, status=status.HTTP_200_OK)
            
        if not description:
            context = {
                "status": status.HTTP_200_OK,
                "success": False,
                'message': 'No description provided.'
            }
            return Response(context, status=status.HTTP_200_OK)

        service = Service.objects.create(order_item=order_item,description=description,is_selected_warranty=is_selected_warranty)
        order_item.status=8
        order_item.service_type = 2
        order_item.save()
        assignment=Technician_Assigned_Order_Item.objects.create(
                order_item=order_item,
                technician=user,
                service_request_date=service_request_date,
                service=service,
                job_type=2
                )
        assignment.working_status= 4  #Request Service
        assignment.save()
        subject = f'EXCITECH Australia-Job Assigned Notification (Service)-{assignment.id}'
        # formatted_date = assignment.installation_date.strftime('%d-%m-%Y')
        # formatted_time = assignment.installation_time.strftime('%I:%M %p') 
        
        
        template_data = {'assignment': assignment}
        message = render_to_string('pages/quotation/job_assigned_email_temp.html', template_data)
        

        from_email = settings.FROM_EMAIL # Replace with your email
        recipient_email = assignment.technician.email
        email = EmailMessage(subject, message, from_email, [recipient_email])
        email.content_subtype = 'html'
        email.send()
        try:
            unique_registration_ids = set()
            get_registration_token = FCMDevice.objects.filter(user_id=assignment.technician.id,active=True)
            for i in get_registration_token:
                print('notification send')
                if i.registration_id not in unique_registration_ids:
                    sendPush(f'EXCITECH Australia - Job #{assignment.id} Assigned for Service',f'Job #{assignment.id} Assigned for Service',[i.registration_id],{"job_id": assignment.id,"type": "job",
                        "tech_ids":assignment.technician.id,"customer_ids":'',"additional_cust_ids":[],"sec_tech_ids":[],"job_chat_allow":[]
                    })     
                    unique_registration_ids.add(i.registration_id)
        except FCMDevice.DoesNotExist:
            
            print("FCMDevice not found for the specified conditions. Push notification not sent.")
        except Exception as e:
            print(f"Error sending push notification: {e}")
                
        print(service_request_images)

        for image_data, video_data in zip_longest(service_request_images, service_request_videos, fillvalue=None):
            
      
            data = {'service_request_image': image_data,
            'service_request_video':video_data
            }
            

            serializer = ServiceRequestImageSerializer(data=data)

            if serializer.is_valid():
                serializer.save(service=service)
                
                
            else:
               return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

      
        context = {
            "status": status.HTTP_201_CREATED,
            "success": True,
            'message': 'Customer service request successfully.'
        }
        return Response(context, status=status.HTTP_201_CREATED)  
    
# class OrderItemhistory(APIView):
#     def get(self, request,order_item_id):
#         order_item = Order_Item.objects.get(id=order_item_id)
#         statuses = [0, 10, 8, 11]
#         filtered_history = []
        
#         order_history = order_item.get_order_history.order_by("timestamp")
        
#         for filter_status in statuses:
#             record = order_history.filter(
#                 new_data__0__fields__status=filter_status
#             ).first()
            
#             if record:
#                 filtered_history.append(record)
        
#         history_serializer = ActivityLogSerializer(filtered_history, many=True)
#         history_data = history_serializer.data
#         serializer = OrderItemSerializer(order_item)
#         chats = Chat.objects.filter(
#           job__id=order_item_id
#         )
#         AllChats = ChatSerializer(chats, many=True)
        
#         return Response(
#             {
#                 'success': True,
#                 'orders': serializer.data,
#                 'chats': AllChats.data,
#                 'order_history': history_data
#             },
#             status=status.HTTP_200_OK
#         )
STATUS_LABELS = {
    0: "Ordered",
    10: "Installation Completed",
    8: "Service Requested",
    11: "Service Completed",
}

class OrderItemhistory(APIView):

    def get(self, request, order_item_id):

        order_item = get_object_or_404(Order_Item, id=order_item_id)

        statuses_needed = [0, 10, 8, 11]
        timeline = []

        # ---------- STATUS HISTORY ----------
        order_history = order_item.get_order_history.order_by("timestamp")

        for st in statuses_needed:
            record = order_history.filter(
                new_data__0__fields__status=st
            ).first()

            if record:
                timeline.append({
                    "type": "status",
                    "label": STATUS_LABELS.get(st),
                    "status_code": st,
                    "date": record.timestamp
                })

        # ---------- CHAT ----------
        chats = Chat.objects.filter(job__id=order_item_id)
        chat_serializer = ChatSerializer(chats, many=True)

        for chat in chat_serializer.data:
            timeline.append({
                "type": "chat",
                "message": chat["content"],
                "sender": chat["sender"],
                "recipient": chat["recipient"],
                "images": chat["chat_images"],
                "is_visible": chat["is_visible"],
                "date": datetime.fromisoformat(chat["timestamp"].replace("Z", "+00:00")),
                # "date": datetime.fromisoformat(chat["timestamp"].replace("Z", "+00:00")).strftime("%d-%m-%Y %H:%M:%S"),
                "is_system": False
            })

        # ---------- SORT EVERYTHING ----------
        timeline = sorted(timeline, key=lambda x: x["date"])
        for item in timeline:
            item["date"] = item["date"].strftime("%d-%m-%Y %H:%M:%S")

        serializer = OrderItemSerializer(order_item)

        return Response(
            {
                "success": True,
                "order": serializer.data,
                "timeline": timeline
            },
            status=status.HTTP_200_OK
        )