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,MenuItem, MealTime,WiFiConfig, Notification,Booking, Client, Loan, Collection, Student, Fees, FeesHistory
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.db.models import Sum, Count
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")  # Allow either username or email field
        password = data["password"]





        # Basic email validation
        if re.match(r"[^@]+@[^@]+\.[^@]+", username_or_email):
            # It's an email address, fetch the user by email
            try:
                user = User.objects.get(email=username_or_email)
            except User.DoesNotExist:
                user = None
        else:
            # It's a username, fetch the user by username
            user = authenticate(request, username=username_or_email, password=password)

        # Authenticate the user
        if user is not None and user.check_password(password):
            login(request, user)
            token = RefreshToken.for_user(user)

          

            
            profile = Profiles.objects.get(user_id=user.id)

     
            profile_photo =  request.build_absolute_uri(profile.profiles.url) if profile.profiles else None


                

                

            companyname = "loop"
            phone = profile.phone
            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,
                }
            })
        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)



# 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": True,
#             "data": {
#                 "username": user.username,
#                 "email": user.email,
#                 "role": profile.role.id,
#                 "profile": profile.profiles.url,
#             }
#         })
    

def send_otp_email(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}")
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}")

        
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('params', {}).get('email', None)
            print('Received email:', email)

            # ✅ Step 1: Check if email exists in registered users
            if not User.objects.filter(email=email).exists():
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "Email not found"},
                    "error": True,
                    "message": "Email not registered"
                })

            # ✅ Step 2: Create OTP record and send OTP
            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 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 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,
                    'role': student.role,

                    '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__in=[2, 3,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,
                        'role': student.role,

                        '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
        # ஆப்பில் இருந்து "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')


            # 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=role,
                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')
                role = data.get('role')

                mm = Profiles.objects.get(user_id=id)
                sd = User.objects.get(id=id)

                mm.name = username
                mm.email = email
                mm.phone = phone
                mm.role = role
                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 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}"
            })


from rest_framework.permissions import IsAuthenticated, AllowAny
from django.contrib.auth import get_user_model
User = get_user_model()


from django.utils import timezone
from datetime import datetime



VALID_MEAL_TYPES = {'breakfast', 'lunch', 'dinner', 'tea_time'}


def _parse_hhmm(value):
    if not value:
        return None
    try:
        return datetime.strptime(value, "%H:%M").time()
    except (ValueError, TypeError):
        return None


def _validate_meal_time(meal_type, from_raw, to_raw):
    if not meal_type:
        return None
    if not from_raw or not to_raw:
        return "Both From time and To time are required when a meal type is selected."
    from_t = _parse_hhmm(from_raw)
    to_t   = _parse_hhmm(to_raw)
    if from_t is None or to_t is None:
        return "Time must be in HH:MM format (e.g. 07:30)."
    if to_t <= from_t:
        return "To time must be later than From time."
    return None


def _upsert_meal_time(user, meal_type, from_raw, to_raw):
    from_t = _parse_hhmm(from_raw)
    to_t   = _parse_hhmm(to_raw)
    meal_time, _ = MealTime.objects.update_or_create(
        created_by=user,
        meal_type=meal_type,
        defaults={"from_time": from_t, "to_time": to_t},
    )
    return meal_time


def _get_meal_time_for_user(user_id, meal_type):
    """Get from_time/to_time for a meal_type from MealTime table."""
    try:
        mt = MealTime.objects.get(created_by_id=user_id, meal_type=meal_type)
        return {
            'from_time': mt.from_time.strftime('%H:%M'),
            'to_time'  : mt.to_time.strftime('%H:%M'),
        }
    except MealTime.DoesNotExist:
        return {'from_time': None, 'to_time': None}

import io
from PIL import Image, ImageDraw, ImageFont
from rest_framework.response import Response
# ... உங்க மத்த இம்போர்ட்டுகள் ...

def generate_tamil_bitmap(text):
    """
    தமிழ் டெக்ஸ்ட்டை 8 பிக்சல் உயரமுள்ள பிளாக் & ஒயிட் பிட்மேப் பைட்டுகளாக மாற்றுமொரு சூப்பர் ஃபங்க்ஷன்!
    """
    if not text:
        return []
        
    # 1. ஒரு தற்காலிக இமேஜ் கிரியேட் பண்ணி டெக்ஸ்ட்டோட அகலத்தை (Width) கண்டுபிடிக்கிறோம்
    # சிஸ்டம்ல தமிழ் ஃபான்ட் (Arial / Ubuntu / FreeSans) இருக்கிறதா எனப் பார்க்கிறோம். 
    # லினக்ஸ் சர்வர்னா 'FreeSans.ttf' அல்லது உங்ககிட்ட இருக்கிற ஏதாவது ஒரு தமிழ் ttf ஃபான்ட் பாத் கொடுங்க Thala.
    try:
        font = ImageFont.truetype("Arial.ttf", 8) # Height 8 பிக்சலுக்கு ஏத்த மாதிரி Font size 8
    except IOError:
        font = ImageFont.load_default()

    # டெக்ஸ்ட் நீளத்தை கணக்கிட ஒரு சின்ன கேன்வாஸ்
    img_test = Image.new('1', (500, 8), 0)
    draw_test = ImageDraw.Draw(img_test)
    
    # Pillow புது வெர்ஷன்களில் textlength() யூஸ் பண்ணலாம்
    try:
        text_width = int(draw_test.textlength(text, font=font)) + 4
    except AttributeError:
        # பழைய வெர்ஷன்களுக்கு textsize
        text_width = draw_test.textsize(text, font=font)[0] + 4
        
    if text_width < 32: 
        text_width = 32 # குறைந்தபட்சம் ஒரு P10 போர்டு வித்

    # 2. உண்மையான பிளாக் அண்ட் ஒயிட் இமேஜை வரைகிறோம் (1-bit pixels, black background)
    image = Image.new('1', (text_width, 8), 0)
    draw = ImageDraw.Draw(image)
    draw.text((0, 0), text, font=font, fill=1) # வெள்ளையாக டெக்ஸ்ட் எழுதப்படும் (1 = LED ON)

    # 3. P10 கியூப் லைப்ரரிக்கு ஏத்த மாதிரி வெர்டிகல் பைட் மேப்பிங் (Vertical Byte Encoding) பண்றோம்
    # 8 பிக்சல் உயரம் என்பதால், ஒவ்வொரு காலமும் (Column) ஒரு பைட் (1 பைட் = 8 பிட்)
    bitmap_bytes = []
    for x in range(text_width):
        byte_val = 0
        for y in range(8):
            pixel = image.getpixel((x, y))
            if pixel:  # பிக்சல் ஆன்-ல இருந்தா பிட்டை செட் பண்ணு
                byte_val |= (1 << y)
        bitmap_bytes.append(byte_val)

    return {
        "width": text_width,
        "height": 8,
        "bytes": bitmap_bytes
    }
