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,MatchStream, Client, Student, Team, Player, Match
from django.core.exceptions import ObjectDoesNotExist
from rest_framework.exceptions import NotFound
from django.contrib.auth import authenticate, login
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import User
from django.utils import timezone as djtz
from django.utils import timezone
from datetime import date, datetime, timedelta
import requests
from django.utils import timezone
from django.http import HttpResponse
import base64
from rest_framework.parsers import MultiPartParser, FormParser
from django.db.models import Q
from rest_framework.generics import RetrieveAPIView, ListAPIView
from .serializers import UserSerializer
from rest_framework.permissions import IsAuthenticated
from datetime import datetime, time
import json
from django.core.mail import EmailMessage
from school.settings import BASE_DIR
import pdfkit
from django.core.exceptions import ObjectDoesNotExist
# import openai
import re
from django.conf import settings
import threading
# import pywhatkit
from django.core.mail import send_mail
from django.utils.crypto import get_random_string
from django.db.models import Sum




from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from django.core.exceptions import ObjectDoesNotExist
from rest_framework_simplejwt.tokens import RefreshToken
import re  # For basic email validation
# from twilio.rest import Client as TwilioClient # 💡 Maru Peyaridhal!
class LoginAPIView(APIView):
    def post(self, request):
        data = request.data
        username_or_email = data.get("username")
        password = data.get("password")

        if not username_or_email or not password:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "error"},
                "message": "Username and password are required"
            }, status=status.HTTP_400_BAD_REQUEST)

        # Basic email validation
        user = None
        if re.match(r"[^@]+@[^@]+\.[^@]+", username_or_email):
            try:
                user = User.objects.get(email=username_or_email)
            except User.DoesNotExist:
                user = None
        else:
            user = authenticate(request, username=username_or_email, password=password)

        # Authenticate and Status Check
        if user is not None and user.check_password(password):
            try:
                profile = Profiles.objects.get(user_id=user.id)
                
                # --- இங்கேதான் Inactive Status செக் செய்கிறோம் ---
                if profile.status == 2:
                    return Response({
                        "status": {"code": status.HTTP_403_FORBIDDEN, "response": "error"},
                        "error": "Account Inactive",
                        "message": "You are inactive by Admin. Please contact Admin.",
                        "data": None
                    }, status=status.HTTP_403_FORBIDDEN)
                # -----------------------------------------------

                login(request, user)
                token = RefreshToken.for_user(user)
                
                profile_photo = request.build_absolute_uri(profile.profiles.url) if profile.profiles else None
                companyname = "loop"
                
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Login success",
                    "data": {
                        "name": user.username,
                        "id": user.id,
                        "username": user.username,
                        "email": user.email,
                        "isSuper": user.is_superuser,
                        "refresh": str(token),
                        "token": str(token.access_token),
                        "profile": profile_photo,
                        "companyname": companyname,
                        "phone": profile.phone,
                        "role": profile.role,
                    }
                })
            except Profiles.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "error"},
                    "message": "User profile not found"
                }, status=status.HTTP_404_NOT_FOUND)
        else:
            return Response({
                "status": {"code": status.HTTP_401_UNAUTHORIZED, "response": "error"},
                "error": "Authentication failed",
                "message": "Invalid username or password",
                "data": None
            }, status=status.HTTP_401_UNAUTHORIZED)

from datetime import datetime

from rest_framework.views import APIView
from rest_framework.response import Response

from .models import Match, LiveScore  # adjust import path to match your project


# ── Module-level helpers ──────────────────────────────────────────────
# These MUST live outside the view class (not nested inside a method),
# because both the single-match branch and the list branch call
# _match_data(). Defining it only inside one branch's try block means the
# other branch crashes with NameError the moment it's hit.

def _team_json(team):
    if not team:
        return None
    return {
        "id": team.id,
        "name": team.name,
        "logo_emoji": getattr(team, "logo_emoji", None),
        "logo_color": getattr(team, "logo_color", None),
    }


def _combined_match_datetime(m):
    """
    match_date and match_time are stored as separate columns.
    Combine them into a single ISO datetime string so the frontend
    can reliably compare against "now" to gate the live-watch button.
    """
    if not m.match_date:
        return None
    t = m.match_time or datetime.min.time()
    dt = datetime.combine(m.match_date, t)
    return dt.isoformat()


def _match_data(m):
    live = LiveScore.objects.filter(match_id=m.id).order_by("-updated_at").first()

    # batting_team_id / bowling_team_id hold the *latest* live state on the
    # Match row. Once the match is over, batting_team_id is whichever team
    # was batting last (2nd innings, usually), and bowling_team_id is the
    # team that bowled last — i.e. the team that batted FIRST.
    first_batting_id = m.bowling_team_id or m.team_a_id

    team_a_runs = team_a_wickets = team_a_balls = 0
    team_b_runs = team_b_wickets = team_b_balls = 0

    if live:
        if live.innings == 2:
            # innings1_* holds the (now finished) first innings' final score
            inn1_runs, inn1_wkts, inn1_balls = live.innings1_runs or 0, live.innings1_wickets or 0, live.innings1_balls or 0
            inn2_runs, inn2_wkts, inn2_balls = live.runs or 0, live.wickets or 0, live.balls or 0
        else:
            # Only one innings has been recorded so far
            inn1_runs, inn1_wkts, inn1_balls = live.runs or 0, live.wickets or 0, live.balls or 0
            inn2_runs, inn2_wkts, inn2_balls = 0, 0, 0

        if first_batting_id == m.team_a_id:
            team_a_runs, team_a_wickets, team_a_balls = inn1_runs, inn1_wkts, inn1_balls
            team_b_runs, team_b_wickets, team_b_balls = inn2_runs, inn2_wkts, inn2_balls
        else:
            team_b_runs, team_b_wickets, team_b_balls = inn1_runs, inn1_wkts, inn1_balls
            team_a_runs, team_a_wickets, team_a_balls = inn2_runs, inn2_wkts, inn2_balls
    else:
        # No LiveScore row at all — fall back to whatever's on Match itself
        team_a_runs, team_a_wickets, team_a_balls = m.team_a_runs, m.team_a_wickets, m.team_a_balls
        team_b_runs, team_b_wickets, team_b_balls = m.team_b_runs, m.team_b_wickets, m.team_b_balls

    winner = None
    if m.status == "completed" and (team_a_runs or team_b_runs):
        if team_a_runs > team_b_runs:
            winner = f"{m.team_a.name} Won"
        elif team_b_runs > team_a_runs:
            winner = f"{m.team_b.name} Won"
        else:
            winner = "Match Tied"

    return {
        "id": m.id,
        "status": m.status,
        "overs": m.overs,
        "venue": m.venue,
        "match_date": _combined_match_datetime(m),  # combined date+time ISO string
        "team_a": _team_json(m.team_a),
        "team_b": _team_json(m.team_b),
        "team_a_runs": team_a_runs,
        "team_a_wickets": team_a_wickets,
        "team_a_balls": team_a_balls,
        "team_b_runs": team_b_runs,
        "team_b_wickets": team_b_wickets,
        "team_b_balls": team_b_balls,
        "winner": winner,
        "toss_choice": m.toss_choice,
        "toss_winner_id": m.toss_winner_id,
    }


