from django.conf import settings
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Profiles,Otp,Product,CategoryServiceProvider,UserBooking, Notification, Client, Loan,JobPost,  Collection, Student, Attendance, Fees, FeesHistory,Category,Subcategory
from django.core.exceptions import ObjectDoesNotExist
from rest_framework.exceptions import NotFound
from django.contrib.auth import authenticate, login
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import User
from django.utils import timezone as djtz
from django.utils import timezone
from datetime import date, datetime, timedelta
import requests
from django.utils import timezone
from django.http import HttpResponse
import base64
from rest_framework.parsers import MultiPartParser, FormParser
from django.db.models import Q
from rest_framework.generics import RetrieveAPIView, ListAPIView
from .serializers import UserSerializer
from rest_framework.permissions import IsAuthenticated
from datetime import datetime, time
import json
from django.core.mail import EmailMessage
from school.settings import BASE_DIR
import pdfkit
from django.core.exceptions import ObjectDoesNotExist
# import openai
import re
from django.conf import settings
import threading
# import pywhatkit
from django.core.mail import send_mail
from django.utils.crypto import get_random_string
from django.db.models import Sum




from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from django.core.exceptions import ObjectDoesNotExist
from rest_framework_simplejwt.tokens import RefreshToken
import re  # For basic email validation
# from twilio.rest import Client as TwilioClient # ?? Maru Peyaridhal!
class LoginAPIView(APIView):
    def post(self, request):
        data = request.data
        username_or_email = data.get("username")
        password = data.get("password")

        if not username_or_email or not password:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "error"},
                "message": "Username and password are required"
            }, status=status.HTTP_400_BAD_REQUEST)

        # Basic email validation
        user = None
        if re.match(r"[^@]+@[^@]+\.[^@]+", username_or_email):
            try:
                user = User.objects.get(email=username_or_email)
            except User.DoesNotExist:
                user = None
        else:
            user = authenticate(request, username=username_or_email, password=password)

        # Authenticate and Status Check
        if user is not None and user.check_password(password):
            try:
                profile = Profiles.objects.get(user_id=user.id)
                
                # --- ????????? Inactive Status ???? ?????????? ---
                if profile.status == 2:
                    return Response({
                        "status": {"code": status.HTTP_403_FORBIDDEN, "response": "error"},
                        # "error": "Account Inactive",
                        # "message": "You are inactive by Admin. Please contact Admin.",
                        "error": "Waiting for approval",
                        "message": "Your account is waiting for admin approval.",
                        "data": None
                    }, status=status.HTTP_403_FORBIDDEN)
                # -----------------------------------------------

                login(request, user)
                token = RefreshToken.for_user(user)
                
                profile_photo = request.build_absolute_uri(profile.profiles.url) if profile.profiles else None
                companyname = "loop"
                
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Login success",
                    "data": {
                        "name": user.username,
                        "id": user.id,
                        "username": user.username,
                        "email": user.email,
                        "isSuper": user.is_superuser,
                        "refresh": str(token),
                        "token": str(token.access_token),
                        "profile": profile_photo,
                        "companyname": companyname,
                        "phone": profile.phone,
                        "role": profile.role,
                    }
                })
            except Profiles.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "error"},
                    "message": "User profile not found"
                }, status=status.HTTP_404_NOT_FOUND)
        else:
            return Response({
                "status": {"code": status.HTTP_401_UNAUTHORIZED, "response": "error"},
                "error": "Authentication failed",
                "message": "Invalid username or password",
                "data": None
            }, status=status.HTTP_401_UNAUTHORIZED)



# views.py ???????? ????????? ????? ???????????
# class UserAPIView(RetrieveAPIView):
#     permission_classes = (IsAuthenticated,)
#     serializer_class = UserSerializer

#     def get_object(self):
#         return self.request.user

#     def post(self, request):
#         data = request.data
#         user = User.objects.get(email=data["email"])
#         profile = Profiles.objects.get(user=user)
#         return Response({
#             "status": {"code": status.HTTP_200_OK, "response": "success"},
#             "error": False,
#             "data": {
#                 "username": user.username,  
#                 "email": user.email,
#                 "role": profile.role.id if profile.role else None,
#                 "profile": profile.profiles.url if profile.profiles else None,
#             }
#         })
class UserDashboardAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user.id
        # ?????? Booking ????? ????????? ???? ?????????
        booking_count = UserBooking.objects.filter(user_id=user).count()
        # ???? ??????? ??????? ????????????? ????? ???????????
        
        return Response({
            "status": "success",
            "data": {
                "booking_count": booking_count,
                "expiry_minutes": 30  # ????? ???? ??????????
            }
        })
    
def send_otp_email(email, otp):
    # Subject-? ??????? ??????? ??????????????
    subject = 'OTP Verification - iITS Community'
    
    # Message-? ???????????????? ???? ?????? ??????????????
    message = f'''Dear User,

    Welcome to iITS Community! ??

    Your One-Time Password (OTP) for account verification is:

    {otp}

    This code is valid for the next 1 minutes. Please do not share this OTP with anyone.


    Best regards,
    Team iITS Community
    iITS Community Support Team
    '''
    try:
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [email],
            fail_silently=False,
        )
        print(f"Success: OTP sent to {email}")
    except Exception as e:
        print(f"Error sending email: {e}")


def forgot_send_otp_email(email, otp):
    subject = 'Password Reset Request - iITS Community'
    
    message = f'''Dear User,

    We received a request to reset the password for your iITS Community account. ??

    Your One-Time Password (OTP) for password reset is:

    {otp}

    This code is valid for a limited time. If you did not request this, please ignore this email and ensure your account is secure.

    Please do not share this OTP with anyone for security reasons.


    Best regards,
    Team iITS Community
    Support Team
    '''
    try:
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [email],
            fail_silently=False,
        )
        print(f"Success: Forgot Password OTP sent to {email}")
    except Exception as e:
        print(f"Error sending email: {e}")

def send_otp_emails(email, otp):
   
    subject = 'Your One-Time  (OTP) for Verification'
    message = f'''Dear User,

    Your One-Time  (OTP) for verification is:

    {otp}

    Please enter this code to proceed. This OTP is valid for the next 1 minutes.

    If you did not request this code, please ignore this email.

    Thank you,  
    Pearlcon Technologies LLP
    https://pearlcons.com
        '''
    try:
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [email],
            fail_silently=False,
        )
    except Exception as e:
        print(f"Error sending email: {e}")

        




class SubcategoryAPIView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                designation = Subcategory.objects.get(id=id)
                data = {
                    'id': designation.id,
                    'name': designation.name,
                    'description': designation.description,
                    'department': designation.category_id
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:
                index = 0
                designations = []

                for designation in Subcategory.objects.all():
                    index += 1

                    try:
                        department = Category.objects.get(id=designation.category_id)
                        department = department.name
                    except Category.DoesNotExist:
                        department = ''

                    designations.append({
                        'row': index,
                        'id': designation.id,
                        'name': designation.name,
                        'description': designation.description,
                        'department': department
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": designations
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

    def post(self, request):
        data = request.data

        try:
            department = Subcategory.objects.create(
                name=data["name"],
                description=data["description"],
                category_id=data["department"], # ID-? ???????? ??????? category_id ?? ??????????????
                created_by=request.user
            )
            department.save()

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Designation created successfully"
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })

    def put(self, request, id):
        data = request.data

        try:
            designation = Subcategory.objects.get(id=id)

            designation.name = data["name"]
            designation.description = data["description"]
            designation.department = Category.objects.get(id=data["department"])
            designation.save()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "Designation updated successfully"
            })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "No data found"
            })

    def delete(self, request, id):
        if id is not None:
            try:
                designation = Subcategory.objects.get(id=id)
                designation.delete()

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Designation deleted successfully"
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": None,
                    "message": "No data found"
                })
        else:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": None,
                "message": "Something went wrong"
            })
class CategoryAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                category = Category.objects.get(id=id)
                data = {
                    'id': category.id,
                    'name': category.name,
                    'parent': category.parent.id if category.parent else None,
                    'description': category.description,
                    'service_status': category.service_status
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                parent_id = request.query_params.get('parent_id') # URL-?? ?parent_id=1 ?? ???????????
            
                if parent_id:
                    queryset = Category.objects.filter(parent_id=parent_id)
                else:
                    queryset = Category.objects.filter(parent=None) # ?????? ???????????? ???????

                companies = []
                for index, company in enumerate(queryset, start=1):
                    companies.append({
                        'row': index,
                        'id': company.id,
                        'name': company.name,
                        'description': company.description,
                        'service_status': company.service_status,

                        'has_subcategories': company.subcategories.exists() # ??????? ?????? ????? ??? ??? ??????
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

    def post(self, request):
        data = request.data

        try:



            company = Category.objects.create(
                name=data["name"],
                description=data.get("description", ""),
                parent_id=data.get("parent_id"), # Subcategory ???????? parent_id ?????? ????????
                service_status=data.get("service_status", 1),
                created_by=request.user
            )

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Department created successfully"
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })

    def put(self, request, id):
        data = request.data
        try:
            category = Category.objects.get(id=id)
            category.name = data.get("name", category.name)
            category.description = data.get("description", category.description)
            
            # Sub-category ?? ????????? parent_id ??????? ??????????????????
            # Main category ?? ????????? ??????? status-? ??????? ????????
            if "service_status" in data and data["service_status"] is not None:
                category.service_status = data["service_status"]

            category.save()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "Category updated successfully"
            })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "No data found"
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": str(e)
            })

    def delete(self, request, id):
        try:
            category = Category.objects.get(id=id)
            
            # ??????? ????: ?????? ???? sub-categories ???????????
            has_sub = Category.objects.filter(parent_id=id).exists()
            
            if has_sub:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": "Cannot delete! This category has sub-categories."
                }, status=status.HTTP_400_BAD_REQUEST)

            category.delete()
            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "message": "Deleted successfully"
            })
        except ObjectDoesNotExist:
            return Response({"message": "Not found"}, status=status.HTTP_404_NOT_FOUND)
        
class UserCategoryAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                category = Category.objects.get(id=id)
                data = {
                    'id': category.id,
                    'name': category.name,
                    'parent': category.parent.id if category.parent else None,
                    'description': category.description,
                    'service_status': category.service_status
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                parent_id = request.query_params.get('parent_id') # URL-?? ?parent_id=1 ?? ???????????
            
                if parent_id:
                    queryset = Category.objects.filter(parent_id=parent_id)
                else:
                    queryset = Category.objects.filter(parent=None) # ?????? ???????????? ???????

                companies = []
                for index, company in enumerate(queryset, start=1):
                    companies.append({
                        'row': index,
                        'id': company.id,
                        'name': company.name,
                        'description': company.description,
                        'service_status': company.service_status,

                        'has_subcategories': company.subcategories.exists() # ??????? ?????? ????? ??? ??? ??????
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })



import pandas as pd

class ImportProvidersView(APIView):
    def post(self, request):
        file = request.FILES.get('file')
        if not file:
            return Response({"error": "No file uploaded"}, status=400)
            
        try:
            # 1. ??????? ???? ???? ???????
            df = pd.read_excel(file)
            df = df.fillna('') 

            profiles_to_create = []
            
            for index, row in df.iterrows():
                # Safety: row.get() ?????????????? ????????
                email_val = str(row.get('Email', '')).strip().lower()
                
                # ??????? ??????? ????????? ????? ????????? ???????
                if not email_val:
                    continue

                # ??????? ??????? ?????????? ??????? role=2 (Provider) ???? ????? ???? ???????
                if not Profiles.objects.filter(email=email_val, role=2).exists():
                    profiles_to_create.append(
                        Profiles(
                            name=row.get('Name', 'Unknown'),
                            email=email_val,
                            address=row.get('Address', ''),
                            servicename=row.get('Skill Summary', ''),
                            role=2,
                            status=1
                        )
                    )

            # 2. Bulk Create
            if profiles_to_create:
                Profiles.objects.bulk_create(profiles_to_create)
                return Response({"message": f"{len(profiles_to_create)} providers imported successfully"}, status=201)
            else:
                return Response({"message": "No new providers to import"}, status=200)

        except Exception as e:
            # ??????? ????? ???????? ????? ????????? ????? ???? ?????
            return Response({"error": f"Import failed: {str(e)}"}, status=400)

class ServiceProviderManagerAPI(APIView):
    
    # 1. GET: ??? ??????????? Subcategory-?? ???? ????? ???????????????? ??????
    def get(self, request):
        category_id = request.query_params.get('category_id')
        if not category_id:
            return Response({"error": "category_id is required"}, status=400)
            
        # Mapping table-?? ??????? ??????????? category-????? ???????????? ???????????
        mappings = CategoryServiceProvider.objects.filter(category_id=category_id, status=1)
        
        provider_list = []
        for item in mappings:
            provider_list.append({
                "id": item.provider.id,
                "name": item.provider.name,
                "skill": item.provider.servicename,
                "email": item.provider.email,
                "address": item.provider.address,
                "status": item.provider.status
            })
            
        return Response({"status": "success", "data": provider_list}, status=200)

    # 2. POST: ????? ????????? ????????? ???-????????????? ??????
    def post(self, request):
        category_id = request.data.get('category_id')
        provider_id = request.data.get('provider_id')
        name = request.data.get('name')
        skill = request.data.get('skill')
        email = request.data.get('email')
        address = request.data.get('address')

        # 1. ??????? ???? ???????????? ???? ????????? ??????????? ????? ?????????
        if provider_id:
            # ??????? ??????????? ????? ???? ???????
            exists = CategoryServiceProvider.objects.filter(
                category_id=category_id, 
                provider_id=provider_id  # ?????? ????? ??????? ????? 'provider' ??????? provider_id ?? ???????????
            ).exists()

            if exists:
                return Response({"error": "This provider is already linked to this category!"}, status=400)

            # ?????? ???????
            CategoryServiceProvider.objects.create(
                category_id=category_id,
                provider_id=provider_id 
            )
            return Response({"message": "Existing provider linked successfully"}, status=200)

        # 2. ????? ????????? ??????????? ??????
        else:
            if not category_id or not name or not skill:
                return Response({"error": "Missing required fields"}, status=400)

            # ???????? ??????? ???? ?????? ????? ????????? ??? ?????? (Optional but Good)
            

            # Profiles-?? ????? ?????? ?????????
            new_provider = Profiles.objects.create(
                name=name, servicename=skill, email=email, 
                address=address, role=2, status=1
            )

            # ??????? (Mapping) ????????????
            CategoryServiceProvider.objects.create(
                category_id=category_id,
                provider=new_provider
            )

            return Response({
                "message": "New provider created and linked successfully", 
                "id": new_provider.id
            }, status=201)

    # 3. PUT: ????????? ????????? ??????? ?????
    def put(self, request):
        provider_id = request.data.get('provider_id')
        try:
            provider = Profiles.objects.get(id=provider_id)
            provider.name = request.data.get('name', provider.name)
            provider.servicename = request.data.get('skill', provider.servicename)
            provider.email = request.data.get('email', provider.email)
            provider.address = request.data.get('address', provider.address)
            provider.save()
            return Response({"message": "Provider updated successfully"}, status=200)
        except Profiles.DoesNotExist:
            return Response({"error": "Provider not found"}, status=404)

    # 4. DELETE: ??? ????????? ????? (Status-? 0 ???????? ????????)
    def delete(self, request):
        p_id = request.data.get('provider_id')
        c_id = request.data.get('category_id')

        # Debug ????????
        print(f"DEBUG: Trying to delete Provider ID: {p_id}, Category ID: {c_id}")

        if not c_id:
            return Response({"error": "Category ID is missing in request"}, status=400)

        try:
            # filter ???????? ??????????
            record = CategoryServiceProvider.objects.filter(
                category_id=c_id, 
                provider_id=p_id
            ).first()

            if record:
                record.delete()
                return Response({"message": "Provider removed successfully"}, status=200)
            
            return Response({"error": "No matching record found"}, status=404)

        except Exception as e:
            return Response({"error": str(e)}, status=500)
from django.contrib.auth import get_user_model
User = get_user_model()

class SendotpAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            email = data.get('email', '').strip().lower() # Space-??? ??????, ????? ??????????? ???????????

            if not email:
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Email address is required."
                }, status=status.HTTP_400_BAD_REQUEST)

            # --- Role 3-????? ??????? ???? ?????????? ---
            if Profiles.objects.filter(email=email, role="3").exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "This email is already registered as a User. Please try another email."
                }, status=status.HTTP_400_BAD_REQUEST)
           
            user = Otp.objects.create(email=email)
            otp = get_random_string(length=6, allowed_chars='1234567890')
            user.otp = otp
            user.otp_created_at = timezone.now()
            user.save()

            threading.Thread(target=send_otp_email, args=(email, otp)).start()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "Success"},
                "error": None,
                "data": {"email": email}
            })
        except Exception as e:
            print("Error:", e)
            return Response({
                "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "Internal Server Error"},
                'error': True,
                "message": str(e)
            })

class ForgototpAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            username = data.get('username', '').strip()

            if not username:
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Username is required."
                }, status=status.HTTP_400_BAD_REQUEST)

            # 1. Profile ???? ???????
            profile = Profiles.objects.filter(name=username).first() 

            if not profile:
                return Response({
                    "status": {"code": 404, "response": "failed"},
                    "message": "User not found. Please check your username."
                }, status=status.HTTP_404_NOT_FOUND)

            email = profile.email
            
            # --- ???? ?????? ?????? ????? ???? ??????? ?????????? ---
            # 2. ???? ??????????? ??????? ???? ?????? ???? OTP-??????? ???????? ????????????
            Otp.objects.filter(email=email).delete()
            
            # 3. ??????? ????? OTP-? ???????????????
            otp_code = get_random_string(length=6, allowed_chars='1234567890')
            otp_user = Otp.objects.create(
                email=email,
                otp=otp_code,
                otp_created_at=timezone.now()
            )

            # 4. Email ??????????
            threading.Thread(target=forgot_send_otp_email, args=(email, otp_code)).start()

            return Response({
                "status": {"code": 200, "response": "Success"},
                "error": None,
                "data": {"email": email}, 
                "message": "OTP sent to your registered email."
            }, status=status.HTTP_200_OK)

        except Exception as e:
            print("Forgot OTP Error:", e) # ??????? ???? ???? ????? ????
            return Response({
                "status": {"code": 500, "response": "failed"},
                "error": True,
                "message": f"Server Error: {str(e)}"
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class PasswordresetAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            username = data.get('username', '').strip()
            new_password = data.get('new_password', '').strip()

            if not username or not new_password:
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Username and New Password are required."
                }, status=status.HTTP_400_BAD_REQUEST)

            # 1. Profiles ???????? ???? ????? ??????????? ????? ?????????
            profile = Profiles.objects.filter(name=username).first()

            if not profile:
                return Response({
                    "status": {"code": 404, "response": "failed"},
                    "message": "User profile not found."
                }, status=status.HTTP_404_NOT_FOUND)

            # 2. Django-???? ?????? User ??????? ?????????? ??????? ???????
            # (??????? ?????? ???????????? ??????? ?????????)
            user = User.objects.filter(id=profile.user_id).first()
            if user:
                user.password = make_password(new_password) # Hash ???????
                user.save()

            # 3. ?????? ?????? Profiles ?????????? ??????? ???????
            profile.password = new_password # ??????? ??????? ?????? ????????? ??????? ????????????
            profile.save()

            # 4. ?????????? ?????, ???? ??????? ???? OTP-??? ?????????????
            Otp.objects.filter(email=profile.email).delete()

            return Response({
                "status": {"code": 200, "response": "success"},
                "message": "Password updated successfully! You can now login."
            }, status=status.HTTP_200_OK)

        except Exception as e:
            print("Reset Password Error:", e)
            return Response({
                "status": {"code": 500, "response": "failed"},
                "message": f"Server Error: {str(e)}"
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class VerifyforgototpAPIView(APIView):
    def get(self, request):
        # 1. Params-???????? ???????? ????????
        username = request.query_params.get('username', '').strip()
        otp_entered = request.query_params.get('otp', '').strip()

        try:
            # 2. ??????? Username-? ?????? Profile-???????? Email-? ??????????
            profile = Profiles.objects.filter(name=username).first()
            
            if not profile:
                return Response({
                    "status": {"code": 404, "response": "failed"},
                    "message": "User not found."
                }, status=status.HTTP_404_NOT_FOUND)

            email = profile.email

            # 3. OTP ???????? ???? Email ??????? OTP ?????????? ????? ?????????
            otp_record = Otp.objects.filter(email=email, otp=otp_entered).first()

            if otp_record:
                # OTP ???! (??????????? ??????? ??????????)
                return Response({
                    "status": {"code": 200, "response": "success"},
                    "message": "OTP Verified successfully."
                }, status=status.HTTP_200_OK)
            else:
                # OTP ????? ?????????
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Invalid OTP. Please check the code."
                }, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            return Response({
                "status": {"code": 500, "response": "failed"},
                "message": str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class SendotpsAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            email = data.get('email', None)
            print('Received email:', email)

            # If this is registration
            if User.objects.filter(email=email).exists():
                return Response({
                    "status": {"code": status.HTTP_409_CONFLICT, "response": "Email already registered"},
                    "error": True,
                    "message": "This email is already registered. Please use another email."
                })

            otp = get_random_string(length=6, allowed_chars='1234567890')
            user = Otp.objects.create(email=email, otp=otp, otp_created_at=timezone.now())

            threading.Thread(target=send_otp_emails, args=(email, otp)).start()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "Success"},
                "error": None,
                "data": {"email": email}
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "Internal Server Error"},
                'error': True,
                "message": str(e)
            })

from datetime import timedelta
from django.utils import timezone