# ─────────────────────────────────────────────────────────────────
# MENU ITEM API VIEW
# ─────────────────────────────────────────────────────────────────
class MenuItemAPIView(APIView):

    def get_permissions(self):
        if self.request.method == 'GET':
            return [AllowAny()]
        return [IsAuthenticated()]

    def get(self, request, id=None):
        # ── Single item by ID ──
        if id is not None:
            try:
                item    = MenuItem.objects.get(id=id)
                user_id = item.created_by_id
                times   = MealTime.objects.get(created_by_id=user_id,meal_type=item.meal_type)
                return Response({
                    "status": {"code": 200, "response": "success"},
                    "data": {
                        'id'           : item.id,
                        'industry_type': item.industry_type,
                        'name'         : item.name,
                        'price'        : str(item.price) if item.price is not None else None,
                        'meal_type'    : item.meal_type,
                        'is_available' : item.is_available,
                        'from_time'    : times.from_time,
                        'to_time'      : times.to_time,
                    }
                }, status=200)
            except MenuItem.DoesNotExist:
                return Response({
                    "status": {"code": 404, "response": "failed"},
                    "message": "Menu item not found"
                }, status=404)

        # ── List / filter ──
        # ── List / filter ──
        try:
            meal_type     = request.query_params.get('meal_type')
            industry_type = request.query_params.get('industry_type')
            is_esp32      = request.user.is_anonymous

            if is_esp32:
                board_name = request.query_params.get('board_name')
                if not board_name:
                    return Response({
                        "status": {"code": 400, "response": "failed"},
                        "message": "board_name required for ESP32"
                    }, status=400)
                try:
                    target_user = Profiles.objects.get(servicename=board_name)
                    user_id     = target_user.user_id
                except Profiles.DoesNotExist:
                    return Response({
                        "status": {"code": 404, "response": "failed"},
                        "message": f"No user found with board_name: {board_name}"
                    }, status=404)
            else:
                user_id = request.user.id

            items = MenuItem.objects.filter(created_by_id=user_id)

            if is_esp32:
                items = items.filter(is_available=True)

            if industry_type:
                items = items.filter(industry_type=industry_type)

            if meal_type:
                items = items.filter(meal_type=meal_type)

            items = items.order_by('name')

            item_list = []
            for index, item in enumerate(items, 1):
                user_id = item.created_by_id
                
                try:
                    # MealTime table la irunthu required matching row edukurom
                    times = MealTime.objects.get(created_by_id=user_id, meal_type=item.meal_type)
                    # Frontend safe format key response convert panrom ('13:45' format)
                    from_time_str = times.from_time.strftime('%H:%M') if times.from_time else None
                    to_time_str   = times.to_time.strftime('%H:%M') if times.to_time else None
                except MealTime.DoesNotExist:
                    # Oruவேளை matching data table la illana backend response crash aagama safe check handler
                    from_time_str = None
                    to_time_str   = None

                item_list.append({
                    'row'          : index,
                    'id'           : item.id,
                    'industry_type': item.industry_type,
                    'name'         : item.name,
                    'price'        : str(item.price) if item.price is not None else None,
                    'meal_type'    : item.meal_type,
                    'is_available' : item.is_available,
                    'from_time'    : from_time_str,  # Clean template strings sent to UI
                    'to_time'      : to_time_str,
                })

            print(item_list,'dsdsdsdsdsdsd')

            return Response({
                "status": {"code": 200, "response": "success"},
                "data"  : item_list,
            }, status=200)

        except Exception as e:
            return Response({"error": str(e)}, status=400)
    def post(self, request):
        data = request.data
        try:
            industry  = data.get('industry_type', 'other')
            raw_price = data.get('price')
            price     = raw_price if raw_price not in (None, '') else None
            meal_type = data.get('meal_type') or None

            if meal_type and meal_type not in VALID_MEAL_TYPES:
                return Response({"message": "Invalid meal_type."}, status=400)

            from_raw = data.get('from_time')
            to_raw   = data.get('to_time')

            error = _validate_meal_time(meal_type, from_raw, to_raw)
            if error:
                return Response({"message": error}, status=400)

            item = MenuItem.objects.create(
                industry_type = industry,
                name          = data.get('name'),
                price         = price,
                created_by    = request.user,
                meal_type     = meal_type,
                is_available  = bool(data.get('is_available', True)),
            )

            if meal_type:
                _upsert_meal_time(request.user, meal_type, from_raw, to_raw)

            return Response({
                "message": "Menu item added successfully!",
                "id"     : item.id
            }, status=201)
        except Exception as e:
            return Response({"message": str(e)}, status=400)

    def put(self, request, id):
        data = request.data
        try:
            item     = MenuItem.objects.get(id=id)
            industry = data.get('industry_type', item.industry_type)

            item.industry_type = industry
            item.name          = data.get('name', item.name)

            if 'price' in data:
                raw_price  = data.get('price')
                item.price = raw_price if raw_price not in (None, '') else None

            new_meal_type = data.get('meal_type', item.meal_type) or None
            if new_meal_type and new_meal_type not in VALID_MEAL_TYPES:
                return Response({"message": "Invalid meal_type."}, status=400)

            from_raw = data.get('from_time')
            to_raw   = data.get('to_time')

            meal_type_changed = 'meal_type' in data and new_meal_type != item.meal_type
            time_fields_sent  = ('from_time' in data) or ('to_time' in data)

            if new_meal_type and (meal_type_changed or time_fields_sent):
                error = _validate_meal_time(new_meal_type, from_raw, to_raw)
                if error:
                    return Response({"message": error}, status=400)
                _upsert_meal_time(request.user, new_meal_type, from_raw, to_raw)

            item.meal_type    = new_meal_type
            item.is_available = bool(data.get('is_available', item.is_available))
            item.save()

            return Response({
                "status" : "success",
                "message": "Menu item updated successfully!"
            }, status=200)
        except MenuItem.DoesNotExist:
            return Response({"message": "Menu item not found"}, status=404)
        except Exception as e:
            return Response({"message": str(e)}, status=400)

    def delete(self, request, id=None):
        if id is not None:
            try:
                item = MenuItem.objects.get(id=id)
                item.delete()
                return Response({
                    "status" : {"code": 200, "response": "success"},
                    "message": "Menu item deleted successfully"
                })
            except MenuItem.DoesNotExist:
                return Response({"message": "No menu item found"}, status=404)
        return Response({"message": "id required"}, status=400)