# ── View ───────────────────────────────────────────────────────────────
class MatchAPIView(APIView):

    # ── GET ──────────────────────────────────────────────
    def get(self, request, id=None):

        # Single match
        if id is not None:
            try:
                m = Match.objects.select_related("team_a", "team_b").get(id=id)
                return Response({
                    "status": {"code": 200, "response": "success"},
                    "error":  None,
                    "data":   _match_data(m),
                })
            except Match.DoesNotExist:
                return Response({
                    "status":  {"code": 404, "response": "failed"},
                    "message": "Match not found",
                })

        # All matches
        try:
            status_filter = request.query_params.get("status")
            qs = Match.objects.select_related("team_a", "team_b").all().order_by("-created_at")
            if status_filter:
                qs = qs.filter(status=status_filter)

            return Response({
                "status": {"code": 200, "response": "success"},
                "error":  None,
                "data":   [_match_data(m) for m in qs],
            })
        except Exception as e:
            return Response({
                "status":  {"code": 400, "response": "failed"},
                "message": str(e),
            })

    # ── POST — Create ────────────────────────────────────
    def post(self, request):
        data = request.data
        try:
            team_a_id = data.get("team_a")
            team_b_id = data.get("team_b")
            overs     = int(data.get("overs", 10))
 
            if not team_a_id or not team_b_id:
                return Response({"status": {"code": 400, "response": "failed"}, "message": "team_a மற்றும் team_b required."})
            if str(team_a_id) == str(team_b_id):
                return Response({"status": {"code": 400, "response": "failed"}, "message": "ஒரே team இரண்டு முறை select பண்ண முடியாது!"})
            if overs < 1 or overs > 50:
                return Response({"status": {"code": 400, "response": "failed"}, "message": "Overs 1-50 இடையே இருக்கணும்."})
 
            team_a = Team.objects.get(id=team_a_id)
            team_b = Team.objects.get(id=team_b_id)
 
            toss_winner_id  = data.get("toss_winner")
            toss_choice     = data.get("toss_choice")
            batting_team_id = data.get("batting_team")
            bowling_team_id = data.get("bowling_team")
            striker_id      = data.get("striker")
            non_striker_id  = data.get("non_striker")
            bowler_id       = data.get("bowler")
 
            toss_winner  = Team.objects.get(id=toss_winner_id)   if toss_winner_id  else None
            batting_team = Team.objects.get(id=batting_team_id)  if batting_team_id else None
            bowling_team = Team.objects.get(id=bowling_team_id)  if bowling_team_id else None
            striker      = Player.objects.get(id=striker_id)     if striker_id      else None
            non_striker  = Player.objects.get(id=non_striker_id) if non_striker_id  else None
            bowler       = Player.objects.get(id=bowler_id)      if bowler_id       else None
 
            match_date_str = data.get("match_date")
            match_time_str = data.get("match_time")
            match_date = datetime.strptime(match_date_str, "%Y-%m-%d").date() if match_date_str else None
            match_time = datetime.strptime(match_time_str, "%H:%M").time()    if match_time_str else None
 
            match = Match.objects.create(
                team_a       = team_a,
                team_b       = team_b,
                toss_winner  = toss_winner,
                toss_choice  = toss_choice,
                batting_team = batting_team,
                bowling_team = bowling_team,
                striker      = striker,
                non_striker  = non_striker,
                bowler       = bowler,
                overs        = overs,
                venue        = data.get("venue", "").strip(),
                status       = data.get("status", "live"),
                match_date   = match_date,
                match_time   = match_time,
            )
 
            return Response({
                "status":  {"code": 201, "response": "success"},
                "message": f"{team_a.name} vs {team_b.name} match create ஆச்சு! 🏏",
                "data":    _match_data(match),             # ✅ FIX 3
            })
 
        except Team.DoesNotExist:
            return Response({"status": {"code": 404, "response": "failed"}, "message": "Team not found"})
        except Player.DoesNotExist:
            return Response({"status": {"code": 404, "response": "failed"}, "message": "Player not found"})
        except Exception as e:
            return Response({"status": {"code": 400, "response": "failed"}, "message": str(e)})
 
    # ── PUT — Update ─────────────────────────────────────
    def put(self, request, id=None):
        if id is None:
            return Response({"status": {"code": 400, "response": "failed"}, "message": "Match id required."})
 
        try:
            match = Match.objects.get(id=id)
        except Match.DoesNotExist:
            return Response({"status": {"code": 404, "response": "failed"}, "message": "Match not found"})
 
        data = request.data
        try:
            if "overs" in data:
                overs = int(data["overs"])
                if overs < 1 or overs > 50:
                    return Response({"status": {"code": 400, "response": "failed"}, "message": "Overs 1-50 இடையே இருக்கணும்."})
                match.overs = overs
 
            if "venue" in data:
                match.venue = data["venue"].strip()
 
            if "status" in data:
                allowed = ["live", "upcoming", "completed"]
                if data["status"] not in allowed:
                    return Response({"status": {"code": 400, "response": "failed"}, "message": f"Status must be one of: {allowed}"})
                match.status = data["status"]
 
            if "match_date" in data and data["match_date"]:
                match.match_date = datetime.strptime(data["match_date"], "%Y-%m-%d").date()
 
            if "match_time" in data and data["match_time"]:
                match.match_time = datetime.strptime(data["match_time"], "%H:%M").time()
 
            if "toss_winner" in data and data["toss_winner"]:
                match.toss_winner = Team.objects.get(id=data["toss_winner"])
            if "toss_choice" in data:
                match.toss_choice = data["toss_choice"]
 
            if "batting_team" in data and data["batting_team"]:
                match.batting_team = Team.objects.get(id=data["batting_team"])
            if "bowling_team" in data and data["bowling_team"]:
                match.bowling_team = Team.objects.get(id=data["bowling_team"])
 
            if "striker" in data and data["striker"]:
                match.striker = Player.objects.get(id=data["striker"])
            if "non_striker" in data and data["non_striker"]:
                match.non_striker = Player.objects.get(id=data["non_striker"])
            if "bowler" in data and data["bowler"]:
                match.bowler = Player.objects.get(id=data["bowler"])
 
            match.save()
 
            return Response({
                "status":  {"code": 200, "response": "success"},
                "message": "Match updated successfully! 🏏",
                "data":    _match_data(match),             # ✅ FIX 4
            })
 
        except Team.DoesNotExist:
            return Response({"status": {"code": 404, "response": "failed"}, "message": "Team not found"})
        except Player.DoesNotExist:
            return Response({"status": {"code": 404, "response": "failed"}, "message": "Player not found"})
        except ValueError as e:
            return Response({"status": {"code": 400, "response": "failed"}, "message": f"Invalid value: {e}"})
        except Exception as e:
            return Response({"status": {"code": 400, "response": "failed"}, "message": str(e)})
 


class UserDashboardAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user.id
        # உங்கள் Booking மாடல் பெயருக்கு ஏற்ப மாற்றவும்
        booking_count = UserBooking.objects.filter(user_id=user).count()
        # வேறு ஏதேனும் கவுண்ட் தேவைப்பட்டால் இங்கே சேர்க்கலாம்
        
        return Response({
            "status": "success",
            "data": {
                "booking_count": booking_count,
                "expiry_minutes": 30  # செஷன் டைம் தகவலுக்காக
            }
        })
    
def send_otp_email(email, otp):
    # Subject-ஐ இன்னும் தெளிவாக மாற்றியுள்ளேன்
    subject = 'OTP Verification - iITS Community'
    
    # Message-ஐ பிராண்டிங்கிற்கு ஏத்த மாதிரி மாற்றியுள்ளேன்
    message = f'''Dear User,

    Welcome to iITS Community! 🚀

    Your One-Time Password (OTP) for account verification is:

    {otp}

    This code is valid for the next 1 minutes. Please do not share this OTP with anyone.


    Best regards,
    Team iITS Community
    iITS Community Support Team
    '''
    try:
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [email],
            fail_silently=False,
        )
        print(f"Success: OTP sent to {email}")
    except Exception as e:
        print(f"Error sending email: {e}")