class VerifyotpAPIView(APIView):
    def get(self, request):
        email = request.query_params.get('email')
        otp_entered = request.query_params.get('otp')

        try:
            user_otp = Otp.objects.filter(email=email).latest('otp_created_at')

            # Expiry time check (30 seconds)
            expiration_time = user_otp.otp_created_at + timedelta(seconds=60)
            if timezone.now() > expiration_time:
                return Response({
                    "status": 401,
                    "message": "OTP expired. Please request a new one.",
                    "error": True
                }, status=status.HTTP_200_OK) 

            if otp_entered == user_otp.otp:
                return Response({
                    "status": 200,
                    "message": "OTP Verified",
                    "error": False
                }, status=status.HTTP_200_OK)
            else:
                return Response({
                    "status": 400,
                    "message": "Invalid OTP",
                    "error": True
                }, status=status.HTTP_200_OK)

        except Otp.DoesNotExist:
            return Response({
                "status": 404,
                "message": "OTP not found",
                "error": True
            }, status=status.HTTP_200_OK)




    def delete(self, request, id):
        if id is not None:
            try:
                profile = Profiles.objects.get(user_id=id)

                # Delete the image file from storage (optional)
                if profile.profiles:  # replace 'image' with your actual image field name
                    profile.profiles.delete(save=False)  # Deletes the file from MEDIA folder
                    profile.profiles = None
                    profile.save()

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Profile image deleted successfully"
                })

            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": None,
                    "message": "Profile not found"
                })

        return Response({
            "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
            "error": "ID not provided",
            "message": "User ID is required"
        })




class ProfileupdateAPIView(APIView):
    
    permission_classes = (IsAuthenticated,)

    def get(self, request, **kwargs):
        id = kwargs.get('id')


        if id is not None:
            try:
                user = User.objects.get(id=id)
                company = Profiles.objects.get(user_id=user.id)
                if company.profiles and company.profiles.url != "../static/dummy.png":
                    pr = company.profiles.url
                else:
                    pr = "../static/dummy.png"

                data = {
                    'name': company.name,
                    'email': company.email,
                    'phone': company.phone,
                    'f_name': user.first_name,
                    'l_name': user.last_name,

                    'profile' : pr,
                    'id': user.id   
                }



                

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "Success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "Failed"},
                    'error': True,
                    "message": "Company not found"
                })

    def post(self, request):
        data = request.data
        try:


            pho = data.get("prof_photo")
            # name = data.get("username")

            take = Profiles.objects.get(user_id=request.user.id)
            take.profiles = pho

            take.save()
            # # Create User instance
            # van = User(username=name, email=email, password=hashed_password)
            # van.save()

           

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Profile updated successfully"
            })

        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {str(e)}"
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "failed"},
                "error": True,
                "message": f"An error occurred: {str(e)}"
            })


    def put(self, request, id):
        data = request.data
        # 1. ???????? FILES-?? ??????? ??????????
        photo = request.FILES.get('prof_photo') 
        
        try:
            mm = Profiles.objects.get(user_id=id)
            sd = User.objects.get(id=id)

            # 2. User ?????? ??????? (get() ?????????????? ?????????????)
            sd.username = data.get("first_name", sd.username)
            sd.first_name = data.get("first_names", sd.first_name)
            sd.last_name = data.get("last_name", sd.last_name)
            sd.email = data.get("email_id", sd.email)
            sd.save()

            # 3. Profiles ?????? ???????
            mm.email = data.get("email_id", mm.email)
            mm.phone = data.get("phone_no", mm.phone)
            mm.name = data.get("first_name", mm.name)

            # 4. ????? ????????? ??????? ??????? ?????????
            if photo:
                mm.profiles = photo
            
            mm.save()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "User updated successfully"
            })

        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "User not found"
            })


class UserlistAPIView(APIView):
    def get(self, request, **kwargs):
        id = kwargs.get('id')


        if id is not None:
            try:
                student = Profiles.objects.get(user_id=id)
                data = {
                    'id': student.user_id,
                    'username': student.name,
                    'phone': student.phone,
                    'password': student.password,
                    'email': student.email,
                   
                    'status': student.status,
                    # Photo URL-? ?????? (????????: http://127.0.0.1:8000/media/students/abc.jpg)
                    'profile_photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except Student.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No student found",
                })
        else:
            try:
                employees = Profiles.objects.filter(role=3)
                employee_list = []
                for index, student in enumerate(employees, 1):
                    employee_list.append({
                        'row': index,
                        'id': student.user_id,
                        'employeeName': student.name,
                        'email': student.email,
                        'phone': student.phone,
                        'status': student.status,

                        'photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": employee_list
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })


class RegisterAPIView(APIView):
    def get(self, request, **kwargs):
        id = kwargs.get('id')


        if id is not None:
            try:
                student = Profiles.objects.get(user_id=id)
                data = {
                    'id': student.user_id,
                    'username': student.name,
                    'phone': student.phone,
                    'password': student.password,
                    'email': student.email,
                   
                    'status': student.status,
                    # Photo URL-? ?????? (????????: http://127.0.0.1:8000/media/students/abc.jpg)
                    'profile_photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except Student.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No student found",
                })
        else:
            try:
                employees = Profiles.objects.filter(role=0).order_by('-created_at')
                employee_list = []
                for index, student in enumerate(employees, 1):
                    employee_list.append({
                        'row': index,
                        'id': student.user_id,
                        'employeeName': student.name,
                        'email': student.email,
                        'phone': student.phone,
                        'status': student.status,

                        'photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": employee_list
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })
            
    def post(self, request):
        data = request.data
        photo = request.FILES.get('profile_photo')

        try:
            username     = data.get('username')
            email        = data.get('email')
            phone        = data.get('phone')
            password     = data.get('password')
            role         = data.get('role')         # "2" = Provider, "3" = User
            skill_summary = data.get('skill_summary', '')

            # --- Role Setup ---
            if role == "2":      # Service Provider
                roles          = "2"
                profile_status = "2"   # Admin approve ??? inactive
            elif role == "3":    # Normal User
                roles          = "3"
                profile_status = "2"   # ???? active
            else:
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Invalid role selected."
                }, status=400)

            # --- Validations (role specific) ---
            if Profiles.objects.filter(name=username, role=roles).exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": f"Username '{username}' is already taken."
                }, status=400)

            if Profiles.objects.filter(email=email, role=roles).exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "This email address is already registered."
                }, status=400)

            if Profiles.objects.filter(phone=phone, role=roles).exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "This mobile number is already registered."
                }, status=400)

            # Service Provider — Skill Summary ????????
            if role == "2" and not skill_summary.strip():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Skill summary is required for Service Providers."
                }, status=400)

            # --- Create User + Profile ---
            with transaction.atomic():
                hashed_password = make_password(password)
                user = User.objects.create(
                    username=username,
                    email=email,
                    password=hashed_password
                )

                Profiles.objects.create(
                    name=username,
                    email=email,
                    phone=phone,
                    role=roles,
                    status=profile_status,
                    user_id=user.id,
                    password=password,
                    profiles=photo,
                    servicename=skill_summary  # ?? Model-?? ???? field ??????????
                )

            return Response({
                "status": {"code": 201, "response": "success"},
                "error": None,
                "message": "Account created successfully",
            }, status=201)

        except Exception as e:
            return Response({
                "status": {"code": 400, "response": "failed"},
                "error": True,
                "message": f"Error: {str(e)}"
            }, status=400)
    # def post(self, request):
    #     data = request.data
    #     # ??????? ??????? "profile_photo" ????? ?????????????, ??? ????? ???????????
    #     photo = request.FILES.get('profile_photo') 


    #     try:
    #         username = data.get('username')
    #         email = data.get('email')
    #         phone = data.get('phone')
    #         password = data.get('password')
    #         role = data.get('role')


    #         if role == "3":
    #             roles  = "3"
    #             profile_status = "2"

    #         else:
    #             roles = "0"
    #             profile_status = "1"



    #         if Profiles.objects.filter(name=username, role="3").exists():
    #             return Response({
    #                 "status": {"code": 400, "response": "failed"},
    #                 "message": f"Username '{username}' is already taken."
    #             }, status=status.HTTP_400_BAD_REQUEST)

    #         # 2. Check if Email already exists
    #         if Profiles.objects.filter(email=email, role="3").exists():
    #             return Response({
    #                 "status": {"code": 400, "response": "failed"},
    #                 "message": "This email address is already registered."
    #             }, status=status.HTTP_400_BAD_REQUEST)

    #         # 3. Check if Phone already exists
    #         if Profiles.objects.filter(phone=phone, role="3").exists():
    #             return Response({
    #                 "status": {"code": 400, "response": "failed"},
    #                 "message": "This mobile number is already registered."
    #             }, status=status.HTTP_400_BAD_REQUEST)


    #         # 1. User ????????????
    #         hashed_password = make_password(password)
    #         van = User.objects.create(
    #             username=username, 
    #             email=email, 
    #             password=hashed_password
    #         )

    #         # 2. Profile ????????????
    #         photo = request.FILES.get('profile_photo') 

    #         profile = Profiles.objects.create(
    #             name=username,
    #             email=email,
    #             phone=phone,
    #             role=roles,
    #             status=profile_status,   # ?? Added Here

    #             user_id=van.id,
    #             password=password,
    #             profiles=photo  # ?? ?????? Database Column ????? 'profiles' ??????? ??? ???
    #         )

    #         return Response({
    #             "status": {"code": 201, "response": "success"},
    #             "error": None,
    #             "message": "Employee created successfully",
    #         }, status=status.HTTP_201_CREATED)

    #     except Exception as e:
    #         return Response({
    #             "status": {"code": 400, "response": "failed"},
    #             "error": True,
    #             "message": f"Error: {str(e)}"
    #     }, status=status.HTTP_400_BAD_REQUEST)


    
    def put(self, request, id):
        data = request.data
        # ??????? ??????? "profile_photo" ????? ?????????????, ??? ????? ???????????
        photo = request.FILES.get('profile_photo') 
        
        try:
                photo = request.FILES.get('profile_photo') 

                username = data.get('username')
                email = data.get('email')
                phone = data.get('phone')
                password = data.get('password')
                mm = Profiles.objects.get(user_id=id)
                sd = User.objects.get(id=id)

                mm.name = username
                mm.email = email
                mm.phone = phone

                mm.password = password

                if photo:
                    mm.profiles = photo
                mm.save()
                passes = make_password(password) 
                sd.username = username
                sd.email = email
                sd.password = passes
                sd.save()

                return Response({
                    "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                    "error": None,
                    "message": "User updated successfully"
                })
        except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": "Something went wrong"
                })

    def delete(self,  *args, **kwargs):
        company_id = kwargs.get('id')

        try:

            pr  = Profiles.objects.get(user_id =company_id)
            pr.delete()
            company = User.objects.get(id=company_id)
            company.delete()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "Company deleted successfully"
            })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "No data found"
            })



class CompanydashboardAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request):
        
        try:
            from django.utils.timezone import now

            op = request.user.id

            totalenquiry = Product.objects.filter(created_by_id=op).count()

            from django.utils.timezone import now
            from datetime import timedelta

            op = request.user.id

            # Get current date
            current_date = now()

            

            totalvendorlastmonth = 6
            totalvendor=5
            totalenquirytodaydate=6
            activevendor=6
            monthdata=7
            inactivevendor=8
            last_month_enquiry=9
            current_month_enquiry=8
            current_month_auction=5
            last_month_auction=4
            current_month_product=2
            last_month_product=2
            
                
            data = {
                "totalenquiry": totalenquiry,
                "totalvendor": totalvendor,
                "totalenquirytodaydate": totalenquirytodaydate,
                "activevendor" : activevendor,
                "inactivevendor" : inactivevendor,
                "monthdata" : monthdata,
                "totalvendorlastmonth" :totalvendorlastmonth,
                "current_month_enquiry" : current_month_enquiry,
                "last_month_enquiry" : last_month_enquiry,
                "current_month_auction" : current_month_auction,
                "last_month_auction" : last_month_auction,
                "current_month_product" : current_month_product,
                "last_month_product" : last_month_product

            }

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "data": data
            })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "No data found",
            })
        



class AdmindashboardAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request):
        
        try:
            from django.utils.timezone import now

            op = request.user.id

            current_date = now()
            

            activecompany = Profiles.objects.filter(status=1, role=0).count()
            inactivecompany = Profiles.objects.filter(status = 2, role=0).count()

            import calendar
            from datetime import datetime
            monthdata = []
            current_year = datetime.now().year
            current_month = datetime.now().month
            bak = current_month+1
            from django.db.models import Sum

            # Loop from January (1) to May (5)
            for month in range(1, bak):
                month_name = calendar.month_abbr[month]  # 'Jan', 'Feb', etc.

                payment = 0

                monthdata.append({
                    'monthname': month_name,
                    'counts': payment
                })

            




            totalcompany = Profiles.objects.filter(role=0).count()
            paidcompany = 0
            unpaidcompany  = 0

            qp = Profiles.objects.filter(role=0)
            for b in qp:
                try:
                    2
                    # User has payment ? skip
                except Payment.DoesNotExist:
                    3
                        

            
            

            
                
            data = {
                "paidcompany": paidcompany,
                "unpaidcompany": unpaidcompany,

                "totalcompany": totalcompany,
               
                "activecompany" : activecompany,
                "inactivecompany" : inactivecompany,
                "monthdata" : monthdata
            }
            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "data": data
            })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "No data found",
            })



    



class CheckcompanyAPIView(APIView):
    def get(self, request, id=None):
        phone = request.query_params.get('phone')
        email = request.query_params.get('email')
        name = request.query_params.get('username')

       
        gstnumber = request.query_params.get('gstnumber') or request.query_params.get('gst')



        print("Check Params:", phone, email, gstnumber)

        if phone or email or gstnumber or name:
            query = Q()
            if name:
                query |= Q(name=name)
            if phone:
                query |= Q(phone=phone)
            if email:
                query |= Q(email=email)
            if gstnumber:
                query |= Q(gstnumber=gstnumber)

            exists = Profiles.objects.filter(query).exists()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "exists": exists
            })

        return Response({
            "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
            "error": True,
            "message": "No phone, email, or GST provided."
        }, status=status.HTTP_400_BAD_REQUEST)


class ProductAPIView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                company = Product.objects.get(id=id)

               
                data = {
                    'id': company.id,
                    'company_name': company.company_name,
                    'application': company.application,
                    'project_name': company.project_name,
                    'country': company.country,
                    'bidclosedate': company.bidclosedate,
                    'deliverydate': company.deliverydate,


                    's2dailyflow' : company.s2dailyflow,
                    's2monthflow' : company.s2monthflow,
                    's2weekflow': company.s2weekflow,
                    's2maxdailyflow': company.s2maxdailyflow,
                    's2hourflow': company.s2hourflow,
                    's2bod': company.s2bod,
                    's2bodout': company.s2bodout,
                    's2bodrate': company.s2bodrate,
                    
                    's2cod': company.s2cod,
                    's2codout': company.s2codout,
                    's2codrate': company.s2codrate,

                    's2tss': company.s2tss,
                    's2tssout': company.s2tssout,
                    's2tssrate': company.s2tssrate,

                    's2tn': company.s2tn,
                    's2tnout': company.s2tnout,
                    's2tnrate': company.s2tnrate,


                    's2tp': company.s2tp,
                    's2tpout': company.s2tpout,
                    's2tprate': company.s2tprate,

                    's2oil': company.s2oil,
                    's2oilout': company.s2oilout,
                    's2oilrate': company.s2oilrate,

                    's2avgwatertemp': company.s2avgwatertemp,
                    's2avgwatertempout': company.s2avgwatertempout,
                    's2avgwatertemprate': company.s2avgwatertemprate,

                    's2maxwatertemp': company.s2maxwatertemp,
                    's2maxwatertempout': company.s2maxwatertempout,
                    's2maxwatertemprate': company.s2maxwatertemprate,

                    's2minwatertemp': company.s2minwatertemp,
                    's2minwatertempout': company.s2minwatertempout,
                    's2minwatertemprate': company.s2minwatertemprate,






                    'Davgflux1': company.Davgflux1,
                    'Davgflux2': company.Davgflux2,
                    'Dpeakflux': company.Dpeakflux,

                    'Msurfacearea1': company.Msurfacearea1,
                    'Msurfacearea2': company.Msurfacearea2,
                    'productcode': company.productcode,


                    'Noofmodule': company.Noofmodule,
                    'Noofmtrain': company.Noofmtrain,
                    'Noofmptrain': company.Noofmptrain,
                    'TNM': company.TNM,
                    'TMsurfacearea': company.TMsurfacearea,
                    'Aavgflux1': company.Aavgflux1,
                    'Aavgflux2': company.Aavgflux2,
                    'Apeakflux1': company.Apeakflux1,
                    'Apeakflux2': company.Apeakflux2,

                    's4AT1': company.s4AT1,
                    's4AT2': company.s4AT2,
                    's4AT3': company.s4AT3,
                    's4AT4': company.s4AT4,
                    's4AT5': company.s4AT5,
                    's4AT6': company.s4AT6,
                    's4AT7': company.s4AT7,

                    's4TT1': company.s4TT1,
                    's4TT2': company.s4TT2,
                    's4TT3': company.s4TT3,
                    's4TT4': company.s4TT4,
                    's4TT5': company.s4TT5,
                    's4TT6': company.s4TT6,
                    's4TT7': company.s4TT7,

                    's4MT1': company.s4MT1,
                    's4MT2': company.s4MT2,
                    's4MT3': company.s4MT3,
                    's4MT4': company.s4MT4,
                    's4MT5': company.s4MT5,
                    's4MT6': company.s4MT6,
                    's4MT7': company.s4MT7,






                    



                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                index = 0
                companies = []

                
                products = Product.objects.filter(created_by_id=request.user.id)

                


                for company in products:
                    index += 1

                   

                    companies.append({
                        'row': index,
                        'id': company.id,
                        'company_name': company.company_name,
                        'application': company.application,
                        'project_name': company.project_name,
                        'country': company.country,

                       
                        'status': company.status,

                    })


                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

    def post(self, request):
        data = request.data

        try:
            company = Product.objects.create(
                company_name=data["company_name"],
                project_name=data["project_name"],
                application =data["application"],
                country =data["country"],

                deliverydate = data["deliverydate"],
                bidclosedate = data["bidclosedate"],


                s2dailyflow = data["s2dailyflow"],
                s2monthflow = data["s2monthflow"],
                s2weekflow = data["s2weekflow"],
                s2maxdailyflow = data["s2maxdailyflow"],
                s2hourflow = data["s2hourflow"],
                s2bod = data["s2bod"],
                s2bodout = data["s2bodout"],
                s2bodrate = data["s2bodrate"],
                s2cod = data["s2cod"],
                s2codout = data["s2codout"],
                s2codrate = data["s2codrate"],
                s2tss = data["s2tss"],
                s2tssout = data["s2tssout"],
                s2tssrate = data["s2tssrate"],
                s2tn = data["s2tn"],
                s2tnout = data["s2tnout"],
                s2tnrate = data["s2tnrate"],
                s2tp = data["s2tp"],
                s2tpout = data["s2tpout"],
                s2tprate = data["s2tprate"],
                s2oil = data["s2oil"],
                s2oilout = data["s2oilout"],
                s2oilrate = data["s2oilrate"],
                s2avgwatertemp = data["s2avgwatertemp"],
                s2avgwatertempout = data["s2avgwatertempout"],
                s2avgwatertemprate = data["s2avgwatertemprate"],
                s2maxwatertemp = data["s2maxwatertemp"],
                s2maxwatertempout = data["s2maxwatertempout"],
                s2maxwatertemprate = data["s2maxwatertemprate"],
                s2minwatertemp = data["s2minwatertemp"],
                s2minwatertempout = data["s2minwatertempout"],
                s2minwatertemprate = data["s2minwatertemprate"],


                Davgflux1 = data["Davgflux1"],
                Davgflux2 = data["Davgflux2"],
                Dpeakflux = data["Dpeakflux"],
                Msurfacearea1 = data["Msurfacearea1"],
                Msurfacearea2 = data["Msurfacearea2"],
                productcode = data["productcode"],
                Noofmodule = data["Noofmodule"],
                Noofmtrain = data["Noofmtrain"],
                Noofmptrain = data["Noofmptrain"],
                TNM = data["TNM"],
                TMsurfacearea = data["TMsurfacearea"],
                Aavgflux1 = data["Aavgflux1"],
                Aavgflux2 = data["Aavgflux2"],
                Apeakflux1 = data["Apeakflux1"],
                Apeakflux2 = data["Apeakflux2"],


                s4AT1 = data["s4AT1"],
                s4AT2 = data["s4AT2"],
                s4AT3 = data["s4AT3"],
                s4AT4 = data["s4AT4"],
                s4AT5 = data["s4AT5"],
                s4AT6 = data["s4AT6"],
                s4AT7 = data["s4AT7"],

                
                s4TT1 = data["s4TT1"],
                s4TT2 = data["s4TT2"],
                s4TT3 = data["s4TT3"],
                s4TT4 = data["s4TT4"],
                s4TT5 = data["s4TT5"],
                s4TT6 = data["s4TT6"],
                s4TT7 = data["s4TT7"],

                s4MT1 = data["s4MT1"],
                s4MT2 = data["s4MT2"],
                s4MT3 = data["s4MT3"],
                s4MT4 = data["s4MT4"],
                s4MT5 = data["s4MT5"],
                s4MT6 = data["s4MT6"],
                s4MT7 = data["s4MT7"],





                

                created_by=request.user
            )
            company.save()

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Product created successfully"
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })





    def put(self, request, id):
        data = request.data

        try:

          

            company = Product.objects.get(id=id)
            company.company_name = data.get("company_name", company.company_name)
            company.project_name = data.get("project_name", company.project_name)
            company.application = data.get("application", company.application)
            company.country = data.get("country", company.country) 
            company.deliverydate = data.get("deliverydate", company.deliverydate)
            company.bidclosedate = data.get("bidclosedate", company.bidclosedate)




            company.s2dailyflow = data.get("s2dailyflow", company.s2dailyflow)
            company.s2monthflow = data.get("s2monthflow", company.s2monthflow)
            company.s2weekflow= data.get("s2weekflow", company.s2weekflow)
            company.s2maxdailyflow= data.get("s2maxdailyflow", company.s2maxdailyflow)
            company.s2hourflow= data.get("s2hourflow", company.s2hourflow)
            company.s2bod= data.get("s2bod", company.s2bod)
            company.s2bodout= data.get("s2bodout", company.s2bodout)
            company.s2bodrate= data.get("s2bodrate", company.s2bodrate)
            
            company.s2cod= data.get("s2cod", company.s2cod)
            company.s2codout= data.get("s2codout", company.s2codout)
            company.s2codrate= data.get("s2codrate", company.s2codrate)

            company.s2tss= data.get("s2tss", company.s2tss)
            company.s2tssout= data.get("s2tssout", company.s2tssout)
            company.s2tssrate= data.get("s2tssrate", company.s2tssrate)

            company.s2tn= data.get("s2tn", company.s2tn)
            company.s2tnout= data.get("s2tnout", company.s2tnout)
            company.s2tnrate= data.get("s2tnrate", company.s2tnrate)
            company.s2tp= data.get("s2tp", company.s2tp)
            company.s2tpout= data.get("s2tpout", company.s2tpout)
            company.s2tprate= data.get("s2tprate", company.s2tprate)

            company.s2oil= data.get("s2oil", company.s2oil)
            company.s2oilout= data.get("s2oilout", company.s2oilout)
            company.s2oilrate= data.get("s2oilrate", company.s2oilrate)

            company.s2avgwatertemp= data.get("s2avgwatertemp", company.s2avgwatertemp)
            company.s2avgwatertempout= data.get("s2avgwatertempout", company.s2avgwatertempout)
            company.s2avgwatertemprate= data.get("s2avgwatertemprate", company.s2avgwatertemprate)

            company.s2maxwatertemp= data.get("s2maxwatertemp", company.s2maxwatertemp)
            company.s2maxwatertempout= data.get("s2maxwatertempout", company.s2maxwatertempout)
            company.s2maxwatertemprate= data.get("s2maxwatertemprate", company.s2maxwatertemprate)

            company.s2minwatertemp= data.get("s2minwatertemp", company.s2minwatertemp)
            company.s2minwatertempout= data.get("s2minwatertempout", company.s2minwatertempout)
            company.s2minwatertemprate= data.get("s2minwatertemprate", company.s2minwatertemprate)


            company.Davgflux1= data.get("Davgflux1", company.Davgflux1)
            company.Davgflux2= data.get("Davgflux2", company.Davgflux2)
            company.Dpeakflux= data.get("Dpeakflux", company.Dpeakflux)
            company.Msurfacearea1= data.get("Msurfacearea1", company.Msurfacearea1)
            company.Msurfacearea2= data.get("Msurfacearea2", company.Msurfacearea2)
            company.productcode= data.get("productcode", company.productcode)
            company.Noofmodule= data.get("Noofmodule", company.Noofmodule)
            company.Noofmtrain= data.get("Noofmtrain", company.Noofmtrain)
            company.Noofmptrain= data.get("Noofmptrain", company.Noofmptrain)
            company.TNM= data.get("TNM", company.TNM)
            company.TMsurfacearea= data.get("TMsurfacearea", company.TMsurfacearea)
            company.Aavgflux1= data.get("Aavgflux1", company.Aavgflux1)
            company.Aavgflux2= data.get("Aavgflux2", company.Aavgflux2)
            company.Apeakflux1= data.get("Apeakflux1", company.Apeakflux1)
            company.Apeakflux2= data.get("Apeakflux2", company.Apeakflux2)

            company.s4AT1= data.get("s4AT1", company.s4AT1)
            company.s4AT2= data.get("s4AT2", company.s4AT2)
            company.s4AT3= data.get("s4AT3", company.s4AT3)
            company.s4AT4= data.get("s4AT4", company.s4AT4)
            company.s4AT5= data.get("s4AT5", company.s4AT5)
            company.s4AT6= data.get("s4AT6", company.s4AT6)
            company.s4AT7= data.get("s4AT7", company.s4AT7)

            company.s4TT1= data.get("s4TT1", company.s4TT1)
            company.s4TT2= data.get("s4TT2", company.s4TT2)
            company.s4TT3= data.get("s4TT3", company.s4TT3)
            company.s4TT4= data.get("s4TT4", company.s4TT4)
            company.s4TT5= data.get("s4TT5", company.s4TT5)
            company.s4TT6= data.get("s4TT6", company.s4TT6)
            company.s4TT7= data.get("s4TT7", company.s4TT7)

            company.s4MT1= data.get("s4MT1", company.s4MT1)
            company.s4MT2= data.get("s4MT2", company.s4MT2)
            company.s4MT3= data.get("s4MT3", company.s4MT3)
            company.s4MT4= data.get("s4MT4", company.s4MT4)
            company.s4MT5= data.get("s4MT5", company.s4MT5)
            company.s4MT6= data.get("s4MT6", company.s4MT6)
            company.s4MT7= data.get("s4MT7", company.s4MT7)








             

            company.save()



            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "Product updated successfully"
            })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "No data found"
            })
        except Exception as e:
            print(e)
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": "Something went wrong"
            })

   


    def delete(self, request, id):
        if id is not None:
            try:
                # product_id_str = str(id)
                # is_used = Product.objects.filter(product__contains=[product_id_str]).exists()

                # if is_used:
                #     return Response({
                #         "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                #         "error": "Product is used in enquiry",
                #         "message": "Cannot delete product. It's used in one or more enquiries."
                #     })

                # If not used, delete the product
                product = Product.objects.get(id=id)
                product.delete()

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Product deleted successfully"
                })

            except Product.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": None,
                    "message": "No product found"
                })