# ─────────────────────────────────────────────────────────────────
# BULK DELETE BY INDUSTRY TYPE
# ─────────────────────────────────────────────────────────────────
class BulkDeleteByIndustryView(APIView):
    permission_classes = [IsAuthenticated]

    def delete(self, request):
        industry_type = request.data.get('industry_type')
        if not industry_type:
            return Response({"message": "industry_type required"}, status=400)

        deleted_count, _ = MenuItem.objects.filter(
            created_by    = request.user,
            industry_type = industry_type,
        ).delete()

        return Response({
            "status" : "success",
            "message": f"Deleted {deleted_count} '{industry_type}' items.",
            "deleted": deleted_count,
        })


# ─────────────────────────────────────────────────────────────────
# MY INDUSTRY TYPE
# ─────────────────────────────────────────────────────────────────
class MyIndustryTypeView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        item = MenuItem.objects.filter(created_by=request.user).first()
        return Response({
            "status"       : "success",
            "industry_type": item.industry_type if item else None,
        })


# ─────────────────────────────────────────────────────────────────
# MEAL TIME API — GET/POST per user
# ─────────────────────────────────────────────────────────────────
class MealTimeAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        meal_times = MealTime.objects.filter(created_by=request.user)
        data = [{
            'id'       : mt.id,
            'meal_type': mt.meal_type,
            'from_time': mt.from_time.strftime('%H:%M'),
            'to_time'  : mt.to_time.strftime('%H:%M'),
        } for mt in meal_times]
        return Response({"status": "success", "data": data})

    def post(self, request):
        meal_type = request.data.get('meal_type')
        from_raw  = request.data.get('from_time')
        to_raw    = request.data.get('to_time')

        if not meal_type or meal_type not in VALID_MEAL_TYPES:
            return Response({"message": "Valid meal_type required"}, status=400)

        error = _validate_meal_time(meal_type, from_raw, to_raw)
        if error:
            return Response({"message": error}, status=400)

        _upsert_meal_time(request.user, meal_type, from_raw, to_raw)
        return Response({"status": "success", "message": "Meal time saved!"})

    


# ─────────────────────────────────────────────────────────────────
# BULK DELETE BY INDUSTRY TYPE
# DELETE /api/v1/menu-items/bulk-delete-by-industry/
# Body: { "industry_type": "hotel" }
# ─────────────────────────────────────────────────────────────────
class BulkDeleteMenuItemsByIndustryAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def delete(self, request):
        industry_type = request.data.get('industry_type')
        if not industry_type:
            return Response({"message": "industry_type required"}, status=400)

        deleted_count, _ = MenuItem.objects.filter(
            created_by   = request.user,
            industry_type= industry_type,
        ).delete()

        return Response({
            "status" : "success",
            "message": f"Deleted {deleted_count} '{industry_type}' items.",
            "deleted": deleted_count,
        })