def forgot_send_otp_email(email, otp):
    subject = 'Password Reset Request - iITS Community'
    
    message = f'''Dear User,

    We received a request to reset the password for your iITS Community account. 🔐

    Your One-Time Password (OTP) for password reset is:

    {otp}

    This code is valid for a limited time. If you did not request this, please ignore this email and ensure your account is secure.

    Please do not share this OTP with anyone for security reasons.


    Best regards,
    Team iITS Community
    Support Team
    '''
    try:
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [email],
            fail_silently=False,
        )
        print(f"Success: Forgot Password OTP sent to {email}")
    except Exception as e:
        print(f"Error sending email: {e}")

def send_otp_emails(email, otp):
   
    subject = 'Your One-Time  (OTP) for Verification'
    message = f'''Dear User,

    Your One-Time  (OTP) for verification is:

    {otp}

    Please enter this code to proceed. This OTP is valid for the next 1 minutes.

    If you did not request this code, please ignore this email.

    Thank you,  
    Pearlcon Technologies LLP
    https://pearlcons.com
        '''
    try:
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [email],
            fail_silently=False,
        )
    except Exception as e:
        print(f"Error sending email: {e}")

        



from django.contrib.auth import get_user_model
User = get_user_model()

class SendotpAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            email = data.get('email', '').strip().lower() # Space-களை நீக்கி, சிறிய எழுத்துகளாக மாற்றுகிறது

            if not email:
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Email address is required."
                }, status=status.HTTP_400_BAD_REQUEST)

            # --- Role 3-க்காக மட்டும் செக் செய்கிறோம் ---
            if Profiles.objects.filter(email=email, role="3").exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "This email is already registered as a User. Please try another email."
                }, status=status.HTTP_400_BAD_REQUEST)
           
            user = Otp.objects.create(email=email)
            otp = get_random_string(length=6, allowed_chars='1234567890')
            user.otp = otp
            user.otp_created_at = timezone.now()
            user.save()

            threading.Thread(target=send_otp_email, args=(email, otp)).start()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "Success"},
                "error": None,
                "data": {"email": email}
            })
        except Exception as e:
            print("Error:", e)
            return Response({
                "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "Internal Server Error"},
                'error': True,
                "message": str(e)
            })

class ForgototpAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            username = data.get('username', '').strip()

            if not username:
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Username is required."
                }, status=status.HTTP_400_BAD_REQUEST)

            # 1. Profile செக் செய்தல்
            profile = Profiles.objects.filter(name=username).first() 

            if not profile:
                return Response({
                    "status": {"code": 404, "response": "failed"},
                    "message": "User not found. Please check your username."
                }, status=status.HTTP_404_NOT_FOUND)

            email = profile.email
            
            # --- எரர் வராமல் தடுக்க இங்கே தான் மாற்றம் செய்கிறோம் ---
            # 2. அந்த ஈமெயிலுக்கு ஏற்கனவே உள்ள அத்தனை பழைய OTP-களையும் மொத்தமாக நீக்குகிறோம்
            Otp.objects.filter(email=email).delete()
            
            # 3. இப்போது புதிய OTP-ஐ உருவாக்குகிறோம்
            otp_code = get_random_string(length=6, allowed_chars='1234567890')
            otp_user = Otp.objects.create(
                email=email,
                otp=otp_code,
                otp_created_at=timezone.now()
            )

            # 4. Email அனுப்புதல்
            threading.Thread(target=forgot_send_otp_email, args=(email, otp_code)).start()

            return Response({
                "status": {"code": 200, "response": "Success"},
                "error": None,
                "data": {"email": email}, 
                "message": "OTP sent to your registered email."
            }, status=status.HTTP_200_OK)

        except Exception as e:
            print("Forgot OTP Error:", e) # இப்போது இந்த எரர் வராது சார்
            return Response({
                "status": {"code": 500, "response": "failed"},
                "error": True,
                "message": f"Server Error: {str(e)}"
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class PasswordresetAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            username = data.get('username', '').strip()
            new_password = data.get('new_password', '').strip()

            if not username or not new_password:
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Username and New Password are required."
                }, status=status.HTTP_400_BAD_REQUEST)

            # 1. Profiles டேபிளில் அந்த யூசர் இருக்கிறாரா என்று பார்த்தல்
            profile = Profiles.objects.filter(name=username).first()

            if not profile:
                return Response({
                    "status": {"code": 404, "response": "failed"},
                    "message": "User profile not found."
                }, status=status.HTTP_404_NOT_FOUND)

            # 2. Django-வின் மெயின் User மாடலில் பாஸ்வேர்டை அப்டேட் செய்தல்
            # (ஏனெனில் லாகின் செய்யும்போது இதுதான் முக்கியம்)
            user = User.objects.filter(id=profile.user_id).first()
            if user:
                user.password = make_password(new_password) # Hash செய்தல்
                user.save()

            # 3. உங்கள் கஸ்டம் Profiles டேபிளிலும் அப்டேட் செய்தல்
            profile.password = new_password # ஒருவேளை நீங்கள் பிளைன் டெக்ஸ்டாக சேமிக்க விரும்பினால்
            profile.save()

            # 4. பாதுகாப்பு கருதி, அந்த யூசரின் பழைய OTP-களை நீக்கிவிடுதல்
            Otp.objects.filter(email=profile.email).delete()

            return Response({
                "status": {"code": 200, "response": "success"},
                "message": "Password updated successfully! You can now login."
            }, status=status.HTTP_200_OK)

        except Exception as e:
            print("Reset Password Error:", e)
            return Response({
                "status": {"code": 500, "response": "failed"},
                "message": f"Server Error: {str(e)}"
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class VerifyforgototpAPIView(APIView):
    def get(self, request):
        # 1. Params-லிருந்து டேட்டாவை எடுத்தல்
        username = request.query_params.get('username', '').strip()
        otp_entered = request.query_params.get('otp', '').strip()

        try:
            # 2. முதலில் Username-ஐ வைத்து Profile-லிருந்து Email-ஐ எடுக்கவும்
            profile = Profiles.objects.filter(name=username).first()
            
            if not profile:
                return Response({
                    "status": {"code": 404, "response": "failed"},
                    "message": "User not found."
                }, status=status.HTTP_404_NOT_FOUND)

            email = profile.email

            # 3. OTP டேபிளில் அந்த Email மற்றும் OTP இருக்கிறதா என்று பார்ப்பது
            otp_record = Otp.objects.filter(email=email, otp=otp_entered).first()

            if otp_record:
                # OTP சரி! (வெற்றிகரமாக வெரிஃபை ஆகிவிட்டது)
                return Response({
                    "status": {"code": 200, "response": "success"},
                    "message": "OTP Verified successfully."
                }, status=status.HTTP_200_OK)
            else:
                # OTP தவறாக இருந்தால்
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "Invalid OTP. Please check the code."
                }, status=status.HTTP_400_BAD_REQUEST)

        except Exception as e:
            return Response({
                "status": {"code": 500, "response": "failed"},
                "message": str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class SendotpsAPIView(APIView):
    def post(self, request):
        data = request.data
        try:
            email = data.get('email', None)
            print('Received email:', email)

            # If this is registration
            if User.objects.filter(email=email).exists():
                return Response({
                    "status": {"code": status.HTTP_409_CONFLICT, "response": "Email already registered"},
                    "error": True,
                    "message": "This email is already registered. Please use another email."
                })

            otp = get_random_string(length=6, allowed_chars='1234567890')
            user = Otp.objects.create(email=email, otp=otp, otp_created_at=timezone.now())

            threading.Thread(target=send_otp_emails, args=(email, otp)).start()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "Success"},
                "error": None,
                "data": {"email": email}
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "Internal Server Error"},
                'error': True,
                "message": str(e)
            })