class UserBookingAPIView(APIView):
    # ?????? ????? ????? ????? ?????? (????????????? ??????? ??????????????)
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            # ??? ??????????? ???????? ???????? ??????? ???????
            try:
                booking = UserBooking.objects.get(id=id)
                data = {
                    'id': booking.id,
                    'provider_name': booking.provider.name if booking.provider else "Unknown",
                    'category_name': booking.category_name,
                    'action_type': booking.action_type,
                    'status': booking.booking_status,
                    'created_at': booking.created_at.strftime("%Y-%m-%d %H:%M:%S")
                }
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "Booking not found",
                })
        else:
            # ?????? ????? ??????? ??????? ???????? ????????????? ???????
            try:
                # ????? ?????? ????? ????? ??????? ??????? ??????????
                # ??????? ?????????????? ??????? ?????????????? .all() ??????????????
                user_id = request.user.id if request.user.is_authenticated else None
                
                if user_id:
                    bookings = UserBooking.objects.filter(user_id=user_id).order_by('-created_at')
                else:
                    bookings = UserBooking.objects.all().order_by('-created_at')

                booking_list = []
                index = 0
                for item in bookings:
                    index += 1
                    booking_list.append({
                        'row': index,
                        'id': item.id,
                        'provider_name': item.provider.name if item.provider else "N/A",
                        'category_name': item.category_name,
                        'action_type': item.action_type,
                        'booking_status': item.booking_status,
                        'created_at': item.created_at # ?????? ??????? ??? ?????????? ????? ??????????
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": booking_list
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "failed"},
                    "error": str(e)
                })

    def post(self, request):
        data = request.data
        try:
            # 1. ??????? ????????? ???????????????
            provider_id = data.get("provider_id")
            category_name = data.get("category_name")
            action_type = data.get("action_type") # 'Call' or 'WhatsApp'

            # 2. ?????? ????? ????? ??????????? (??????? ????? ??????? None)
            current_user = request.user if request.user.is_authenticated else None

            # 3. ????? ?????????? ???????????????
            new_booking = UserBooking.objects.create(
                user=current_user,
                provider_id=provider_id,
                category_name=category_name,
                action_type=action_type,
                booking_status=0 # Default: Pending
            )

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Contact logged successfully",
                "data": {
                    "id": new_booking.id,
                    "action": new_booking.action_type
                }
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Error saving booking: {str(e)}"
            })


class ClientAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                company = Product.objects.get(id=id)

                try:
                    fl = company.sfile.url if company.sfile else None
                except ValueError:
                    fl = None 
                data = {
                    'id': company.id,
                    'name': company.name,
                    'code': company.code,

                    'description': company.description,
                    'specification':company.specification,
                    'sfile': fl,
                    'status': company.status

                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                index = 0
                companies = []

                # user_id = request.query_params.get('user_id')
             
                # name = request.query_params.get('name', '').strip()  # Uncomment this line
                # status_param = request.query_params.get('status', '').strip()

                # if user_id:
                #     products = Product.objects.filter(created_by_id=user_id)
                # else:
                #     products = Product.objects.filter(created_by_id=request.user.id)

                

                client = Client.objects.all()

                for company in client:
                    index += 1


                    companies.append({
                        'row': index,
                        'id': company.id,
                        'client_name': company.client_name,
                        'phone': company.phone,

                        'email': company.email,
                        'address': company.address,
                        'doj': company.doj,

                    })


                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

    def post(self, request):
        data = request.data

        try:
            company = Client.objects.create(
                client_name=data["clientName"],

                phone=data["mobilenumber"],
                address =data["address"],
                # email =data["email"],
                # aadhar =data["aadharNumber"],
                # pan =data["panNumber"],
                # doj =data["dateOfJoining"],



                # created_by=request.user
            )
            company.save()

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Client created successfully",
                 "data": {
                "id": company.id,  # ???? ID ???? ????????? ????
                "client": company.client_name
            }
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })





    # def put(self, request, id):
    #     data = request.data

    #     try:

    #         ve =data.get("sfile")

    #         company = Product.objects.get(id=id)
    #         company.name = data.get("name", company.name)
    #         company.code = data.get("code", company.code)

    #         company.description = data.get("description", company.description)
    #         company.specification = data.get("specification", company.specification)
    #         company.sfile = data.get("sfile", company.sfile) 
    #         company.status = data.get("status", company.status)
    #         company.save()

    #         return Response({
    #             "status": {"code": status.HTTP_200_OK, "response": "success"},
    #             "error": None,
    #             "message": "Product updated successfully"
    #         })
    #     except ObjectDoesNotExist:
    #         return Response({
    #             "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
    #             "error": True,
    #             "message": "No data found"
    #         })
    #     except Exception as e:
    #         print(e)
    #         return Response({
    #             "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
    #             "error": True,
    #             "message": "Something went wrong"
    #         })

   


    # def delete(self, request, id):
    #     if id is not None:
    #         try:
    #             product_id_str = str(id)
    #             is_used = Enquiry.objects.filter(product__contains=[product_id_str]).exists()

    #             if is_used:
    #                 return Response({
    #                     "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
    #                     "error": "Product is used in enquiry",
    #                     "message": "Cannot delete product. It's used in one or more enquiries."
    #                 })

    #             # If not used, delete the product
    #             product = Product.objects.get(id=id)
    #             product.delete()

    #             return Response({
    #                 "status": {"code": status.HTTP_200_OK, "response": "success"},
    #                 "error": None,
    #                 "message": "Product deleted successfully"
    #             })

    #         except Product.DoesNotExist:
    #             return Response({
    #                 "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
    #                 "error": None,
    #                 "message": "No product found"
    #             })