# ─────────────────────────────────────────────────────────────────
# MY INDUSTRY TYPE
# GET /api/v1/menu-items/my-industry-type/
# Returns the industry_type of the logged-in user's first menu item
# ─────────────────────────────────────────────────────────────────
class FetchIndustryAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        item = MenuItem.objects.filter(created_by=request.user).first()
        if item:
            return Response({
                "status"       : "success",
                "industry_type": item.industry_type,
            })
        return Response({
            "status"       : "success",
            "industry_type": None,  # No items yet
        })
 

 
# ─────────────────────────────────────────────────────────────────
# WIFI CONFIG API VIEW
# ─────────────────────────────────────────────────────────────────
class WiFiConfigAPIView(APIView):

    def get_permissions(self):
        if self.request.method == 'GET':
            return [AllowAny()]  # ESP32 டோக்கன் இல்லாம ஹிட் பண்ண அனுமதி
        return [IsAuthenticated()]

    def get(self, request):
        try:
            # 1. 🤖 ESP32 போர்டு அனுப்பும் ஹார்ட்பீட் சிக்னல் (Anonymous)
            if request.user.is_anonymous:
                board_name = request.query_params.get('board_name')
                if not board_name:
                    return Response({"message": "board_name required"}, status=400)

                try:
                    # போர்டு பேரை வச்சு ப்ரொஃபைலை எடுக்கிறோம்
                    profile = Profiles.objects.get(servicename=board_name)
                    profile.last_seen = timezone.now()  # 👈 கரண்ட் டைமை அப்டேட் பண்றோம்
                    profile.save()
                    return Response({"status": "success", "message": "Board Heartbeat Updated"})
                except Profiles.DoesNotExist:
                    return Response({"message": f"No board found: {board_name}"}, status=404)

            # 2. 📱 கன்னியாகுமரி ஓனர் பார்க்கும் மொபைல் ஆப் (Authenticated User)
            else:
                try:
                    profile = Profiles.objects.get(user=request.user)
                    
                    is_connected = False
                    if profile.last_seen:
                        # கடைசியா சிக்னல் வந்து 2 நிமிஷத்துக்குள்ள இருந்தா CONNECTED!
                        diff = timezone.now() - profile.last_seen
                        if diff.total_seconds() < 120:
                            is_connected = True

                    return Response({
                        "data": {
                            "is_device_connected": is_connected,
                            "last_seen": profile.last_seen
                        }
                    })
                except Profiles.DoesNotExist:
                    return Response({"message": "Profile not found"}, status=404)

        except Exception as e:
            return Response({"message": str(e)}, status=500)

    def post(self, request):
        data = request.data
        try:
            ssid     = data.get('ssid',     '').strip()
            password = data.get('password', '').strip()

            if not ssid or not password:
                return Response({"message": "ssid and password required"}, status=400)

            existing = WiFiConfig.objects.filter(created_by=request.user).first()
            if existing:
                existing.ssid     = ssid
                existing.password = password
                existing.save()
                return Response({
                    "status" : {"code": 200, "response": "success"},
                    "message": "WiFi config updated!"
                }, status=200)

            WiFiConfig.objects.create(
                ssid       = ssid,
                password   = password,
                created_by = request.user,
            )
            return Response({
                "status" : {"code": 201, "response": "success"},
                "message": "WiFi config saved!"
            }, status=201)

        except Exception as e:
            return Response({"message": str(e)}, status=400)

    def patch(self, request):
        # ESP32 heartbeat via PATCH
        board_name = request.query_params.get('board_name')
        if not board_name:
            return Response({"message": "board_name required"}, status=400)

        try:
            target_user = Profiles.objects.get(servicename=board_name)
            config      = WiFiConfig.objects.get(created_by_id=target_user.user_id)
            config.last_seen = timezone.now()
            config.save()
            return Response({
                "status" : "success",
                "message": "Heartbeat acknowledged",
                "data"   : {
                    "ssid"    : config.ssid,
                    "password": config.password,
                }
            })
        except Profiles.DoesNotExist:
            return Response({"message": f"No user: {board_name}"}, status=404)
        except WiFiConfig.DoesNotExist:
            return Response({"message": "No WiFi config found"}, status=404)
        except Exception as e:
            return Response({"message": str(e)}, status=400)
    def delete(self, request):
        if not request.user.is_authenticated:
            return Response({"message": "Authentication required"}, status=401)
        try:
            config = WiFiConfig.objects.get(created_by=request.user)
            config.delete()
            return Response({
                "status": {"code": 200, "response": "success"},
                "message": "WiFi config deleted successfully"
            })
        except WiFiConfig.DoesNotExist:
            return Response({
                "status": {"code": 404, "response": "failed"},
                "message": "No config found"
            }, status=status.HTTP_404_NOT_FOUND)

  

        
