from django.shortcuts import get_object_or_404, redirect, render
from rest_framework import generics
from django.contrib.auth.models import User
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.permissions import IsAuthenticated
from django.contrib.auth.hashers import check_password
import cloudinary.uploader
from cloudinary.utils import cloudinary_url

from django.db.models import Q
from datetime import datetime

from .messages import sendOTP, sendSms

from .helpers import generate_otp

from .models import UserProfile
from .serializers import UserProfileSerializer

# Create your views here.


#### AUTHENTICATION *********************************************************************************************************

class AppUserRegistration(APIView):

    def post(self, request):
        data = request.data
        if not data:
            return Response({"error":"Please provide all informations!"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            if "first_name" in data: first_name = data["first_name"]
            if "last_name" in data: last_name = data["last_name"]
            if "phonenumber" in data: phonenumber = data["phonenumber"]
            if "email" in data: email = data["email"]
            if "password" in data: password = data["password"]

            if not first_name or not last_name or not email or not password:
                return Response({"error":"Please provide all informations!"}, status=status.HTTP_400_BAD_REQUEST)
            
            allusers = User.objects.filter(email=email).exists() or UserProfile.objects.filter(email=email).exists()
            if allusers:
                return Response({"error":"UserExists"}, status.HTTP_400_BAD_REQUEST)
            
            
            # create user
            randomId = generate_otp(length=4)
            user = User.objects.create_user(
                email=email,
                username=f"{first_name}.{last_name}.{randomId}",
                password=password,
                first_name=first_name,
                last_name=last_name
            )
            profile = UserProfile.objects.create(
                user = user, first_name=first_name, last_name=last_name,
                email=email, phonenumber=phonenumber
            )
            profile.save()

            # return token
            try:
                refresh = RefreshToken.for_user(user)
                data = {
                    "refresh": str(refresh),
                    "access": str(refresh.access_token),
                }
            except Exception as e:
                print(f"Token generation failed: {str(e)}")
                return Response({"error": f"Token generation failed: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


            return Response(data, status=status.HTTP_200_OK)

        except Exception as e:
            print(f"{e}")
            return Response({"error":f"Error message: {e}"}, status=status.HTTP_400_BAD_REQUEST)
            
        
class AppSignUpOtp(APIView):

    def post(self, request):
        data = request.data
        try:
            phone = data.get("phonenumber")
            email = data.get("email")
            otp = data.get("otp")

            if not phone or not email or not otp:
                return Response(status=400)
            
            allusers = User.objects.filter(email=email).exists() or UserProfile.objects.filter(email=email).exists()
            if allusers:
                return Response({"error":"UserExists"}, status.HTTP_400_BAD_REQUEST)
            
            sendOTP(data["otp"], data["phonenumber"])
            return Response(status=200)
            
        except Exception as e:
            print(f"{e}")
            return Response({"error":f"Error message: {e}"}, status=400)
        
# login
class AppUserLogin(APIView):

    def post(self, request):
        data = request.data
        if not data:
            return Response({"error":"Please provide all informations!"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            if "email" in data: email = data["email"]
            if "password" in data: password = data["password"]

            if not email or not password:
                return Response({"error":"Please provide all informations!"}, status=status.HTTP_400_BAD_REQUEST)
            
            # get user
            try:
                user = User.objects.get(email=email)
                profile = UserProfile.objects.get(user=user)
            except User.DoesNotExist:
                return Response({"error":"NoUser"}, status.HTTP_400_BAD_REQUEST)
            
            # return token
            try:
                refresh = RefreshToken.for_user(user)
                data = {
                    "refresh": str(refresh),
                    "access": str(refresh.access_token),
                    "first_name":profile.first_name,
                    "last_name":profile.last_name,
                    "phonenumber":profile.phonenumber,
                }
            except Exception as e:
                print(f"Token generation failed: {str(e)}")
                return Response({"error": f"Token generation failed: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


            return Response(data, status=status.HTTP_200_OK)

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

# edit profile
class AppEditProfile(APIView):

    permission_classes = [IsAuthenticated]

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

        if not "authemail" in data:
            return Response({"error":"Please provide all informations!"}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            user = User.objects.get(email=data["authemail"])
            profile = UserProfile.objects.get(user=user)

            profile.first_name = data["first_name"]
            profile.last_name = data["last_name"]
            profile.phonenumber = data["phonenumber"]
            profile.save()
            return Response(status=status.HTTP_200_OK)
        
        except User.DoesNotExist:
            return Response({"error":"NoUser"}, status.HTTP_400_BAD_REQUEST)


# reset password
class AppResetPassword(APIView):

    permission_classes = [IsAuthenticated]

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

        if not "authemail" in data:
            return Response({"error":"Please provide all informations!"}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            user = User.objects.get(email=data["authemail"])
            profile = UserProfile.objects.get(user=user)
            
            currentpassword = data["currentpassword"]
            newpassword = data["password"]
            if currentpassword and newpassword:
                if check_password(currentpassword, user.password):
                    user.set_password(newpassword)
                    sendSms(profile.phonenumber, f"Hi {profile.first_name}, \nYour password has been updated successfully! Please use your new password next time you login.")
                    return Response(status=status.HTTP_200_OK)
                
                return Response({"error":"IncorrectData"}, status.HTTP_400_BAD_REQUEST)
        
        except User.DoesNotExist:
            return Response({"error":"NoUser"}, status.HTTP_400_BAD_REQUEST)

# upload profile image
class AppUpdateProfileimage(APIView):
    def post(self, request, *args, **kwargs):
        file = request.FILES.get("file")
        email = request.data["authemail"]
        if not file:
            return Response({"error": "No file uploaded"}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            user = User.objects.get(email=email)
            profile = UserProfile.objects.get(user=user)
        except User.DoesNotExist:
            return Response({"error":"NoUser"}, status.HTTP_400_BAD_REQUEST)
        
        try:
            result = cloudinary.uploader.upload(file, folder="profileimages" )
            profile.profileimage = result.get("secure_url")
            profile.save()
            return Response({"url": result.get("secure_url")}, status=status.HTTP_201_CREATED)
        except Exception as e:
            print(e)
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)