class DashboardStatsAPIView(APIView):
    def get(self, request):
        date_str = request.query_params.get('date', None)
        target_date = datetime.strptime(date_str, '%Y-%m-%d').date() if date_str else timezone.now().date()

        all_students = Student.objects.filter(status=1)
        
        # Attendance filtering
        n_present_ids = Attendance.objects.filter(date=target_date, session_type=1, status="Present").values_list('student_id', flat=True)
        s_present_ids = Attendance.objects.filter(date=target_date, session_type=2, status="Present").values_list('student_id', flat=True)

        # Count total eligible students for each type
        n_total = all_students.filter(classType__in=[1, 3]).count()
        s_total = all_students.filter(classType__in=[2, 3]).count()

        n_present = len(n_present_ids)
        s_present = len(s_present_ids)

        # Percentage calculation
        n_percent = int((n_present / n_total) * 100) if n_total > 0 else 0
        s_percent = int((s_present / s_total) * 100) if s_total > 0 else 0

        student_daily_list = []
        for student in all_students:
            is_n_elg = student.classType in [1, 3]
            is_s_elg = student.classType in [2, 3]
            
            n_status = "P" if student.id in n_present_ids else ("A" if is_n_elg else "--")
            s_status = "P" if student.id in s_present_ids else ("A" if is_s_elg else "--")

            student_daily_list.append({
                "name": student.studentName,
                "n_status": n_status,
                "s_status": s_status,
                "is_special": is_s_elg
            })

        return Response({
            "status": {"code": 200, "response": "success"},
            "data": {
                "n_data": {"present": n_present, "total": n_total, "percent": n_percent},
                "s_data": {"present": s_present, "total": s_total, "percent": s_percent},
                "student_list": student_daily_list,
                "selected_date": target_date.strftime('%Y-%m-%d')
            }
        })
class ProviderClassCountAPIView(APIView):
    def get(self, request, id):
        try:

            provider_category = []

            tak  = Profiles.objects.get(id=id)

            man = CategoryServiceProvider.objects.filter(provider_id=tak.id)

            for i in man:
                kop = Category.objects.get(id=i.category_id)

              

                provider_category.append({
                        'id': kop.id,
                        'name': kop.name,
                       
                })

            



            return Response({
                "status": {"code": 200, "response": "success"},
                "data": {
                    "datas": provider_category,
                }
            })
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
class ProviderAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                student = Student.objects.get(id=id)
                data = {
                    'id': student.id,
                    'studentName': student.studentName,
                    'parentName': student.parentName,
                    'mobilenumber': student.mobilenumber,
                    'age': student.age,
                    'address': student.address,
                    'classType': student.classType,
                    'monthly_fees': student.monthly_fees,

                    'dateOfJoining': student.dateOfJoining,
                    'status': student.status,
                    # Photo URL-? ?????? (????????: http://127.0.0.1:8000/media/students/abc.jpg)
                    'photo': request.build_absolute_uri(student.photo.url) if student.photo else None
                }
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except Student.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No student found",
                })
        else:
            try:
                students = Profiles.objects.filter(role=2)
                student_list = []
                for index, student in enumerate(students, 1):
                    student_list.append({
                        'row': index,
                        'id': student.id,
                        'studentName': student.name,
                        'email': student.email,
                        'skill': student.servicename,
                        'address': student.address,
                        'status': student.status,

                        # 'age': student.age,
                        'photo': None
                    })


                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": student_list
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })

    def post(self, request):
        # multipart/form-data ????? ????? ??????? ??????
        data = request.data
        photo = request.FILES.get('photo') # ???????? ??????

        try:
            # classType-? ?????????
            frontend_class = data.get('classType', '[]')
            # FormData-???? ?????? string-?? ?? ?????????????, ?????? json.loads ?????????????????
            if isinstance(frontend_class, str):
                try:
                    frontend_class = json.loads(frontend_class)
                except:
                    frontend_class = []

            final_class_id = 1
            if 'Normal' in frontend_class and 'Special' in frontend_class:
                final_class_id = 3
            elif 'Special' in frontend_class:
                final_class_id = 2

            # ????? ?????? ??????????? ????????????
            student = Student.objects.create(
                studentName=data.get('studentName'),
                parentName=data.get('parentName'),
                mobilenumber=data.get('mobilenumber'),
                age=data.get('age'),
                monthly_fees=data.get('monthly_fees'),

                address=data.get('address'),
                classType=final_class_id,
                dateOfJoining=data.get('dateOfJoining'),
                photo=photo # ?????? ????? ??????????????
            )
            
            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Student created successfully",
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Error: {str(e)}"
            })

    def put(self, request, id):
        data = request.data
        photo = request.FILES.get('photo')

        try:
            student = Student.objects.get(id=id)
            
            # --- PROBLEM FIXED HERE ---
            # Frontend-?? ??????? ????? ????? (1, 2, 3) ???????? ????????????
            class_data = data.get("classType")
            if class_data is not None:
                try:
                    # ??????? ???????? ?? ??????? ???????? ????????????????
                    student.classType = int(class_data)
                except ValueError:
                    pass

            # ???? ??????? ??????? ???????
            student.studentName = data.get("studentName", student.studentName)
            student.parentName = data.get("parentName", student.parentName)
            student.mobilenumber = data.get("mobilenumber", student.mobilenumber)
            student.age = data.get("age", student.age)
            student.address = data.get("address", student.address)
            student.monthly_fees = data.get("monthly_fees", student.monthly_fees)

            
            # Optional fields
            if "status" in data:
                student.status = data.get("status")
            
            # ????? ?????? ??????? ??????? ???????
            if photo:
                student.photo = photo

            student.save()

            return Response({
                "status": {"code": 200, "response": "success"},
                "message": "Student updated to Class Type " + str(student.classType)
            })

        except Student.DoesNotExist:
            return Response({"status": {"code": 404, "response": "failed"}, "message": "Student not found"})
        except Exception as e:
            return Response({"status": {"code": 400, "response": "failed"}, "message": str(e)})

        except Student.DoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "Student not found"
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": str(e)
            })

    def delete(self, request, id):
        try:

            categories  = CategoryServiceProvider.objects.filter(provider_id=id)
            categories.delete()

            provider = Profiles.objects.get(id=id)

            provider.delete()

            

            
          
            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "message": "Deleted provider successfully"
            })
        except ObjectDoesNotExist:
            return Response({"message": "Not found"}, status=status.HTTP_404_NOT_FOUND)




class JobpostAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                student = JobPost.objects.get(id=id)
                data = {
                    'id': student.id,
                    'title': student.title,
                    'salary': student.salary,
                    'description': student.description,
                    'location': student.location,
                    'category_id': student.category_id,
                    'sub_category_id': student.sub_category_id,


                    

                    'status': student.status,
                    # Photo URL-? ?????? (????????: http://127.0.0.1:8000/media/students/abc.jpg)
                    'poster': request.build_absolute_uri(student.poster.url) if student.poster else None
                }
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except Student.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No student found",
                })
        else:
            try:
                jobpost = JobPost.objects.all().order_by('-created_at')
                job_list = []
                for index, student in enumerate(jobpost, 1):

                    cat = Category.objects.get(id=student.category_id)
                    job_list.append({
                        'row': index,
                        'id': student.id,
                        'category': cat.name,
                        'title': student.title,
                        'location': student.location,
                        'salary': student.salary,
                        'status': student.status,

                        'poster': request.build_absolute_uri(student.poster.url) if student.poster else None
                    })
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": job_list
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })

    def post(self, request):
        # multipart/form-data ????? ????? ??????? ??????
        data = request.data
        poster = request.FILES.get('poster') # ???????? ??????

        try:
            #

            # ????? ?????? ??????????? ????????????
            

            jobpost = JobPost.objects.create(
                salary=data.get('salary'),
                location=data.get('location'),
                description=data.get('description'),

                title=data.get('title'),

                category_id = data.get('category'),
                sub_category_id = data.get('sub_category'),

                poster=poster # ?????? ????? ??????????????
            )
            
            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Student created successfully",
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Error: {str(e)}"
            })

    def put(self, request, id):
        data = request.data
        poster = request.FILES.get('poster')

        try:
            student = JobPost.objects.get(id=id)
            
            # --- PROBLEM FIXED HERE ---
            # Frontend-?? ??????? ????? ????? (1, 2, 3) ???????? ????????????
            

            # ???? ??????? ??????? ???????
            student.title = data.get("title", student.title)
            student.location = data.get("location", student.location)
            student.salary = data.get("salary", student.salary)
            student.description = data.get("description", student.description)
            cat_id = data.get("category")
            if cat_id:
                student.category_id = int(cat_id) # String-? Integer ?? ???????? ????????????

            sub_cat_id = data.get("sub_category")
            if sub_cat_id:
                student.sub_category_id = int(sub_cat_id)

            
            
            if poster:
                student.poster = poster

            student.save()

            return Response({
                "status": {"code": 200, "response": "success"},
                "message": "Student updated to Class Type " + str(student.classType)
            })

        except Student.DoesNotExist:
            return Response({"status": {"code": 404, "response": "failed"}, "message": "Student not found"})
        except Exception as e:
            return Response({"status": {"code": 400, "response": "failed"}, "message": str(e)})

        except Student.DoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "Student not found"
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": str(e)
            })



import random
import string
def generate_receipt_no():
    return 'REC' + ''.join(random.choices(string.digits, k=6))
from datetime import datetime
from django.db.models import Sum as DSum
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Student, Fees, FeesHistory

class FeesAPIView(APIView):
    def get(self, request, id=None):
        current_month = datetime.now().month
        current_year = datetime.now().year

        if id:
            try:
                student = Student.objects.get(id=id)
                m_fees = float(student.monthly_fees)

                # 1. ???? ????????? ??????? ?????? ????
                month_paid = FeesHistory.objects.filter(
                    student_id=id, 
                    payment_date__month=current_month, 
                    payment_date__year=current_year
                ).aggregate(total=DSum('amount_paid'))['total'] or 0
                m_paid = float(month_paid)

                # 2. Master Table-?? ???? ??????
                fee_record = Fees.objects.filter(student_id=id).first()
                db_balance = float(fee_record.balance_amount) if fee_record else 0.0

                # --- ???? (Jim) ????? ????????????? ?4500 ?? ??????? ?????? ---
                # ??????? ????? ????? ???????, ??????? ??????? ????????????? ???????, 
                # ???? ??????????? (500) ???????? ??? ????????? (4000) ????? ????????.
                if m_paid == 0 and db_balance < m_fees:
                    total_payable = db_balance + m_fees
                else:
                    total_payable = db_balance

                # 3. ???? ?????? (Arrears) ????????
                current_month_bal = m_fees - m_paid
                if current_month_bal < 0: current_month_bal = 0
                
                prev_arrears = total_payable - current_month_bal
                if prev_arrears < 0: prev_arrears = 0

                data = {
                    'studentName': student.studentName,
                    'month_fees': m_fees,
                    'month_paid': m_paid,
                    'month_balance': current_month_bal,
                    'previous_balance': prev_arrears,
                    'total_payable': total_payable
                }
                return Response({"status": {"code": 200}, "data": data})
            except Student.DoesNotExist:
                return Response({"status": {"code": 404}, "message": "Student not found"})
        
        else:
            # List View (Feesmanagement.js)
            students = Student.objects.filter(status=1)
            data_list = []
            for student in students:
                m_fees = float(student.monthly_fees)
                month_paid_sum = FeesHistory.objects.filter(
                    student_id=student.id,
                    payment_date__month=current_month,
                    payment_date__year=current_year
                ).aggregate(total=DSum('amount_paid'))['total'] or 0
                
                fee_record = Fees.objects.filter(student_id=student.id).first()
                db_balance = float(fee_record.balance_amount) if fee_record else 0.0
                
                if month_paid_sum == 0 and db_balance < m_fees:
                    total_balance = db_balance + m_fees
                else:
                    total_balance = db_balance

                data_list.append({
                    'id': student.id,
                    'studentName': student.studentName,
                    'fees': m_fees,
                    'balance': total_balance,
                    'paid': float(month_paid_sum),
                })
            return Response({"status": {"code": 200}, "data": data_list})

    def put(self, request, id):
        try:
            student_obj = Student.objects.get(id=id)
            d = request.data
            paid_now = float(d.get('paid_amount', 0))
            new_balance = float(d.get('balance_amount', 0))
            
            fee, created = Fees.objects.get_or_create(student=student_obj, defaults={
                'total_amount': 0, 'paid_amount': 0, 'balance_amount': 0, 'payment_date': datetime.now().date()
            })
            
            fee.paid_amount = float(fee.paid_amount or 0) + paid_now
            fee.balance_amount = new_balance
            fee.save()

            FeesHistory.objects.create(
                student=student_obj, amount_paid=paid_now, payment_date=datetime.now().date()
            )
            return Response({"status": {"code": 200}, "message": "Saved Successfully"})
        except Exception as e:
            return Response({"status": {"code": 400}, "message": str(e)})