import json
import base64
import time
from django.core.files.base import ContentFile
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Student
 
 
class StudentAPIView(APIView):
    # permission_classes = (IsAuthenticated,)
 
    def _handle_photo(self, request, data):
        """
        எல்லா device / country-லயும் photo handle பண்றோம்:
 
        Method 1 → request.FILES['photo']
                    Android native multipart
                    Web direct blob (India Netlify)
 
        Method 2 → data['photo_base64']
                    iOS Safari (Oman, எந்த country-லயும்)
                    FileReader base64 string
        """
 
        # Method 1: Normal file upload
        if 'photo' in request.FILES:
            return request.FILES['photo']
 
        # Method 2: Base64 string upload (iOS Safari fix)
        photo_base64 = data.get('photo_base64')
        photo_filename = data.get('photo_filename', f'photo_{int(time.time())}.jpg')
 
        if photo_base64:
            try:
                # "data:image/jpeg;base64,/9j/4AAQ..." → split பண்ணி data மட்டும் எடு
                if ',' in photo_base64:
                    photo_base64 = photo_base64.split(',')[1]
 
                # Extra whitespace / newline remove பண்ணு
                photo_base64 = photo_base64.strip()
 
                image_data = base64.b64decode(photo_base64)
                return ContentFile(image_data, name=photo_filename)
            except Exception as e:
                print(f"[Photo] Base64 decode error: {e}")
                return None
 
        return None
 
    # ------------------------------------------------------------------ GET --
    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,
                    'normal_fees': student.normal_fees,
                    'special_fees': student.special_fees,
                    'dateOfJoining': student.dateOfJoining,
                    'status': student.status,
                    '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 = Student.objects.all().order_by('-created_at')
                student_list = []
                for index, student in enumerate(students, 1):
                    student_list.append({
                        'row': index,
                        'id': student.id,
                        'studentName': student.studentName,
                        'parentName': student.parentName,
                        'mobilenumber': student.mobilenumber,
                        'classType': student.classType,
                        'status': student.status,
                        'age': student.age,
                        '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": student_list,
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })
 
    # ----------------------------------------------------------------- POST --
    def post(self, request):
        data = request.data
        photo = self._handle_photo(request, data)
 
        try:
            n_fees = float(data.get('normal_fees', 0) or 0)
            s_fees = float(data.get('special_fees', 0) or 0)
            total_fees = n_fees + s_fees
 
            frontend_class = data.get('classType', '[]')
            if isinstance(frontend_class, str):
                try:
                    frontend_class = json.loads(frontend_class)
                except Exception:
                    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'),
                address=data.get('address'),
                monthly_fees=total_fees,
                normal_fees=n_fees,
                special_fees=s_fees,
                classType=final_class_id,
                dateOfJoining=data.get('dateOfJoining'),
                photo=photo,
                status=1,
            )
 
            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "message": "Student created successfully",
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "message": str(e),
            })
 
    # ------------------------------------------------------------------ PUT --
    def put(self, request, id):
        data = request.data
        photo = self._handle_photo(request, data)
 
        try:
            student = Student.objects.get(id=id)
 
            # classType update
            class_data = data.get("classType")
            if class_data is not None:
                try:
                    student.classType = int(class_data)
                except (ValueError, TypeError):
                    pass
 
            # Fees update
            if "normal_fees" in data:
                student.normal_fees = data.get("normal_fees")
 
            if "special_fees" in data:
                student.special_fees = data.get("special_fees")
 
            # monthly_fees = normal + special auto calculate
            try:
                n = float(data.get("normal_fees") or student.normal_fees or 0)
                s = float(data.get("special_fees") or student.special_fees or 0)
                student.monthly_fees = n + s
            except Exception:
                pass
 
            # Basic fields
            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)
 
            if "status" in data:
                student.status = data.get("status")
 
            # Photo update
            if photo:
                student.photo = photo
 
            student.save()
 
            return Response({
                "status": {"code": 200, "response": "success"},
                "message": f"Student {student.studentName} updated successfully.",
            })
 
        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),
            })

    def delete(self, request, id):
        if id is not None:
            try:

                student = Student.objects.get(id=id)

                # 2. மற்ற டேபிள்களில் உள்ள தரவுகளை நீக்குகிறோம்
                # ஒருவேளை உங்கள் models-ல் ForeignKey(on_delete=models.CASCADE) இருந்தால், 
                # student.delete() செய்தாலே இவை அனைத்தும் தானாக நீங்கிவிடும். 
                # அப்படி இல்லையென்றால் கீழே உள்ளவாறு செய்யலாம்:

                Attendance.objects.filter(student_id=id).delete()
                Fees.objects.filter(student_id=id).delete()
                FeesHistory.objects.filter(student_id=id).delete()

                student.delete()
                

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Student and all related records deleted successfully"
                })

            except Product.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": None,
                    "message": "No student found"
                })


class BookingReportAPIView(APIView):
    def get(self, request):
        from_date = request.query_params.get('from_date')
        to_date = request.query_params.get('to_date')

        if not from_date or not to_date:
            return Response({"message": "Please provide both from_date and to_date"}, status=status.HTTP_400_BAD_REQUEST)

        # குறிப்பிட்ட தேதிக்குள் உள்ள புக்கிங்களை நெட் வாரியாக குரூப் செய்தல்
        report_data = Booking.objects.filter(
            booking_date__range=[from_date, to_date]
        ).values('net_selection').annotate(
            total_bookings=Count('id'),
            total_revenue=Sum('amount')
        ).order_by('-total_revenue')

        # ஒட்டுமொத்த டோட்டல் கணக்கிடுதல்
        overall_stats = Booking.objects.filter(
            booking_date__range=[from_date, to_date]
        ).aggregate(
            grand_total_bookings=Count('id'),
            grand_total_revenue=Sum('amount')
        )

        return Response({
            "status": "success",
            "date_range": {"from": from_date, "to": to_date},
            "detailed_report": report_data,
            "overall": overall_stats
        }, status=status.HTTP_200_OK)