from datetime import timedelta
from django.utils import timezone

class VerifyotpAPIView(APIView):
    def get(self, request):
        email = request.query_params.get('email')
        otp_entered = request.query_params.get('otp')

        try:
            user_otp = Otp.objects.filter(email=email).latest('otp_created_at')

            # Expiry time check (30 seconds)
            expiration_time = user_otp.otp_created_at + timedelta(seconds=60)
            if timezone.now() > expiration_time:
                return Response({
                    "status": 401,
                    "message": "OTP expired. Please request a new one.",
                    "error": True
                }, status=status.HTTP_200_OK) 

            if otp_entered == user_otp.otp:
                return Response({
                    "status": 200,
                    "message": "OTP Verified",
                    "error": False
                }, status=status.HTTP_200_OK)
            else:
                return Response({
                    "status": 400,
                    "message": "Invalid OTP",
                    "error": True
                }, status=status.HTTP_200_OK)

        except Otp.DoesNotExist:
            return Response({
                "status": 404,
                "message": "OTP not found",
                "error": True
            }, status=status.HTTP_200_OK)




    def delete(self, request, id):
        if id is not None:
            try:
                profile = Profiles.objects.get(user_id=id)

                # Delete the image file from storage (optional)
                if profile.profiles:  # replace 'image' with your actual image field name
                    profile.profiles.delete(save=False)  # Deletes the file from MEDIA folder
                    profile.profiles = None
                    profile.save()

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "message": "Profile image deleted successfully"
                })

            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": None,
                    "message": "Profile not found"
                })

        return Response({
            "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
            "error": "ID not provided",
            "message": "User ID is required"
        })




class ProfileupdateAPIView(APIView):
    
    permission_classes = (IsAuthenticated,)

    def get(self, request, **kwargs):
        id = kwargs.get('id')


        if id is not None:
            try:
                user = User.objects.get(id=id)
                company = Profiles.objects.get(user_id=user.id)
                if company.profiles and company.profiles.url != "../static/dummy.png":
                    pr = company.profiles.url
                else:
                    pr = "../static/dummy.png"

                data = {
                    'name': company.name,
                    'email': company.email,
                    'phone': company.phone,
                    'f_name': user.first_name,
                    'l_name': user.last_name,

                    'profile' : pr,
                    'id': user.id   
                }



                

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "Success"},
                    "error": None,
                    "data": data
                })
            except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "Failed"},
                    'error': True,
                    "message": "Company not found"
                })

    def post(self, request):
        data = request.data
        try:


            pho = data.get("prof_photo")
            # name = data.get("username")

            take = Profiles.objects.get(user_id=request.user.id)
            take.profiles = pho

            take.save()
            # # Create User instance
            # van = User(username=name, email=email, password=hashed_password)
            # van.save()

           

            return Response({
                "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                "error": None,
                "message": "Profile updated successfully"
            })

        except KeyError as e:
            return Response({
                "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error": True,
                "message": f"Missing required field: {str(e)}"
            })
        except Exception as e:
            return Response({
                "status": {"code": status.HTTP_500_INTERNAL_SERVER_ERROR, "response": "failed"},
                "error": True,
                "message": f"An error occurred: {str(e)}"
            })


    def put(self, request, id):
        data = request.data
        # 1. போட்டோவை FILES-ல் இருந்து எடுக்கவும்
        photo = request.FILES.get('prof_photo') 
        
        try:
            mm = Profiles.objects.get(user_id=id)
            sd = User.objects.get(id=id)

            # 2. User டேபிள் அப்டேட் (get() பயன்படுத்துவது பாதுகாப்பானது)
            sd.username = data.get("first_name", sd.username)
            sd.first_name = data.get("first_names", sd.first_name)
            sd.last_name = data.get("last_name", sd.last_name)
            sd.email = data.get("email_id", sd.email)
            sd.save()

            # 3. Profiles டேபிள் அப்டேட்
            mm.email = data.get("email_id", mm.email)
            mm.phone = data.get("phone_no", mm.phone)
            mm.name = data.get("first_name", mm.name)

            # 4. இமேஜ் இருந்தால் மட்டும் அப்டேட் செய்யவும்
            if photo:
                mm.profiles = photo
            
            mm.save()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "User updated successfully"
            })

        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "User not found"
            })


class UserlistAPIView(APIView):
    def get(self, request, **kwargs):
        id = kwargs.get('id')


        if id is not None:
            try:
                student = Profiles.objects.get(user_id=id)
                data = {
                    'id': student.user_id,
                    'username': student.name,
                    'phone': student.phone,
                    'password': student.password,
                    'email': student.email,
                   
                    'status': student.status,
                    # Photo URL-ஐ எடுக்க (உதாரணமாக: http://127.0.0.1:8000/media/students/abc.jpg)
                    'profile_photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except Student.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No student found",
                })
        else:
            try:
                employees = Profiles.objects.filter(role=3)
                employee_list = []
                for index, student in enumerate(employees, 1):
                    employee_list.append({
                        'row': index,
                        'id': student.user_id,
                        'employeeName': student.name,
                        'email': student.email,
                        'phone': student.phone,
                        'status': student.status,

                        'photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": employee_list
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })


class RegisterAPIView(APIView):
    def get(self, request, **kwargs):
        id = kwargs.get('id')


        if id is not None:
            try:
                student = Profiles.objects.get(user_id=id)
                data = {
                    'id': student.user_id,
                    'username': student.name,
                    'phone': student.phone,
                    'password': student.password,
                    'email': student.email,
                   
                    'status': student.status,
                    # Photo URL-ஐ எடுக்க (உதாரணமாக: http://127.0.0.1:8000/media/students/abc.jpg)
                    'profile_photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                }

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": data
                })
            except Student.DoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error": True,
                    "message": "No student found",
                })
        else:
            try:
                employees = Profiles.objects.filter(role=0).order_by('-created_at')
                employee_list = []
                for index, student in enumerate(employees, 1):
                    employee_list.append({
                        'row': index,
                        'id': student.user_id,
                        'employeeName': student.name,
                        'email': student.email,
                        'phone': student.phone,
                        'status': student.status,

                        'photo': request.build_absolute_uri(student.profiles.url) if student.profiles else None
                    })

                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error": None,
                    "data": employee_list
                })
            except Exception as e:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": str(e),
                })
    def post(self, request):
        data = request.data
        # ஆப்பில் இருந்து "profile_photo" என்று அனுப்புகிறோம், அதை இங்கே எடுக்கிறோம்
        photo = request.FILES.get('profile_photo') 


        try:
            username = data.get('username')
            email = data.get('email')
            phone = data.get('phone')
            password = data.get('password')
            role = data.get('role')


            if role == "3":
                roles  = "3"
            else:
                roles = "0"


            if Profiles.objects.filter(name=username, role="3").exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": f"Username '{username}' is already taken."
                }, status=status.HTTP_400_BAD_REQUEST)

            # 2. Check if Email already exists
            if Profiles.objects.filter(email=email, role="3").exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "This email address is already registered."
                }, status=status.HTTP_400_BAD_REQUEST)

            # 3. Check if Phone already exists
            if Profiles.objects.filter(phone=phone, role="3").exists():
                return Response({
                    "status": {"code": 400, "response": "failed"},
                    "message": "This mobile number is already registered."
                }, status=status.HTTP_400_BAD_REQUEST)


            # 1. User உருவாக்குதல்
            hashed_password = make_password(password)
            van = User.objects.create(
                username=username, 
                email=email, 
                password=hashed_password
            )

            # 2. Profile உருவாக்குதல்
            photo = request.FILES.get('profile_photo') 

            profile = Profiles.objects.create(
                name=username,
                email=email,
                phone=phone,
                role=roles,
                user_id=van.id,
                password=password,
                profiles=photo  # 👈 உங்கள் Database Column பெயர் 'profiles' என்றால் இது சரி
            )

            return Response({
                "status": {"code": 201, "response": "success"},
                "error": None,
                "message": "Employee created successfully",
            }, status=status.HTTP_201_CREATED)

        except Exception as e:
            return Response({
                "status": {"code": 400, "response": "failed"},
                "error": True,
                "message": f"Error: {str(e)}"
        }, status=status.HTTP_400_BAD_REQUEST)


    
    def put(self, request, id):
        data = request.data
        # ஆப்பில் இருந்து "profile_photo" என்று அனுப்புகிறோம், அதை இங்கே எடுக்கிறோம்
        photo = request.FILES.get('profile_photo') 
        
        try:
                photo = request.FILES.get('profile_photo') 

                username = data.get('username')
                email = data.get('email')
                phone = data.get('phone')
                password = data.get('password')
                mm = Profiles.objects.get(user_id=id)
                sd = User.objects.get(id=id)

                mm.name = username
                mm.email = email
                mm.phone = phone

                mm.password = password

                if photo:
                    mm.profiles = photo
                mm.save()
                passes = make_password(password) 
                sd.username = username
                sd.email = email
                sd.password = passes
                sd.save()

                return Response({
                    "status": {"code": status.HTTP_201_CREATED, "response": "success"},
                    "error": None,
                    "message": "User updated successfully"
                })
        except ObjectDoesNotExist:
                return Response({
                    "status": {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "error": True,
                    "message": "Something went wrong"
                })

    def delete(self,  *args, **kwargs):
        company_id = kwargs.get('id')

        try:

            pr  = Profiles.objects.get(user_id =company_id)
            pr.delete()
            company = User.objects.get(id=company_id)
            company.delete()

            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error": None,
                "message": "Company deleted successfully"
            })
        except ObjectDoesNotExist:
            return Response({
                "status": {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error": True,
                "message": "No data found"
            })




        



    



class 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 DashboardStatsAPIView(APIView):
    def get(self, request):
        date_str = request.query_params.get('date', None)
        target_date = datetime.strptime(date_str, '%Y-%m-%d').date() if date_str else timezone.now().date()

        all_students = Student.objects.filter(status=1)
        
        # Attendance filtering
        n_present_ids = Attendance.objects.filter(date=target_date, session_type=1, status="Present").values_list('student_id', flat=True)
        s_present_ids = Attendance.objects.filter(date=target_date, session_type=2, status="Present").values_list('student_id', flat=True)

        # Count total eligible students for each type
        n_total = all_students.filter(classType__in=[1, 3]).count()
        s_total = all_students.filter(classType__in=[2, 3]).count()

        n_present = len(n_present_ids)
        s_present = len(s_present_ids)

        # Percentage calculation
        n_percent = int((n_present / n_total) * 100) if n_total > 0 else 0
        s_percent = int((s_present / s_total) * 100) if s_total > 0 else 0

        student_daily_list = []
        for student in all_students:
            is_n_elg = student.classType in [1, 3]
            is_s_elg = student.classType in [2, 3]
            
            n_status = "P" if student.id in n_present_ids else ("A" if is_n_elg else "--")
            s_status = "P" if student.id in s_present_ids else ("A" if is_s_elg else "--")

            student_daily_list.append({
                "name": student.studentName,
                "n_status": n_status,
                "s_status": s_status,
                "is_special": is_s_elg
            })

        return Response({
            "status": {"code": 200, "response": "success"},
            "data": {
                "n_data": {"present": n_present, "total": n_total, "percent": n_percent},
                "s_data": {"present": s_present, "total": s_total, "percent": s_percent},
                "student_list": student_daily_list,
                "selected_date": target_date.strftime('%Y-%m-%d')
            }
        })
        
class 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 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 TeamAPIView(APIView):
    # permission_classes = (IsAuthenticated,)
 
    # ════════════════════════════════════════════
    #  GET — single team or all teams
    # ════════════════════════════════════════════
    def get(self, request, id=None):
 
        # ── Single team ──────────────────────────
        if id is not None:
            try:
                team = Team.objects.get(id=id)
 
                # players_count — safely try பண்றோம்
                try:
                    p_count = team.player_set.count()
                except Exception:
                    try:
                        p_count = team.players.count()
                    except Exception:
                        p_count = 0
 
                data = {
                    'id':            team.id,
                    'name':          team.name,
                    'short_name':    team.short_name,
                    'logo_emoji':    team.logo_emoji,
                    'logo_color':    team.logo_color,
                    'home_ground':   team.home_ground,
                    'captain_name':  team.captain_name,
                    'status':        team.status,
                    'players_count': p_count,
                    'created_at':    team.created_at,
                }
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error":  None,
                    "data":   data,
                })
            except Team.DoesNotExist:
                return Response({
                    "status":  {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error":   True,
                    "message": "Team not found",
                })
 
        # ── All teams ────────────────────────────
        else:
            try:
                # annotate பண்றோம் — @property தேவையில்லை
                # உங்க Player model-ல் team ForeignKey இருந்தா:
                #   class Player(models.Model):
                #       team = models.ForeignKey(Team, ...)
                # அப்போ Count('player') — lowercase model name
                # related_name='players' வச்சிருந்தா → Count('players')
 
                teams_qs = (
                    Team.objects.all()
                    .order_by('-created_at')
                    .annotate(pc=Count('player'))
                )
 
                team_list = []
                for index, team in enumerate(teams_qs, 1):
                    team_list.append({
                        'row':           index,
                        'id':            team.id,
                        'name':          team.name,
                        'short_name':    team.short_name,
                        'logo_emoji':    team.logo_emoji,
                        'logo_color':    team.logo_color,
                        'home_ground':   team.home_ground,
                        'captain_name':  team.captain_name,
                        'status':        team.status,
                        'players_count': team.pc,
                    })
 
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error":  None,
                    "data":   team_list,
                })
 
            except Exception as e:
                # annotate fail ஆனா — count இல்லாம return பண்றோம்
                try:
                    teams_qs = Team.objects.all().order_by('-created_at')
                    team_list = []
                    for index, team in enumerate(teams_qs, 1):
                        team_list.append({
                            'row':           index,
                            'id':            team.id,
                            'name':          team.name,
                            'short_name':    team.short_name,
                            'logo_emoji':    team.logo_emoji,
                            'logo_color':    team.logo_color,
                            'home_ground':   team.home_ground,
                            'captain_name':  team.captain_name,
                            'status':        team.status,
                            'players_count': 0,
                        })
                    return Response({
                        "status": {"code": status.HTTP_200_OK, "response": "success"},
                        "error":  None,
                        "data":   team_list,
                    })
                except Exception as e2:
                    return Response({
                        "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                        "error":   True,
                        "message": str(e2),
                    })
 
    # ════════════════════════════════════════════
    #  POST — Create new team
    # ════════════════════════════════════════════
    def post(self, request):
        data = request.data
        try:
            name = data.get('name', '').strip()
            if not name:
                return Response({
                    "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "message": "Team name is required.",
                })
            if Team.objects.filter(name__iexact=name).exists():
                return Response({
                    "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "message": f"'{name}' என்ற team ஏற்கனவே இருக்கு!",
                })
            team = Team.objects.create(
                name         = name,
                short_name   = data.get('short_name', '').strip().upper()[:10],
                logo_emoji   = data.get('logo_emoji', '🏏'),
                logo_color   = data.get('logo_color', '#1565C0'),
                home_ground  = data.get('home_ground', '').strip(),
                captain_name = data.get('captain_name', '').strip(),
                status       = int(data.get('status', 1)),
            )
            return Response({
                "status":  {"code": status.HTTP_201_CREATED, "response": "success"},
                "message": f"Team '{team.name}' create ஆச்சு! 🏏",
                "data":    {"id": team.id, "name": team.name},
            })
        except Exception as e:
            return Response({
                "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "message": str(e),
            })
 
    # ════════════════════════════════════════════
    #  PUT — Update team
    # ════════════════════════════════════════════
    def put(self, request, id):
        data = request.data
        try:
            team = Team.objects.get(id=id)
            name = data.get('name', team.name).strip()
            if Team.objects.filter(name__iexact=name).exclude(id=id).exists():
                return Response({
                    "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "message": f"'{name}' என்ற team ஏற்கனவே இருக்கு!",
                })
            team.name         = name
            team.short_name   = data.get('short_name',   team.short_name   or '').strip().upper()[:10]
            team.logo_emoji   = data.get('logo_emoji',   team.logo_emoji)
            team.logo_color   = data.get('logo_color',   team.logo_color)
            team.home_ground  = data.get('home_ground',  team.home_ground  or '').strip()
            team.captain_name = data.get('captain_name', team.captain_name or '').strip()
            if 'status' in data:
                team.status = int(data.get('status'))
            team.save()
            return Response({
                "status":  {"code": status.HTTP_200_OK, "response": "success"},
                "message": f"Team '{team.name}' updated ஆச்சு! ",
                "data":    {"id": team.id, "name": team.name},
            })
        except Team.DoesNotExist:
            return Response({
                "status":  {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "message": "Team not found",
            })
        except Exception as e:
            return Response({
                "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "message": str(e),
            })
 
    # ════════════════════════════════════════════
    #  DELETE — Delete team
    # ════════════════════════════════════════════
    def delete(self, request, id):
        try:
            team      = Team.objects.get(id=id)
            team_name = team.name
            # Player.objects.filter(team_id=id).delete()  # cascade இல்லன்னா uncomment
            team.delete()
            return Response({
                "status":  {"code": status.HTTP_200_OK, "response": "success"},
                "error":   None,
                "message": f"Team '{team_name}' deleted! ",
            })
        except Team.DoesNotExist:
            return Response({
                "status":  {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error":   True,
                "message": "Team not found",
            })
        except Exception as e:
            return Response({
                "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error":   True,
                "message": str(e),
            })
        


class PlayerAPIView(APIView):
    # permission_classes = (IsAuthenticated,)   # uncomment if auth needed
 
    # ════════════════════════════════════════════
    #  GET — ?team=<id>  → team-ல் உள்ள players
    #        ?id=<id>    → single player
    # ════════════════════════════════════════════
    def get(self, request, id=None):
 
        # Single player
        if id is not None:
            try:
                player = Player.objects.get(id=id)
                return Response({
                    "status": {"code": status.HTTP_200_OK, "response": "success"},
                    "error":  None,
                    "data": {
                        "id":        player.id,
                        "name":      player.name,
                        "player_id": player.player_id,
                        "role":      player.role,
                        "team":      player.team_id,
                        "team_name": player.team.name,
                        "status":    player.status,
                    },
                })
            except Player.DoesNotExist:
                return Response({
                    "status":  {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                    "error":   True,
                    "message": "Player not found",
                })
 
        # All players (filter by team optional)
        team_id = request.query_params.get("team")
        try:
            qs = Player.objects.select_related("team").all()
            if team_id:
                qs = qs.filter(team_id=team_id)
 
            player_list = []
            for index, p in enumerate(qs, 1):
                player_list.append({
                    "row":       index,
                    "id":        p.id,
                    "name":      p.name,
                    "player_id": p.player_id,
                    "role":      p.role,
                    "team":      p.team_id,
                    "team_name": p.team.name,
                    "status":    p.status,
                })
 
            return Response({
                "status": {"code": status.HTTP_200_OK, "response": "success"},
                "error":  None,
                "data":   player_list,
            })
 
        except Exception as e:
            return Response({
                "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error":   True,
                "message": str(e),
            })
 
    # ════════════════════════════════════════════
    #  POST — Create player
    # ════════════════════════════════════════════
    def post(self, request):
        data = request.data
        try:
            name = data.get("name", "").strip()
            if not name:
                return Response({
                    "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "message": "Player name is required.",
                })
 
            team_id = data.get("team")
            if not team_id:
                return Response({
                    "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "message": "Team ID is required.",
                })
 
            # Team exist பண்றதா check
            try:
                team = Team.objects.get(id=team_id)
            except Team.DoesNotExist:
                return Response({
                    "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                    "message": f"Team ID {team_id} not found.",
                })
 
            # Role validate
            valid_roles = ["BAT", "BOWL", "ALL", "WK"]
            role = data.get("role", "BAT")
            if role not in valid_roles:
                role = "BAT"
 
            player = Player.objects.create(
                team      = team,
                name      = name,
                player_id = data.get("player_id", "").strip(),
                role      = role,
                status    = int(data.get("status", 1)),
            )
 
            return Response({
                "status":  {"code": status.HTTP_201_CREATED, "response": "success"},
                "message": f"Player '{player.name}' added to {team.name}! 🏏",
                "data": {
                    "id":        player.id,
                    "name":      player.name,
                    "player_id": player.player_id,
                    "role":      player.role,
                    "team":      player.team_id,
                },
            })
 
        except Exception as e:
            return Response({
                "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "message": str(e),
            })
 
    # ════════════════════════════════════════════
    #  PUT — Update player
    # ════════════════════════════════════════════
    def put(self, request, id):
        data = request.data
        try:
            player = Player.objects.get(id=id)
 
            valid_roles = ["BAT", "BOWL", "ALL", "WK"]
            role = data.get("role", player.role)
            if role not in valid_roles:
                role = player.role
 
            player.name      = data.get("name",      player.name).strip()
            player.player_id = data.get("player_id", player.player_id or "").strip()
            player.role      = role
            if "status" in data:
                player.status = int(data["status"])
            player.save()
 
            return Response({
                "status":  {"code": status.HTTP_200_OK, "response": "success"},
                "message": f"Player '{player.name}' updated! ✅",
                "data":    {"id": player.id, "name": player.name},
            })
 
        except Player.DoesNotExist:
            return Response({
                "status":  {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "message": "Player not found",
            })
        except Exception as e:
            return Response({
                "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "message": str(e),
            })
 
    # ════════════════════════════════════════════
    #  DELETE — Remove player
    # ════════════════════════════════════════════
    def delete(self, request, id):
        try:
            player      = Player.objects.get(id=id)
            player_name = player.name
            player.delete()
            return Response({
                "status":  {"code": status.HTTP_200_OK, "response": "success"},
                "error":   None,
                "message": f"Player '{player_name}' deleted! ✅",
            })
        except Player.DoesNotExist:
            return Response({
                "status":  {"code": status.HTTP_404_NOT_FOUND, "response": "failed"},
                "error":   True,
                "message": "Player not found",
            })
        except Exception as e:
            return Response({
                "status":  {"code": status.HTTP_400_BAD_REQUEST, "response": "failed"},
                "error":   True,
                "message": str(e),
            })
 
 

# import secrets
# import requests
# from rest_framework.views import APIView
# from rest_framework.response import Response
# from rest_framework import status
# from django.shortcuts import get_object_or_404
# from django.utils import timezone
 
# from .models import Match, MatchStream
 
# # ── Config — swap these 2 lines when you move from laptop testing to VPS ──
# MEDIAMTX_API = "http://localhost:9997"    # Django & MediaMTX same machine while testing
# MEDIAMTX_HLS = "http://192.168.29.202:8888"   # ← your laptop's WiFi IP while testing
# RTMP_BASE = "rtmp://192.168.29.202:1935"      # ← your laptop's WiFi IP while testing
# # When going live on a VPS:
# #   MEDIAMTX_API = "http://localhost:9997"   (still localhost IF Django + MediaMTX are on the same VPS)
# #   MEDIAMTX_HLS = "http://YOUR_VPS_IP:8888"
# #   RTMP_BASE    = "rtmp://YOUR_VPS_IP:1935"
 
 
# class StreamAPIView(APIView):
#     """
#     POST /api/v1/stream/start/<match_id>/   → generate key, return RTMP URL
#     GET  /api/v1/stream/status/<match_id>/  → check if live
#     POST /api/v1/stream/stop/<match_id>/    → mark ended
#     GET  /api/v1/stream/watch/<match_id>/   → return HLS URL for viewer
#     """
 
#     # ── Start / stop share the POST verb, routed via urls.py `action` kwarg ──
#     def post(self, request, match_id, action="start"):
#         if action == "start":
#             return self._start_stream(request, match_id)
#         elif action == "stop":
#             return self._stop_stream(request, match_id)
#         return Response({"message": "Unknown action"}, status=status.HTTP_400_BAD_REQUEST)
 
#     def _start_stream(self, request, match_id):
#         try:
#             match = get_object_or_404(Match, id=match_id)
 
#             stream, _created = MatchStream.objects.get_or_create(
#                 match=match,
#                 defaults={
#                     "stream_key": f"match_{match_id}_{secrets.token_hex(8)}",
#                     "status": "idle",
#                 }
#             )
 
#             stream_path = f"live/{stream.stream_key}"
#             stream.hls_url = f"{MEDIAMTX_HLS}/{stream_path}/index.m3u8"
#             stream.status = "live"
#             stream.started_at = timezone.now()
#             stream.save()
 
#             match.status = "live"
#             match.save(update_fields=["status"])
 
#             return Response({
#                 "status": {"code": 200, "response": "success"},
#                 "data": {
#                     "stream_key": stream.stream_key,
#                     "rtmp_url": f"{RTMP_BASE}/{stream_path}",
#                     "hls_url": stream.hls_url,
#                     "match_id": match_id,
#                     "instructions": {
#                         "push_url": f"{RTMP_BASE}/{stream_path}",
#                         "watch_url": stream.hls_url,
#                     }
#                 }
#             })
#         except Match.DoesNotExist:
#             return Response({"message": "Match not found"}, status=status.HTTP_404_NOT_FOUND)
#         except Exception as e:
#             return Response({"message": str(e)}, status=status.HTTP_400_BAD_REQUEST)
 
#     def _stop_stream(self, request, match_id):
#         try:
#             stream = MatchStream.objects.get(match_id=match_id)
#             stream.status = "ended"
#             stream.ended_at = timezone.now()
#             stream.save()
#             return Response({
#                 "status": {"code": 200, "response": "success"},
#                 "message": "Stream stopped",
#                 "data": {"recording_url": stream.get_recording_url()}
#             })
#         except MatchStream.DoesNotExist:
#             return Response({"message": "Stream not found"}, status=status.HTTP_404_NOT_FOUND)
 
#     # ── GET (status / watch), routed via urls.py `action` kwarg ──
#     def get(self, request, match_id, action="watch"):
#         if action == "status":
#             return self._get_status(request, match_id)
#         return self._get_watch_url(request, match_id)
 
#     def _get_status(self, request, match_id):
#         try:
#             stream = MatchStream.objects.get(match_id=match_id)
 
#             is_live = False
#             try:
#                 r = requests.get(f"{MEDIAMTX_API}/v3/paths/get/{stream.stream_key}", timeout=2)
#                 if r.status_code == 200:
#                     data = r.json()
#                     is_live = data.get("ready", False)
#             except Exception:
#                 # MediaMTX unreachable (e.g. not running yet) — fall back to DB flag
#                 is_live = stream.status == "live"
 
#             return Response({
#                 "status": {"code": 200, "response": "success"},
#                 "data": {
#                     "is_live": is_live,
#                     "stream_status": stream.status,
#                     "hls_url": stream.hls_url if is_live else None,
#                     "started_at": stream.started_at,
#                 }
#             })
#         except MatchStream.DoesNotExist:
#             return Response({
#                 "status": {"code": 200, "response": "success"},
#                 "data": {"is_live": False}
#             })
 
#     def _get_watch_url(self, request, match_id):
#         """Read-only — no longer mutates viewer_count (that's WS-driven now)."""
#         try:
#             stream = MatchStream.objects.get(match_id=match_id)
#             return Response({
#                 "status": {"code": 200, "response": "success"},
#                 "data": {
#                     "hls_url": stream.hls_url,
#                     "stream_status": stream.status,
#                     "is_live": stream.status == "live",
#                     "recording_url": stream.get_recording_url(),
#                     "match_id": match_id,
#                 }
#             })
#         except MatchStream.DoesNotExist:
#             return Response({
#                 "status": {"code": 404, "response": "failed"},
#                 "message": "Stream not found for this match"
#             }, status=status.HTTP_404_NOT_FOUND)




















# ═══════════════════════════════════════════════════════════════
#  Django Streaming Backend — HLS + CDN  (FIXED, COMPLETE)
#  pip install requests
# ═══════════════════════════════════════════════════════════════

# ─── settings.py ──────────────────────────────
"""
import os

# ── LOCAL TEST ──
STREAMING = {
    "RTMP_BASE":   "rtmp://192.168.29.202:1935",
    "HLS_BASE":    "http://192.168.29.202:8888",
    "MEDIAMTX_API":"http://192.168.29.202:9997",
    "IS_CDN":      False,
}
"""

import os
import secrets
import requests
from rest_framework.views import APIView
from rest_framework.response import Response
from django.conf import settings
from django.utils import timezone
from django.core.files import File

# from .models import Match, MatchStream  # uncomment in your project


def get_streaming_config():
    # return getattr(settings, "STREAMING", {
    #     "RTMP_BASE": "rtmp://192.168.29.202:1935",
    #     "HLS_BASE": "http://192.168.29.202:8888",
    #     "MEDIAMTX_API": "http://192.168.29.202:9997",
    #     "RECORDINGS_DIR": r"C:\mediamtx\recordings",  # ← Windows path, match MediaMTX recordPath
    #     "IS_CDN": False,
    # })

    return getattr(settings, "STREAMING", {
        "RTMP_BASE": "rtmp://omanlive.online:1935",
        # "HLS_BASE": "http://omanlive.online:8888",
        "HLS_BASE": "https://omanlive.online/hls",

        "MEDIAMTX_API": "http://127.0.0.1:9997",
        "RECORDINGS_DIR": "/var/www/html/HOTSTAR/school/media/recordings",
        "IS_CDN": False,
    })


class StreamAPIView(APIView):
    """
    POST /api/v1/stream/start/<match_id>/  → get RTMP/WHIP path to push
    GET  /api/v1/stream/watch/<match_id>/  → get HLS URL to watch
    GET  /api/v1/stream/status/<match_id>/ → is stream live?
    POST /api/v1/stream/stop/<match_id>/   → end stream
    """

    # ── POST router ───────────────────────────
    def post(self, request, match_id, action="start"):
        if action == "stop":
            return self._stop(request, match_id)
        return self._start(request, match_id)

    # ── GET router ────────────────────────────
    # def get(self, request, match_id, action="watch"):
    #     if action == "status":
    #         return self._status(request, match_id)
    #     return self._watch(request, match_id)

    def get(self, request, match_id, action="watch"):
        if action == "status":
            return self._status(request, match_id)
        if action == "highlight":
            return self._highlight(request, match_id)
        return self._watch(request, match_id)


    # ══════════════════════════════════════════
    #  START stream (broadcaster)
    # ══════════════════════════════════════════
    def _start(self, request, match_id):
        cfg = get_streaming_config()
        try:
            match = Match.objects.get(id=match_id)

            # stream_key = "match_<id>" ONLY — same name the phone uses
            # for WHIP publish (see LiveBroadcast.jsx: streamPath = `match_${matchId}`)
            stream, created = MatchStream.objects.get_or_create(
                match=match,
                defaults={
                    "stream_key": f"match_{match_id}",
                    "status": "idle",
                }
            )

            # If an old row exists with a stale random-suffix key, fix it
            correct_key = f"match_{match_id}"
            if stream.stream_key != correct_key:
                stream.stream_key = correct_key

            stream_path = stream.stream_key  # "match_3" — NOT "live/match_3_xxxx"

            hls_url = f"{cfg['HLS_BASE']}/{stream_path}/index.m3u8"

            stream.rtmp_url = f"{cfg['RTMP_BASE']}/{stream_path}"
            stream.hls_url = hls_url
            stream.status = "live"
            stream.started_at = timezone.now()
            stream.save()

            match.status = "live"
            match.save(update_fields=["status"])

            return Response({
                "status": {"code": 200, "response": "success"},
                "data": {
                    "stream_key": stream.stream_key,
                    "rtmp_url": stream.rtmp_url,
                    "hls_url": stream.hls_url,
                    "match_id": match_id,
                    "is_cdn": cfg["IS_CDN"],
                }
            })
        except Match.DoesNotExist:
            return Response({"message": "Match not found"}, status=404)
        except Exception as e:
            return Response({"message": str(e)}, status=400)

    # ══════════════════════════════════════════
    #  STOP stream (broadcaster)
    # ══════════════════════════════════════════
    def _stop(self, request, match_id):
        try:
            stream = MatchStream.objects.get(match_id=match_id)
        except MatchStream.DoesNotExist:
            return Response({"message": "No stream found for this match"}, status=404)

        stream.status = "ended"
        stream.ended_at = timezone.now()

        # Where MediaMTX actually writes recordings (raw recordPath from mediamtx.yml)
        # mediamtx_rec_dir = r"C:\mediamtx\recordings"
        mediamtx_rec_dir = "/var/www/html/HOTSTAR/school/media/recordings"

        found = False
        if os.path.isdir(mediamtx_rec_dir):
            for root, dirs, files in os.walk(mediamtx_rec_dir):
                for f in files:
                    if stream.stream_key in f:
                        full_path = os.path.join(root, f)
                        with open(full_path, "rb") as fh:
                            # Saves into MEDIA_ROOT/recordings/match_<id>/<f>
                            # matching your model's upload_to function
                            stream.recording.save(f, File(fh), save=False)
                        found = True
                        break
                if found:
                    break
        else:
            print(f"⚠️ Recordings directory not found: {mediamtx_rec_dir}")

        if not found:
            print(f"⚠️ No recording file found for '{stream.stream_key}' in {mediamtx_rec_dir}")

        stream.save()

        return Response({
            "status": {"code": 200, "response": "success"},
            "message": "Stream stopped",
            "data": {
                "recording_url": stream.get_recording_url() if hasattr(stream, "get_recording_url") else None,
            },
        })

    # ══════════════════════════════════════════
    #  STATUS (poll from anywhere)
    # ══════════════════════════════════════════
    def _status(self, request, match_id):
        cfg = get_streaming_config()
        try:
            stream = MatchStream.objects.get(match_id=match_id)
            is_live = False

            # Check MediaMTX API if the path is actually publishing
            try:
                r = requests.get(
                    f"{cfg['MEDIAMTX_API']}/v3/paths/get/{stream.stream_key}",
                    timeout=2
                )
                if r.status_code == 200:
                    data = r.json()
                    is_live = data.get("ready", False)
            except Exception:
                is_live = (stream.status == "live")

            return Response({
                "status": {"code": 200, "response": "success"},
                "data": {
                    "is_live": is_live,
                    "hls_url": stream.hls_url if is_live else None,
                    "viewer_count": stream.viewer_count,
                    "started_at": stream.started_at,
                    "recording_url": getattr(stream, "recording_url", None),
                }
            })
        except MatchStream.DoesNotExist:
            return Response({
                "status": {"code": 200, "response": "success"},
                "data": {"is_live": False}
            })

    # ══════════════════════════════════════════
    #  WATCH (viewer requests playback URL)
    # ══════════════════════════════════════════
    def _watch(self, request, match_id):
        try:
            stream = MatchStream.objects.get(match_id=match_id)
            # Increment viewer count
            MatchStream.objects.filter(id=stream.id).update(
                viewer_count=stream.viewer_count + 1
            )
            stream.refresh_from_db()
            return Response({
                "status": {"code": 200, "response": "success"},
                "data": {
                    "hls_url": stream.hls_url,
                    "status": stream.status,          # VideoPlayer.jsx checks d.status === "live"
                    "is_live": stream.status == "live",
                    "recording_url": getattr(stream, "recording_url", None),
                    "viewer_count": stream.viewer_count,
                }
            })
        except MatchStream.DoesNotExist:
            return Response({"message": "No stream for this match"}, status=404)



   
    def _highlight(self, request, match_id):
        try:
            stream = MatchStream.objects.get(match_id=match_id)
        except MatchStream.DoesNotExist:
            return Response({"message": "No recording found for this match"}, status=404)
 
        # stream.stream_key is already "match_6" etc — this is the exact
        # folder name MediaMTX creates under recordings/ (from %path in
        # recordPath). Dynamic — works for any match, nothing hardcoded.
        folder = os.path.join(settings.MEDIA_ROOT, "recordings", stream.stream_key)
 
        if not os.path.isdir(folder):
            return Response({
                "status": {"code": 202, "response": "pending"},
                "message": f"No recordings folder yet for '{stream.stream_key}'",
                "data": {"recording_url": None},
            }, status=404)
 
        VIDEO_EXT = (".mp4", ".m4s", ".ts", ".mkv")
        latest_name, latest_mtime = None, None
        for f in os.listdir(folder):
            full = os.path.join(folder, f)
            if os.path.isfile(full) and f.lower().endswith(VIDEO_EXT):
                mtime = os.path.getmtime(full)
                if latest_mtime is None or mtime > latest_mtime:
                    latest_mtime, latest_name = mtime, f
 
        if not latest_name:
            return Response({
                "status": {"code": 202, "response": "pending"},
                "message": f"Folder exists but no recording file yet for '{stream.stream_key}'",
                "data": {"recording_url": None},
            }, status=404)
 
        # Build the URL exactly like Django would for any MEDIA_URL file:
        # MEDIA_URL + "recordings/<stream_key>/<filename>"
        relative_url = f"{settings.MEDIA_URL}recordings/{stream.stream_key}/{latest_name}"
        recording_url = request.build_absolute_uri(relative_url)
 
        return Response({
            "status": {"code": 200, "response": "success"},
            "data": {
                "match_id": match_id,
                "stream_key": stream.stream_key,
                "recording_url": recording_url,
                "recorded_at": stream.ended_at,
            }
        })
 