class FeesHistoryAPIView(APIView):
    def get(self, request, student_id):
        try:
            # ???????? ??????? ???????? ????????????? ???????? ???????????? ???????????
            history = FeesHistory.objects.filter(student_id=student_id).order_by('-payment_date')
            
            data = []
            for h in history:
                data.append({
                    'id': h.id,
                    'amount_paid': float(h.amount_paid),
                    'payment_date': h.payment_date.strftime('%d-%m-%Y'), # ?????? ???? ??????
                    'payment_mode': h.payment_mode
                })
            return Response({"status": {"code": 200}, "data": data})
        except Exception as e:
            return Response({"status": {"code": 400}, "message": str(e)})
   
class StudentStatusAPIView(APIView):
    def patch(self, request, id):
        try:
            student = Student.objects.get(id=id)
            # 1-?? ????????? 2-???? ?????????, ????????????? 1-???? ?????????
            if student.status == 1:
                student.status = 2
            else:
                student.status = 1
            
            student.save()
            return Response({
                "status": {"code": 200, "response": "success"},
                "new_status": student.status,
                "message": "Status updated successfully"
            })
        except Student.DoesNotExist:
            return Response({"error": "Student not found"}, status=404)
        
class EmployeeStatusAPIView(APIView):
    def patch(self, request, id):
        try:
            student = Profiles.objects.get(user_id=id)
            # 1-?? ????????? 2-???? ?????????, ????????????? 1-???? ?????????
            if student.status == 1:
                student.status = 2
            else:
                student.status = 1
            
            student.save()
            return Response({
                "status": {"code": 200, "response": "success"},
                "new_status": student.status,
                "message": "Status updated successfully"
            })
        except Student.DoesNotExist:
            return Response({"error": "Student not found"}, status=404)


from django.db import transaction

class EmployeeDeleteAPIView(APIView):
    def delete(self, request, id):
        try:
            with transaction.atomic():  # ??????? success ??? ??????? save
                # 1?? Booking ??????? delete
                UserBooking.objects.filter(user_id=id).delete()

                # 2?? Profile delete
                Profiles.objects.filter(user_id=id).delete()

                # 3?? ??????? Main User delete
                User.objects.filter(id=id).delete()

            return Response({
                "status": {"code": 200, "response": "success"},
                "message": "User deleted successfully"
            })

        except Exception as e:
            return Response({
                "status": {"code": 500, "response": "error"},
                "message": str(e)
            }, status=500)
import calendar
from datetime import datetime

class MonthlyAttendanceAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        month = int(request.query_params.get('month', datetime.now().month))
        year = int(request.query_params.get('year', datetime.now().year))
        student_id_param = request.query_params.get('student_id')

        num_days = calendar.monthrange(year, month)[1]
        month_name = calendar.month_name[month][:3]
        
        # ??????? ????????
        days_list = []
        for d in range(1, num_days + 1):
            days_list.append({
                "day_num": d,
                "display": f"{month_name} {d:02d}"
            })

        # ?????? ???????
        if student_id_param and student_id_param != "all":
            students = Student.objects.filter(id=student_id_param)
        else:
            students = Student.objects.all()

        # ???? ????????? ??????? ????????????
        attendance_records = Attendance.objects.filter(date__month=month, date__year=year)

        report_data = []
        for student in students:
            student_att = {}
            total_n_p = 0  # Normal Present
            total_n_a = 0  # Normal Absent
            total_s_p = 0  # Special Present
            total_s_a = 0  # Special Absent
            
            for day_obj in days_list:
                d = day_obj["day_num"]
                n_rec = attendance_records.filter(student_id=student.id, date__day=d, session_type=1).first()
                s_rec = attendance_records.filter(student_id=student.id, date__day=d, session_type=2).first()
                
                n_status = "P" if n_rec and n_rec.status == "Present" else ("A" if n_rec else "-")
                s_status = "P" if s_rec and s_rec.status == "Present" else ("A" if s_rec else "-")
                
                student_att[f"day_{d}_n"] = n_status
                student_att[f"day_{d}_s"] = s_status
                
                # ????????
                if n_status == "P": total_n_p += 1
                elif n_status == "A": total_n_a += 1
                
                if s_status == "P": total_s_p += 1
                elif s_status == "A": total_s_a += 1

            report_data.append({
                "name": student.studentName,
                "attendance": student_att,
                "total_n_p": total_n_p,
                "total_n_a": total_n_a,
                "total_s_p": total_s_p,
                "total_s_a": total_s_a,
            })

        return Response({
            "days": days_list,
            "report": report_data
        })
class AttendanceAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request):
        try:
            # Query Params ????? ???? ??????? ??????? ???????
            query_date = request.query_params.get('date', date.today().isoformat())
            session_type = request.query_params.get('session_type') # 1: Normal, 2: Special

            attendances = Attendance.objects.filter(date=query_date).order_by('-created_at')
            
            if session_type:
                attendances = attendances.filter(session_type=session_type)

            attendance_list = []
            for index, att in enumerate(attendances, 1):
                attendance_list.append({
                    'row': index,
                    'id': att.id,
                    'studentId': att.student.id,
                    'studentName': att.student.studentName,
                    'status': att.status, # Present / Absent
                    'session_type': att.session_type,
                    'date': att.date,
                })

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "data": attendance_list
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": str(e),
            })

    def post(self, request):
        data = request.data
        try:
            student_id = data.get('studentId')
            att_date = data.get('date', date.today().isoformat())
            session = data.get('session_type') # 1 or 2
            att_status = data.get('status') # Present or Absent

            # ??????? ??? ??????, ??? ????????? ???????????? ?????????? ???? ????????????
            attendance_obj = Attendance.objects.filter(
                student_id=student_id, 
                date=att_date, 
                session_type=session
            ).first()

            if attendance_obj:
                # ????????? ?????? Update ???????
                attendance_obj.status = att_status
                # ?????? ????? ????? ????? ??????????????: attendance_obj.user = request.user
                attendance_obj.save()
                message = "Attendance updated successfully"
            else:
                # ????????????? ???????? ????????????
                attendance_obj = Attendance.objects.create(
                    student_id=student_id,
                    date=att_date,
                    session_type=session,
                    status=att_status,
                    # user=request.user # Login ????? ?????????
                )
                message = "Attendance marked successfully"

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": message,
                "data": {
                    "id": attendance_obj.id,
                    "studentName": attendance_obj.student.studentName,
                    "status": attendance_obj.status
                }
            })

        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Error: {str(e)}"
            })
     

class LoanAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                company = Product.objects.get(id=id)

                try:
                    fl = company.sfile.url if company.sfile else None
                except ValueError:
                    fl = None 
                data = {
                    'id': company.id,
                    'name': company.name,
                    'code': company.code,

                    'description': company.description,
                    'specification':company.specification,
                    'sfile': fl,
                    'status': company.status

                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                activeloan = []

                loa = Loan.objects.filter(loan_status='Active')


                for i in loa:


                    clients=Client.objects.get(id=i.client_id)


                    activeloan.append({
                        'loan_id' : i.id,
                        'name' : clients.client_name,
                        'phone' : clients.phone
                    })

                index = 0
                companies = []



                

                loan = Loan.objects.all()

                for company in loan:
                    index += 1





                    client=Client.objects.get(id=company.client_id)

                    collectedamount = Collection.objects.filter(loan_id=company.id).aggregate(
                        total=Sum('collectedamonut')
                    )['total'] or 0

                    companies.append({
                        'row': index,
                        'id': company.id,
                        'loan_id':'L00'+str(company.id),
                        'paid': collectedamount,
                        'client_name' : client.client_name,
                        'client_phone': client.phone,
                        'loan_amount': company.loan_amount,
                        'loan_tenure_months': company.loan_tenure_months,

                        'collection_type': company.collection_type,
                        'collection_day': company.collection_day,
                        'loan_status': company.loan_status,

                    })


                


                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies,
                    "activeloan" : activeloan
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

    def post(self, request):
        data = request.data

        try:
            rate  = 0
            company = Loan.objects.create(

               




                client_id=data["clientId"],
                loan_amount=data["loanAmount"],
                loan_date=data["loanDate"], # ??? EMI End Date
                interest_rate=rate,
                loan_tenure_months=data["loanTenure"],
                emi_start_date=data["emiStartDate"],
                # ?????????? ??????? ?????: 
                # ??????? 'collectionType' ???????????? ???????, ??? ???????? ??????? ???????????
                collection_type=data.get("collectionType", "Daily"), 
                collection_day=data["avgRate"],
                loan_status=data["loanStatus"],
                remarks=data.get("remarks", "")






                # created_by=request.user
            )
            company.save()

            # from twilio.rest import Client as TwilioClient

            # client = TwilioClient(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)

            # recipient_number = '+918220432097'
            # message_body = "Hi, This is a Django test message!"

            # message = client.messages.create(
            #     to=recipient_number,
            #     messaging_service_sid=settings.TWILIO_MESSAGING_SERVICE_SID,
            #     body=message_body
            # )



            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Loan created successfully",
               
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })





    # def put(self, request, id):
    #     data = request.data

    #     try:

    #         ve =data.get("sfile")

    #         company = Product.objects.get(id=id)
    #         company.name = data.get("name", company.name)
    #         company.code = data.get("code", company.code)

    #         company.description = data.get("description", company.description)
    #         company.specification = data.get("specification", company.specification)
    #         company.sfile = data.get("sfile", company.sfile) 
    #         company.status = data.get("status", company.status)
    #         company.save()

    #         return Response({
    #             "status": {"code": status.HTTP_200_OK, "response": "success"},
    #             "error": None,
    #             "message": "Product updated successfully"
    #         })
    #     except ObjectDoesNotExist:
    #         return Response({
    #             "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
    #             "error": True,
    #             "message": "No data found"
    #         })
    #     except Exception as e:
    #         print(e)
    #         return Response({
    #             "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
    #             "error": True,
    #             "message": "Something went wrong"
    #         })

   


    # def delete(self, request, id):
    #     if id is not None:
    #         try:
    #             product_id_str = str(id)
    #             is_used = Enquiry.objects.filter(product__contains=[product_id_str]).exists()

    #             if is_used:
    #                 return Response({
    #                     "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
    #                     "error": "Product is used in enquiry",
    #                     "message": "Cannot delete product. It's used in one or more enquiries."
    #                 })

    #             # If not used, delete the product
    #             product = Product.objects.get(id=id)
    #             product.delete()

    #             return Response({
    #                 "status": {"code": status.HTTP_200_OK, "response": "success"},
    #                 "error": None,
    #                 "message": "Product deleted successfully"
    #             })

    #         except Product.DoesNotExist:
    #             return Response({
    #                 "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
    #                 "error": None,
    #                 "message": "No product found"
    #             })
            


class DashboardAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:

                dogo = []
                collection = Collection.objects.filter(loan_id=id)

                for m in collection:


                    dogo.append({
                        'id' : m.id,
                        'collectedamonut' : m.collectedamonut,
                        'method' : m.method,
                        'loan_id' : m.loan_id,
                        'date' : m.created_at
                    

                    })

                collectedamount = Collection.objects.filter(loan_id=id).aggregate(
                        total=Sum('collectedamonut')
                    )['total'] or 0

                loa = Loan.objects.get(id=id)

                cli = Client.objects.get(id=loa.client_id)
                data = {
                'client_name' : cli.client_name,
                'phone' : cli.phone,
                'loan_amount' : loa.loan_amount,
                'tenure' : loa.loan_tenure_months,
                'loan_status' : loa.loan_status,
                'paid' : collectedamount
                 }
               

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": dogo,
                    "datas" : data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                index = 0
                companies = []

                from django.utils import timezone # ????? ???? ???? ????? ???????
                

                active = Loan.objects.filter(loan_status='Active').count()
                inactive = Loan.objects.filter(loan_status='Closed').count()
                total_disbursed = Loan.objects.aggregate(Sum('loan_amount'))['loan_amount__sum'] or 0

                total_collected = Collection.objects.aggregate(Sum('collectedamonut'))['collectedamonut__sum'] or 0

                total_outstanding = float(total_disbursed) - float(total_collected)

                expected_daily = Loan.objects.filter(loan_status='Active').aggregate(Sum('collection_day'))['collection_day__sum'] or 0

              

                

                today = timezone.now().date()
                actual_daily = Collection.objects.filter(created_at__date=today).aggregate(Sum('collectedamonut'))['collectedamonut__sum'] or 0

                datas = {
                    'active' : active,
                    'inactive' : inactive,
                    'total_disbursed': total_disbursed,
                    'total_collected': total_collected,
                    'total_outstanding': total_outstanding,
                    'expected_daily': expected_daily, # ??????
                    'actual_daily': actual_daily      # ??????
                }


                print(datas,'fdddgdgfdgdfgdfgfdgfdgfd')
                

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": datas
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
            
from django.db.models import Sum
from django.utils import timezone
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Loan, Collection

class MonthlyReportAPIView(APIView):
    def get(self, request):
        # Front-end ???????? start_date ??????? end_date ?????
        start_date = request.query_params.get('start_date')
        end_date = request.query_params.get('end_date')

        # ???? ???????? ??????? ????? ??? ?????? ???????????? ????????
        if not start_date or not end_date:
            today = timezone.now().date()
            start_date = today
            end_date = today

        try:
            # 1. ??????????? ??? ??????????? ??????????? ????? ????
            disbursed = Loan.objects.filter(
                created_at__date__range=[start_date, end_date]
            ).aggregate(Sum('loan_amount'))['loan_amount__sum'] or 0

            # 2. ??????????? ??? ??????????? ?????? ??????? ????
            collected = Collection.objects.filter(
                created_at__date__range=[start_date, end_date]
            ).aggregate(Sum('collectedamonut'))['collectedamonut__sum'] or 0

            # 3. ????? ??????? ?????????
            new_loans_count = Loan.objects.filter(
                created_at__date__range=[start_date, end_date]
            ).count()

            return Response({
                "status": "success",
                "data": {
                    "total_disbursed": disbursed,
                    "total_collected": collected,
                    "net_flow": float(collected) - float(disbursed),
                    "new_loans_count": new_loans_count,
                    "period": f"{start_date} to {end_date}"
                }
            }, status=status.HTTP_200_OK)

        except Exception as e:
            return Response({"status": "error", "message": str(e)}, status=status.HTTP_400_BAD_REQUEST)

class CollectionAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:

                dogo = []
                collection = Collection.objects.filter(loan_id=id)

                for m in collection:


                    dogo.append({
                        'id' : m.id,
                        'collectedamonut' : m.collectedamonut,
                        'method' : m.method,
                        'loan_id' : m.loan_id,
                        'date' : m.created_at
                    

                    })

                collectedamount = Collection.objects.filter(loan_id=id).aggregate(
                        total=Sum('collectedamonut')
                    )['total'] or 0

                loa = Loan.objects.get(id=id)

                cli = Client.objects.get(id=loa.client_id)
                data = {
                'client_name' : cli.client_name,
                'phone' : cli.phone,
                'loan_amount' : loa.loan_amount,
                'tenure' : loa.loan_tenure_months,
                'loan_status' : loa.loan_status,
                'paid' : collectedamount
                 }
               

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": dogo,
                    "datas" : data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                index = 0
                companies = []


                

                loan = Loan.objects.all()

                for company in loan:
                    index += 1


                    client=Client.objects.get(id=company.client_id)


                    companies.append({
                        'row': index,
                        'id': company.id,
                        'loan_id':'L00'+str(company.id),



                        'client_name' : client.client_name,
                        'loan_amount': company.loan_amount,
                        'loan_tenure_months': company.loan_tenure_months,

                        'collection_type': company.collection_type,
                        'collection_day': company.collection_day,
                        'loan_status': company.loan_status,

                    })


                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

    def post(self, request):
        data = request.data

        try:
            loan_id = data["loanId"]
            amount_collected = data["amountCollected"]
            payment_mode = data["paymentMode"]
            remarks = data.get("remarks", "")

            # ? Create a new collection entry
            collection = Collection.objects.create(
                loan_id=loan_id,
                collectedamonut=amount_collected,
                method=payment_mode,
                remarks=remarks,
                # created_by=request.user  # uncomment if you have user tracking
            )

            # ? Calculate total collected so far
            collected_total = Collection.objects.filter(loan_id=loan_id).aggregate(
                total=Sum('collectedamonut')
            )['total'] or 0

            # ? Get the loan record
            loan = Loan.objects.get(id=loan_id)

            # ? Check if the loan is fully paid
            if loan.loan_amount <= collected_total:  # use <= for safety
                loan.loan_status = "Closed"
                loan.save()



            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Loan created successfully"
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })


            


class GetclientAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:
                company = Client.objects.filter(id=id)
                data = {
                    'id': company.id,
                    'vendorname': company.vendorname,
                    'phone': company.phone,
                    'email': company.email,
                    'address': company.address
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:



                index = 0
                companies = []

                for company in Client.objects.all():
                    index += 1

                    companies.append({
                        'row': index,
                        'id': company.id,
                        'client': company.client_name,
                        'phone' :company.phone


                    })



                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

class OldloanAPIView(APIView):
    # permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            try:

                dogo = []
                collection = Loan.objects.filter(client_id=id)

                for m in collection:


                    dogo.append({
                        'tenure' : m.loan_tenure_months,
                        'loan_amount' : m.loan_amount,
                        'loan_id' : m.id,
                        'emisdate' : m.emi_start_date,
                        'emildate' : m.loan_date,
                        'loan_status' : m.loan_status
                    

                    })

             
               

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": dogo,
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })
        else:
            try:

                index = 0
                companies = []


                

                loan = Loan.objects.all()

                for company in loan:
                    index += 1


                    client=Client.objects.get(id=company.client_id)


                    companies.append({
                        'row': index,
                        'id': company.id,
                        'loan_id':'L00'+str(company.id),



                        'client_name' : client.client_name,
                        'loan_amount': company.loan_amount,
                        'loan_tenure_months': company.loan_tenure_months,

                        'collection_type': company.collection_type,
                        'collection_day': company.collection_day,
                        'loan_status': company.loan_status,

                    })


                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": companies
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })


class FpAPIView(APIView):

    

    def post(self, request):
        data = request.data

        try:
            
            params = data.get('params', {})

            # Now retrieve 'email' and 'password' from the 'params' dictionary
            email = params.get('email')  # Access the 'email' field
            password = params.get('password')  # Access the 'password' field


            # Hash the password
            hashed_password = make_password(password)

            man = User.objects.get(email=email)

            man.password = hashed_password

            man.save()



            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "Password reset successfully"
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })

class FetchsubcategoryAPIView(APIView):
    def get(self, request, id):
        company = Subcategory.objects.filter(category_id=id)

        data = []

        for i in company:
            data.append({
                'name': i.name,
                'id': i.id
            })

        return Response({
            "status": {"code": status.HTTP_200_OK, "response": "success"},
            "error": None,
            "data": data
        })

class NotificationAPIView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, id=None):
        if id is not None:
            # Fetch a specific vendor by ID
            try:
                company = Vendor.objects.get(id=id)
                data = {
                    'id': company.id,
                    'vendorname': company.vendorname,
                    'phone': company.phone,
                    
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No data found",
                })

        else:
            # Return all notifications of type 'newuser' or 'paymentuser'
            # else:
            from django.utils.timesince import timesince
            from django.utils.timezone import now

            try:
                index = 0
                note = []
                op = request.user.id

                profile = Profiles.objects.get(user_id=op)

                if profile.role == 1:
                    notifications = Notification.objects.filter(
                        type__in=["newuser", "paymentuser"]
                    ).order_by("-created_at")

                    for n in notifications:
                        index += 1
                        try:
                            username = n.user.username if n.user else "Unknown"
                        except User.DoesNotExist:
                            username = "Unknown"

                        if n.type == "newuser":
                            message = f"New Company Registered: {username}"
                        elif n.type == "paymentuser":
                            message = f"{username} made a payment"
                        else:
                            message = "Unknown notification type"

                        note.append({
                            'row': index,
                            'id': n.id,
                            'type': n.type,
                            'message': message,
                            'created_at': n.created_at,
                            'time_ago': timesince(n.created_at, now()) + " ago", 

                        })

                    return Response({
                        "status": {"code": status.HTTP_200_OK, "response": "success"},
                        "error": None,
                        "data": note,
                        "count": len(note), 
                    })

                else:
                    # ? Non-admin user — return permission denied
                    return Response({
                        "status": {"code": status.HTTP_403_FORBIDDEN, "response": "forbidden"},
                        "error": True,
                        "message": "You do not have permission to view notifications.",
                        "data": []
                    })

            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })

    def delete(self, request, id=None):
        try:
            if id is not None:
                # Delete a specific notification
                notification = Notification.objects.get(id=id)
                notification.delete()
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Notification deleted successfully"
                })
            else:
                # Delete all notifications
                op = request.user.id

                Notification.objects.filter(user_id=op).delete()
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "All notifications deleted successfully"
                })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "Notification not found"
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "failed"},
                "error": True,
                "message": str(e)
            })


    

class ProductactivestatusupdateAPIView(APIView):
    
    def put(self, request, id):
        

        try:
            


            ven = Product.objects.get(id=id)

            if ven.status == 1:
                ven.status = 2
                ven.save()

            else:
                ven.status = 1
                ven.save()
            

           

            



           
    
            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Quote accepted successfully"
            })
        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {e}"
            })