class BookingAPIView(APIView):
    # permission_classes = (IsAuthenticated,)


    def get(self, request, id=None):
        if id is not None:
            try:
                booking = Booking.objects.get(id=id)
                data = {
                    'id': booking.id,
                    'customer_name': booking.customer_name,
                    'phone': booking.phone,
                    'email': booking.email,
                    'net_selection': booking.net_selection,
                    'booking_type': booking.booking_type, # இதையும் சேர்க்க வேண்டும்
                    'booking_date': booking.booking_date.strftime('%Y-%m-%d'),
                    'end_date': booking.end_date.strftime('%Y-%m-%d') if booking.end_date else None, # இதையும் சேர்க்க வேண்டும்
                    'start_time': booking.start_time,
                    'end_time': booking.end_time,
                    'amount': booking.amount,
                    'payment_status': booking.payment_status
                }
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "data": data
                })
            except Booking.DoesNotExist:
                return Response({"status": {"code": 404}, "message": "Booking not found"}, status=status.HTTP_404_NOT_FOUND)

        else:
            
            try:
                # 1. ஆப்பில் இருந்து வரும் தேதியைப் பெறுதல்
                target_date_str = request.query_params.get('date')
                
                if target_date_str:
                    target_date = datetime.strptime(target_date_str, '%Y-%m-%d').date()
                else:
                    target_date = timezone.now().date()

                # 2. பில்டர்: குறிப்பிட்ட தேதியில் உள்ளவை மற்றும் அதற்கு மேல் உள்ளவை (Upcoming)
                # __gte = Greater than or equal to
                bookings = Booking.objects.filter(booking_date__gte=target_date).order_by('booking_date', 'start_time')

                booking_list = []
                for index, b in enumerate(bookings, 1):
                    booking_list.append({
                        'row': index,
                        'id': b.id,
                        'customer_name': b.customer_name,
                        'phone': b.phone,
                        'email': b.email,
                        'net_selection': b.net_selection,
                        'booking_type': b.booking_type, # Day/Month விவரம்
                        'booking_date': b.booking_date.strftime('%Y-%m-%d'), 
                        'end_date': b.end_date.strftime('%Y-%m-%d') if b.end_date else None,
                        'start_time': b.start_time,
                        'end_time': b.end_time,
                        'amount': b.amount,
                        'payment_status': b.payment_status
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "data": booking_list
                })
            except Exception as e:
                return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
    from django.db.models import Q

    

    def post(self, request):
        data = request.data
        try:
            b_type = data.get('booking_type', 'Day')
            start_date = datetime.strptime(data.get('booking_date'), '%Y-%m-%d').date()
            raw_start = data.get('start_time')
            raw_end = data.get('end_time')
            net = data.get('net_selection')
            
            # முடிவுத் தேதியை முடிவு செய்தல்
            end_date = None
            if b_type == 'Month':
                end_date = datetime.strptime(data.get('end_date'), '%Y-%m-%d').date()
            else:
                end_date = start_date

            # 1. Conflict Check (ஒரே ஒரு குயரி மூலம் செக் செய்தல்)
            # இந்த லாஜிக் 'Day' மற்றும் 'Month' இரண்டிற்கும் வேலை செய்யும்
            overlap = Booking.objects.filter(
                net_selection=net,
                start_time__lt=raw_end,
                end_time__gt=raw_start
            ).filter(
                # தேதிகள் மோதல் இருக்கிறதா என்று பார்ப்பது
                Q(booking_date__range=(start_date, end_date)) | 
                Q(end_date__range=(start_date, end_date)) |
                Q(booking_date__lte=start_date, end_date__gte=end_date)
            ).exists()

            if overlap:
                return Response({
                    "message": "Slot already booked! Selected dates or times conflict with an existing booking."
                }, status=status.HTTP_409_CONFLICT)

            # 2. Save Booking (ஒரே ஒரு முறை மட்டும் கிரியேட் செய்தல்)
            booking = Booking.objects.create(
                customer_name=data.get('customer_name'),
                phone=data.get('phone'),
                email=data.get('email'),
                net_selection=net,
                booking_type=b_type,
                booking_date=start_date,
                end_date=end_date if b_type == 'Month' else None,
                start_time=raw_start,
                end_time=raw_end,
                amount=data.get('amount'),
                payment_status=data.get('payment_status')
            )

            return Response({
                "message": "Booking confirmed successfully!",
                "id": booking.id
            }, status=status.HTTP_201_CREATED)

        except Exception as e:
            return Response({"message": str(e)}, status=status.HTTP_400_BAD_REQUEST)
    
    # PUT: புக்கிங் விவரங்களை அப்டேட் செய்தல்
    def put(self, request, id):
        data = request.data
        try:
            booking = Booking.objects.get(id=id)
            
            # டேட்டாவைப் பெறுதல்
            b_type = data.get('booking_type', booking.booking_type)
            start_date_str = data.get('booking_date')
            start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date() if start_date_str else booking.booking_date
            
            raw_start = data.get('start_time', booking.start_time)
            raw_end = data.get('end_time', booking.end_time)
            net = data.get('net_selection', booking.net_selection)

            # End Date முடிவு செய்தல்
            if b_type == 'Month' and data.get('end_date'):
                end_date = datetime.strptime(data.get('end_date'), '%Y-%m-%d').date()
            elif b_type == 'Day':
                end_date = start_date
            else:
                end_date = booking.end_date

            # 1. Conflict Check (தன்னைத் தவிர மற்ற புக்கிங்களுடன் செக் செய்தல்)
            overlap = Booking.objects.filter(
                net_selection=net,
                start_time__lt=raw_end,
                end_time__gt=raw_start
            ).filter(
                Q(booking_date__range=(start_date, end_date)) | 
                Q(end_date__range=(start_date, end_date)) |
                Q(booking_date__lte=start_date, end_date__gte=end_date)
            ).exclude(id=id).exists() # 👈 மிக முக்கியம்: அதே புக்கிங்கைத் தவிர்

            if overlap:
                return Response({
                    "message": "Update failed! Slot conflicts with another booking."
                }, status=status.HTTP_409_CONFLICT)

            # 2. விவரங்களை அப்டேட் செய்தல்
            booking.customer_name = data.get('customer_name', booking.customer_name)
            booking.phone = data.get('phone', booking.phone)
            booking.email = data.get('email', booking.email)
            booking.net_selection = net
            booking.booking_type = b_type
            booking.booking_date = start_date
            booking.end_date = end_date if b_type == 'Month' else None
            booking.start_time = raw_start
            booking.end_time = raw_end
            booking.amount = data.get('amount', booking.amount)
            booking.payment_status = data.get('payment_status', booking.payment_status)
            
            booking.save()

            return Response({
                "status": "success",
                "message": "Booking updated successfully!"
            }, status=status.HTTP_200_OK)

        except Booking.DoesNotExist:
            return Response({"message": "Booking not found"}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({"message": str(e)}, status=status.HTTP_400_BAD_REQUEST)
    def delete(self, request, id):
        if id is not None:
            try:
                booking = Booking.objects.get(id=id)
                booking.delete()

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "message": "Booking slot deleted successfully"
                })

            except Booking.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "message": "No booking found"
                })


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)
                fee_record = Fees.objects.filter(student=student).first()

                # இந்த மாதம் இதுவரை செலுத்திய தொகை (History-லிருந்து)
                n_paid_this_month = float(FeesHistory.objects.filter(
                    student=student, fee_type='NORMAL',
                    payment_date__month=current_month, payment_date__year=current_year
                ).aggregate(total=DSum('amount_paid'))['total'] or 0)

                s_paid_this_month = float(FeesHistory.objects.filter(
                    student=student, fee_type='SPECIAL',
                    payment_date__month=current_month, payment_date__year=current_year
                ).aggregate(total=DSum('amount_paid'))['total'] or 0)

                # --- 1. Normal Fees கணக்கீடு ---
                n_fees = float(student.normal_fees or 0)
                if fee_record:
                    # லாஜிக்: இந்த மாதம் இன்னும் கட்டவில்லை மற்றும் பழைய பாக்கி மாத பீஸை விட குறைவாக இருந்தால் கூட்டு
                    if n_paid_this_month == 0 and float(fee_record.normal_balance) < n_fees:
                        n_balance = float(fee_record.normal_balance) + n_fees
                    else:
                        n_balance = float(fee_record.normal_balance)
                else:
                    n_balance = n_fees

                # --- 2. Special Fees கணக்கீடு ---
                s_fees = float(student.special_fees or 0)
                if fee_record:
                    # லாஜிக்: பழைய பாக்கி (20.000) + புதிய மாத பீஸ் (70.000) = 90.000
                    if s_paid_this_month == 0 and float(fee_record.special_balance) < s_fees:
                        s_balance = float(fee_record.special_balance) + s_fees
                    else:
                        s_balance = float(fee_record.special_balance)
                else:
                    s_balance = s_fees

                data = {
                    'studentName': student.studentName,
                    'classType': student.classType,
                    'normal_fees': n_fees,
                    'normal_paid': n_paid_this_month,
                    'normal_balance': n_balance,
                    'special_fees': s_fees,
                    'special_paid': s_paid_this_month,
                    'special_balance': s_balance,
                }
                return Response({"status": {"code": 200}, "data": data})

            except Student.DoesNotExist:
                return Response({"status": {"code": 404}, "message": "Student not found"})
        
        else:
            # லிஸ்ட் வியூ (Fees Management Screen-க்காக)
            students = Student.objects.filter(status=1)
            data_list = []
            
            for student in students:
                fee_record = Fees.objects.filter(student=student).first()
                
                # இந்த மாதம் இதுவரை பணம் கட்டியிருக்கிறாரா என்று பார்க்கிறோம்
                n_paid_this_month = float(FeesHistory.objects.filter(
                    student=student, fee_type='NORMAL',
                    payment_date__month=current_month, payment_date__year=current_year
                ).aggregate(total=DSum('amount_paid'))['total'] or 0)

                s_paid_this_month = float(FeesHistory.objects.filter(
                    student=student, fee_type='SPECIAL',
                    payment_date__month=current_month, payment_date__year=current_year
                ).aggregate(total=DSum('amount_paid'))['total'] or 0)

                # --- 1. Normal Class Balance கணக்கீடு ---
                n_fees = float(student.normal_fees or 0)
                if fee_record:
                    # இதுவரை இந்த மாதம் பணம் கட்டவில்லை என்றால்: பழைய பாக்கி + இந்த மாத பீஸ்
                    if n_paid_this_month == 0 and float(fee_record.normal_balance) < n_fees:
                        n_balance = float(fee_record.normal_balance) + n_fees
                    else:
                        n_balance = float(fee_record.normal_balance)
                else:
                    n_balance = n_fees

                # --- 2. Special Class Balance கணக்கீடு ---
                s_fees = float(student.special_fees or 0)
                if fee_record:
                    # லாஜிக்: இந்த மாதம் பணம் கட்டவில்லை என்றால் (70.000) + பழைய பாக்கி (20.000) = 90.000
                    if s_paid_this_month == 0 and float(fee_record.special_balance) < s_fees:
                        s_balance = float(fee_record.special_balance) + s_fees
                    else:
                        s_balance = float(fee_record.special_balance)
                else:
                    s_balance = s_fees

                data_list.append({
                    'id': student.id,
                    'photo': request.build_absolute_uri(student.photo.url) if student.photo else None,

                    'studentName': student.studentName,
                    'classType': student.classType,
                    'normal_fees': n_fees,
                    'normal_paid': n_paid_this_month,
                    'normal_balance': n_balance,
                    'special_fees': s_fees,
                    'special_paid': s_paid_this_month,
                    'special_balance': s_balance,
                })
            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_type = d.get('fee_type') # 'NORMAL' அல்லது 'SPECIAL'
            
            # 1. ஏற்கனவே ரெக்கார்டு இருந்தால் எடுக்கும், இல்லையென்றால் உருவாக்கும்
            fee, created = Fees.objects.get_or_create(student=student_obj)
            
            # 2. முதல் முறை உருவாக்கும்போது (Initial values)
            if created:
                fee.normal_fees = float(student_obj.normal_fees or 0)
                fee.special_fees = float(student_obj.special_fees or 0)
                fee.payment_date = datetime.now().date()

            # 3. எந்த வகை பீஸ் கட்டுகிறாரோ அந்த கணக்கில் மட்டும் அப்டேட் செய்யும்
            if fee_type == 'NORMAL':
                fee.normal_paid = float(fee.normal_paid or 0) + paid_now
                fee.normal_balance = new_balance
            elif fee_type == 'SPECIAL':
                fee.special_paid = float(fee.special_paid or 0) + paid_now
                fee.special_balance = new_balance
            
            fee.save()

            # 4. பேமெண்ட் ஹிஸ்டரியில் ஒரு பதிவை உருவாக்குதல்
            FeesHistory.objects.create(
                student=student_obj, 
                amount_paid=paid_now, 
                fee_type=fee_type,
                payment_date=datetime.now().date()
            )

            return Response({"status": {"code": 200}, "message": "Payment Recorded 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,
        #             # முக்கியமானது: ஆப்பில் ஃபில்டர் செய்ய இந்த fee_type அவசியம்
        #             'fee_type': h.fee_type if h.fee_type else "NORMAL" 
        #         })

        from dateutil.relativedelta import relativedelta
        try:
            # 1. மாணவர் தகவலை எடுக்கிறோம் (அவர் சேர்ந்த தேதிக்காக)
            student = Student.objects.get(id=student_id)
            join_date = student.created_at.date() # மாணவர் சேர்ந்த தேதி
            current_date = datetime.now().date() # இன்றைய தேதி

            # 2. மாணவரின் கட்டண வரலாற்றை எடுக்கிறோம்
            history_records = FeesHistory.objects.filter(student_id=student_id)
            
            # எளிதாகச் சரிபார்க்க, கட்டணம் செலுத்திய மாதங்களை ஒரு செட்-ஆக (Set) மாற்றுகிறோம்
            # Format: "MM-YYYY-TYPE" (e.g., "05-2026-NORMAL")
            paid_months = set()
            for h in history_records:
                key = f"{h.payment_date.strftime('%m-%Y')}-{h.fee_type}"
                paid_months.add(key)

            final_data = []
            
            # 3. சேர்ந்த தேதியிலிருந்து இன்று வரை ஒவ்வொரு மாதமாக லூப் செய்கிறோம்
            temp_date = join_date.replace(day=1) # சேர்ந்த மாதத்தின் முதல் தேதியிலிருந்து தொடங்குகிறது
            
            while temp_date <= current_date:
                month_year = temp_date.strftime('%m-%Y')
                
                # NORMAL மற்றும் SPECIAL இரண்டிற்கும் சரிபார்க்கிறோம்
                for f_type in ["NORMAL", "SPECIAL"]:
                    check_key = f"{month_year}-{f_type}"
                    
                    if check_key in paid_months:
                        # கட்டணம் செலுத்தியிருந்தால், அந்த விவரத்தைச் சேர்க்கிறோம்
                        record = history_records.get(
                            payment_date__month=temp_date.month, 
                            payment_date__year=temp_date.year,
                            fee_type=f_type
                        )
                        final_data.append({
                            'id': record.id,
                            'month_name': temp_date.strftime('%B %Y'),
                            'amount_paid': float(record.amount_paid),
                            'payment_date': record.payment_date.strftime('%d-%m-%Y'),
                            'fee_type': record.fee_type,
                            'status': 'PAID'
                        })
                   

                    else:
                        # id-க்கு பதிலாக ஒரு தனித்துவமான ஸ்ட்ரிங்
                        final_data.append({
                            'id': f"unpaid-{temp_date.strftime('%m-%Y')}-{f_type}", 
                            'month_name': temp_date.strftime('%B %Y'),
                            'amount_paid': 0,
                            'payment_date': None,
                            'fee_type': f_type,
                            'status': 'NOT_PAID'
                        })
                
                # அடுத்த மாதத்திற்குச் செல்கிறோம்
                temp_date += relativedelta(months=1)

            # லேட்டஸ்ட் விவரங்கள் முதலில் வர வரிசைப்படுத்துகிறோம்
            final_data.reverse()
            
            return Response({"status": {"code": 200}, "data": final_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)

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 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}"
            })


