import json
from datetime import date, datetime
from django.contrib.auth.models import User
from django.utils import timezone
from rest_framework import response
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import Serializer
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import Http404
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.contrib.auth.password_validation import validate_password
from .serializers import UserSerializer, SignupSerializer, UserInfoSerializer, PasswordUpdateSerializer
from core.models import Course, Instructor, UserInformation, UserApproval, UserCourse, UserLoginSession
from django.core.mail import send_mail, EmailMultiAlternatives
from django.contrib.auth.hashers import check_password
from django_otp import devices_for_user
from django_otp.plugins.otp_totp.models import TOTPDevice
from django.db.models import Q, Value
from django.db.models.functions import Concat
import pyotp
import base64
from django.conf import settings
import os
from core.permissions import IsAdmin, IsOrgAdmin, IsInstructor, IsStudent, IsGuardian

from django.contrib.auth.tokens import default_token_generator as token_generator
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes
from django.urls import reverse
from django.contrib.sites.shortcuts import get_current_site
from rest_framework.views import APIView

def get_user(username):
    try:
        try:
            user = User.objects.get(username=username)
        except:
            user = User.objects.get(email=username)

        return user
    except User.DoesNotExist:
        return None

def get_user_by_email(email):
    try:
        return User.objects.get(email=email)
    except User.DoesNotExist:
        return None


def get_user_totp_device(self, user, confirmed=None):
    """
    Gets user's time based one time password devices
    """
    devices = devices_for_user(user, confirmed=confirmed)
    for device in devices:
        if isinstance(device, TOTPDevice):
            return device

VALID_ROLES = ['Admin', 'OrgAdmin', 'Instructor', 'Student', 'Guardian']

def normalize_role(role):
    """Normalize role to match expected values with proper capitalization."""
    if not role:
        return None

    formatted_role = role.strip().lower().capitalize()

    # Special handling for OrgAdmin
    if formatted_role == 'Orgadmin':
        return 'OrgAdmin'

    return formatted_role if formatted_role in VALID_ROLES else None


# Create your views here.
class UserAPIView(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = UserSerializer

    def get_object(self):
        try:
            return self.request.user
        except:
            Http404

    def get(self, request):
        user = self.get_object()
        serializer = UserSerializer(user)

        return Response(serializer.data, status=status.HTTP_200_OK)

class loginView(APIView):
    permission_classes = []

class UserApprovedAPIView(APIView):
    permission_classes = []

    def post(self, request):
        # Get the identifier (username or email) from the request data
        username_email = request.data.get('username_email', None)
        data = {} #initiate empty data
        is_approved = False

        if username_email:
            # Try to get the user by username or email
            user = get_user(username_email) or get_user_by_email(username_email)

            if user:
                try:
                    approval = UserApproval.objects.get(user=user)
                    approval_status = approval.approval_status

                    if approval_status == 'Approved':
                        is_approved = True
                    else:
                        is_approved = False

                    response_status = status.HTTP_200_OK
                except UserApproval.DoesNotExist:
                    response_status = status.HTTP_404_NOT_FOUND
                    data = {'error': 'User approval record not found'}
            else:
                response_status = status.HTTP_404_NOT_FOUND
                data = {'error': 'User not found. Please check the username or email.'}
        else:
            response_status = status.HTTP_400_BAD_REQUEST  # Missing identifier
            data = {'error': 'Identifier (username or email) is required'}

        data.update({'is_approved': is_approved})
        return Response(data, status=response_status)



class SignupAPIView(APIView):
    permission_classes = []

    def post(self, request, *args, **kwargs):
        # Signup logic for creating a new user
        first_name = request.data.get('first_name', None)
        last_name = request.data.get('last_name', None)
        role = request.data.get('role', None)
        username = request.data.get('username', None)
        phone = request.data.get('phone', None)
        user_email = request.data.get('email', None)
        password = request.data.get('password', None)
        confirm_password = request.data.get('confirm_password', None)
        is_organization = request.data.get('is_organization', None)
        referal_code = request.data.get('referal_code', None)

        # Validate and normalize role (you can reuse your existing `normalize_role()` function)
        role = normalize_role(role)
        if not role:
            return Response({'error': 'Invalid role provided.'}, status=status.HTTP_400_BAD_REQUEST)
        if not first_name or not last_name or not username or not phone or not user_email or not password or not confirm_password:
            return Response({'error': 'All fields are required.'}, status=status.HTTP_400_BAD_REQUEST)

        # Ensure passwords match before proceeding
        if password != confirm_password:
            return Response({'error': 'Password and confirm password did not match.'}, status=status.HTTP_400_BAD_REQUEST)

        if User.objects.filter(email=user_email).exists():
            return Response({'error': 'A user with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)

        # Create user
        user = User.objects.create_user(username=username, email=user_email, password=password, first_name=first_name, last_name=last_name)

        # Assign role and other info to user
        user_information, _ = UserInformation.objects.get_or_create(user=user)
        user_information.role = role
        user_information.is_organization = is_organization
        user_information.referal_code = referal_code
        user_information.profile_lock = 'completed' if role == 'Instructor' else 'incomplete'
        user_information.save()

        # Set approval status based on role
        approval_status = 'Approved' if role == 'Student' else 'Not Approved'
        user_approval, _ = UserApproval.objects.get_or_create(user=user)
        user_approval.approval_status = approval_status
        user_approval.save()

        # Create Instructor if role is 'Instructor'
        if role == 'Instructor':
            instructor, _ = Instructor.objects.get_or_create(contact_email=user_email, user=user, defaults={'name': f"{first_name} {last_name}"})
            
            # Generate email verification token and URL
            uid = urlsafe_base64_encode(force_bytes(user.pk))
            token = token_generator.make_token(user)
            # frontend_base_url = "http://localhost:5173/verify-email"  # Replace with your production React domain
            frontend_base_url = "https://eduva.net/verify-email"
            verification_url = f"{frontend_base_url}/{uid}/{token}"


            # # Send verification email
            # send_mail(
            #     'Verify your email for Eduva',
            #     f'Please click the following link to verify your email: {verification_url}',
            #     f"Eduva Team <{settings.EMAIL_HOST_USER}>",
            #     [user_email],
            #     fail_silently=False,
            # )
             # Create the email body with an HTML template
            # Create the HTML message directly
            email_subject = 'Verify your email for Eduva'
            email_message = f"""
            <html>
            <body>
                <p>Dear {user.first_name},</p>
                <p>Thank you for registering with Eduva! Please verify your email address by clicking the link below:</p>
                <p><a href="{verification_url}" target="_blank">Click here to verify your email</a></p>
                <p>If you did not sign up for Eduva, please ignore this email.</p>
                <p>Best regards,<br>Eduva Team</p>
            </body>
            </html>
            """

            # Send the email
            send_mail(
                email_subject,
                '',  # Plain text content (can be left empty for HTML emails)
                f"Eduva Team <{settings.EMAIL_HOST_USER}>",
                [user.email],
                fail_silently=False,
                html_message=email_message,  # This will be the HTML content
            )

            msg = "Account created successfully! Please check your email to verify your account."
        else:
            msg = "Account created successfully!"

        return Response({'success': f'{role} {msg}'}, status=status.HTTP_201_CREATED)

    
class SignupVerifyAPIView(APIView):
    permission_classes = []
    def get(self, request, uidb64, token, *args, **kwargs):
        # Email verification logic
        try:
            # Decode user ID from URL
            uid = urlsafe_base64_decode(uidb64).decode()
            user = User.objects.get(pk=uid)

            # Check token validity
            if token_generator.check_token(user, token):
                # Update approval status after successful email verification
                user_approval = UserApproval.objects.get(user=user)
                user_approval.approval_status = 'Approved'
                user_approval.save()

                user_information = UserInformation.objects.get(user=user)
                user_information.profile_lock = False
                user_information.save()

                return Response(
                    {'success': 'Your email has been successfully verified. You can now log in.'},
                    status=status.HTTP_200_OK
                )
            else:
                return Response(
                    {'error': 'Invalid or expired token.'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        except (TypeError, ValueError, OverflowError, User.DoesNotExist):
            return Response(
                {'error': 'Invalid token or user not found.'},
                status=status.HTTP_400_BAD_REQUEST
            )

            

class UpdatePasswordView(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request, *args, **kwargs):
        serializer = PasswordUpdateSerializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            # Update the password
            user = request.user
            user.set_password(serializer.validated_data['new_password'])
            user.save()

            return Response({'status': True, 'data': None, 'msg': f'Password updated successfully.'}, status=status.HTTP_200_OK)

        msg = []
        errors = serializer.errors
        for key, value in errors.items():
            key = key.replace('_', ' ').capitalize()
            for i in value:
                msg.append(key+': '+i)
        return Response({'status': False, 'data': None, 'msg': msg}, status=status.HTTP_400_BAD_REQUEST)
        


class ProfileAPIView(APIView):
    permission_classes = [IsAuthenticated]
    
    def get(self, request):
        user = self.request.user
        user_information = user.userinformation

        if user_information.role in ['Admin', 'OrgAdmin']:
            try:
                user_id = int(request.data.get('user_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'User id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        if user_information.role not in ['Admin', 'OrgAdmin']:
            user = request.user
            user_information = user.userinformation
            user_id = user.id
        elif user_information.role=='Admin':
            if user_id != user.id:
                try:
                    user = User.objects.get(id=user_id)
                except User.DoesNotExist:
                    return Response({'status': False, 'data': None, 'msg': 'User not found.'}, status=status.HTTP_404_NOT_FOUND)
                
                user_information = user.userinformation
        elif user_information.role=='OrgAdmin':
            if user_id != user.id:
                try:
                    user = User.objects.get(id=user_id)
                except User.DoesNotExist:
                    return Response({'status': False, 'data': None, 'msg': 'User not found.'}, status=status.HTTP_404_NOT_FOUND)
                
                user_information = user.userinformation

                if user_information.is_organization is False:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
                else:
                    if user_information.organization != request.user.userinformation.organization:
                        return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            

        # user_serializer = UserSerializer(user)
        # info_serializer = UserInfoSerializer(user_information)
        profiles =  {
            'user_id': user.id,
            'image': user_information.image.url if user_information.image else None,
            'role': user_information.role,
            'user_name': user.username,
            'first_name': user.first_name,
            'last_name': user.last_name,
            'email': user.email,
            'phone_number': str(user_information.phone_number),
            'country': user_information.location,
            'gender': user_information.gender,
            'dob': user_information.dob,
            'parents_name': user_information.parents_name,
            'pin_code': user_information.pin_code,
            'time_zone': user_information.time_zone,
            'user_completion': user_information.calculate_user_profile_completion(),
        }
        # info_serializer = UserInfoSerializer(user_information)
        return Response({'status': True, 'data': profiles, 'msg': 'User profile fetched.'}, status=status.HTTP_200_OK)

    def put(self, request):
        user = self.request.user
        user_information = user.userinformation
        data = request.data  # Store request.data for easier access

        if user_information.role in ['Admin', 'OrgAdmin']:
            try:
                user_id = int(request.data.get('user_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'User id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        if user_information.role not in ['Admin', 'OrgAdmin']:
            user = request.user
            user_information = user.userinformation
            user_id = user.id
        elif user_information.role=='Admin':
            if user_id != user.id:
                try:
                    user = User.objects.get(id=user_id)
                except User.DoesNotExist:
                    return Response({'status': False, 'data': None, 'msg': 'User not found.'}, status=status.HTTP_404_NOT_FOUND)
                
                user_information = user.userinformation
        elif user_information.role=='OrgAdmin':
            if user_id != user.id:
                try:
                    user = User.objects.get(id=user_id)
                except User.DoesNotExist:
                    return Response({'status': False, 'data': None, 'msg': 'User not found.'}, status=status.HTTP_404_NOT_FOUND)
                
                user_information = user.userinformation

                if user_information.is_organization is False:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
                else:
                    if user_information.organization != request.user.userinformation.organization:
                        return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        


        try:
            # Image Update (separate block for clarity)
            image = data.get('image')
            if image:
                user.userinformation.image = image
                user.userinformation.save()  # Save immediately after image update
            
            # User Fields Update
            user_fields = {
                'first_name': data.get('first_name'),
                'last_name': data.get('last_name'),
                'email': data.get('email'),
            }
            for field, value in user_fields.items():
                if value is not None:  # Check for None *before* setting attribute.
                    setattr(user, field, value)
            user.save()  # Save user once after all user fields are updated

            # User Information Update

            user_info_fields = {
                'phone_number': data.get('phone_number'),
                'location': data.get('country'),
                'gender': data.get('gender'),
                'dob': data.get('dob'),
                # 'parents_name': data.get('parents_name'),
                'pin_code': data.get('pin_code'),
                'time_zone': data.get('time_zone'),
            }

            # Check if userinformation exists. Create if not.
            # user_information = getattr(user, 'userinformation', None)
            # if not user_information:
            #     user_information = UserInformation.objects.create(user=user)

            for field, value in user_info_fields.items():
                if value is not None:
                    setattr(user_information, field, value)
            
            user_information.save()  # Save user information once
            
            serializer = UserInfoSerializer(user_information)
            
            updated_data = {
                'user_id': user.id,
                'image': serializer.data['image'],
                'first_name': user.first_name,
                'last_name': user.last_name,
                'email': user.email,
                'phone_number': serializer.data['phone_number'],
                'location': serializer.data['location'],
                'gender': serializer.data['gender'],
                'dob': serializer.data['dob'],
                'pin_code': serializer.data['pin_code'],
                'time_zone': serializer.data['time_zone'],
            }
            
            return Response({'status': True, 'data': updated_data, "msg": "User profile updated successfully."}, status=status.HTTP_200_OK)

        except Exception as e:
            return Response({'status': False, 'data': None, "msg": e}, status=status.HTTP_400_BAD_REQUEST)



        
class AuthorizedUserAPIView(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor | IsStudent | IsGuardian]

    def get(self, request):
        user = request.user
        user_information = user.userinformation

        if not user_information:
            return Response({"error": "User role not found"}, status=404)

        # Map roles to response keys
        role_mapping = {
            "Admin": "authorize_admin",
            "OrgAdmin": "authorize_org_admin",
            "Instructor": "authorize_instructor",
            "Student": "authorize_student",
            "Guardian": "authorize_guardian",
        }

        user_role_key = role_mapping.get(user_information.role)  # Get role key

        if not user_role_key:
            return Response({"error": "Role not recognized"}, status=400)

        return Response({user_role_key: True})

class UserRequestAPIView(APIView):
    permission_classes = [IsAuthenticated, IsAdmin]

    def get(self, request):
        approval_status = request.GET.get('approval_status', '')
        filter_role = request.GET.get('role', '')
        search = request.GET.get('search', '')

        user = self.request.user
        user_information = user.userinformation
        
        data = []

        if approval_status in ['Approved', 'Not Approved', 'Pending']:
        
            user_approvals = UserApproval.objects.filter(
                Q(user__userinformation__role='Instructor') & 
                Q(approval_status=approval_status) & 
                Q(user__is_superuser=False)).annotate(
                    full_name=Concat('user__first_name', Value(' '), 'user__last_name')
                ).filter(
                    Q(full_name__trigram_word_similar=search) |
                    Q(full_name__icontains=search) |
                    Q(user__email__icontains=search)
                )
        elif approval_status == '':
            user_approvals = UserApproval.objects.filter(
                Q(user__userinformation__role='Instructor') &  
                Q(user__is_superuser=False)).annotate(
                    full_name=Concat('user__first_name', Value(' '), 'user__last_name')
                ).filter(
                    Q(full_name__trigram_word_similar=search) |
                    Q(full_name__icontains=search) |
                    Q(user__email__icontains=search)
                )
        else:
            return Response({'status': False, 'data': None, 'msg': 'Invalid approval status.'}, status=status.HTTP_400_BAD_REQUEST)

        for user_approval in user_approvals:
            user = user_approval.user
            data.append({
                'request_id': user_approval.id,
                'username': user.username,
                'request_name': f'{user.first_name} {user.last_name}',
                'contact_email': user.email,
                'role': user_approval.user.userinformation.role,
                'is_organization': user.userinformation.is_organization,
                'approval_status': user_approval.approval_status,
                'created_at': user_approval.created_at
            })

        return Response({'status': True, 'data': data, 'msg': 'Fetched user approval request list.'}, status=status.HTTP_200_OK)

    def put(self, request):
        id = request.data.get('request_id', None)
        
        approval_status = request.data.get('approval_status', None)
        organization_id = request.data.get('organization_id', None)

        if approval_status not in ['Approved', 'Not Approved', 'Pending', 'Rejected']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid status.'}, status=status.HTTP_400_BAD_REQUEST)

        user = self.request.user

        data = {}
        user_approval, _ = UserApproval.objects.get_or_create(id=id)
        
        if approval_status == 'Rejected':
            requested_user = user_approval.user
            User.objects.get(id=requested_user.id).delete()

            return Response({'status': True, 'data': None, 'msg': 'User approval request rejected.'}, status=status.HTTP_200_OK)

        is_organization = user_approval.user.userinformation.is_organization
        
        if is_organization:
            user_approval.user.userinformation.organization = organization_id
            user_approval.user.userinformation.save() 

        user_approval.approval_status = approval_status
        user_approval.save()

        instructor = user_approval.user.instructor
        instructor.status = approval_status
        instructor.save()

        data['success'] = 'User approved. User can login now.'
        data['user_id'] = user_approval.user.id
        data['user_approval'] = user_approval.approval_status
        data['organization_id'] = organization_id

        user_email = user_approval.user.email

        # Notify user sending email
        # if approval_status == 'Approved':
        #     send_mail(
        #         'Approval Status',
        #         'Congratulations!'
        #         + '\n'
        #         + 'Your request to join LMS has been '
        #         + approval_status
        #         + '\n'
        #         + 'Please login to LMS using ****'
        #         + '\n \n'
        #         + 'Best Regards'
        #         + '\n'
        #         + 'QA Tek Admin',
        #         {settings.EMAIL_HOST_USER},
        #         [user_email],
        #         fail_silently=False
        #     )
        # else:
        #     send_mail(
        #         'Approval Status',
        #         'Your request to join LMS has been '
        #         + approval_status
        #         + '\n \n'
        #         + 'Best Regards'
        #         + '\n'
        #         + 'QA Tek Admin',
        #         {settings.EMAIL_HOST_USER},
        #         [user_email],
        #         fail_silently=False
        #     )

        # Delete user if the user is rejected

        response_status = status.HTTP_200_OK

        return Response({'status': True, 'data': data, 'msg': 'User approval request updated.'}, status=response_status)


class TOTPCreateView(APIView):
    permission_classes = []

    def post(self, request):
        username = request.data['username']
        user = get_user(username)
        user_email = user.email
        user_device = request.META.get('HTTP_USER_AGENT', '')
        time = datetime.now().strftime("%H:%M:%S")
        if not user.is_anonymous:
            device = get_user_totp_device(self, user)
            if not device:
                device = user.totpdevice_set.create(confirmed=False)
                secret_key = device.bin_key
                totp = pyotp.TOTP(base64.b32encode(secret_key))
                one_time_password = totp.now()
                send_mail(
                    'Verification needed',
                    'Please confirm your sign in request'
                    + '\n \n'
                    + 'We have detected an account sign-in request from a device we do not recognize.'
                    + '\n \n'
                    + 'Account: ' + username
                    + '\n'
                    + 'Time: ' + time
                    + '\n'
                    + 'Device: ' + user_device
                    + '\n'
                    + 'To verify your account is safe, please use the following code to enable your new device — it will expire in 30 seconds.'
                    + '\n'
                    + 'Verification code: ' + one_time_password
                    + '\n \n'
                    + 'Best Regards'
                    + '\n'
                    + 'QA Tek Admin',
                    'qatek.lms@gmail.com',
                    [user_email],
                    fail_silently=False
                )
            elif device.confirmed == False:
                secret_key = device.bin_key
                totp = pyotp.TOTP(base64.b32encode(secret_key))
                one_time_password = totp.now()
                send_mail(
                    'Verification needed',
                    'Please confirm your sign in request'
                    + '\n \n'
                    + 'We have detected an account sign-in request from a device we do not recognize.'
                    + '\n \n'
                    + 'Account: ' + username
                    + '\n'
                    + 'Time: ' + time
                    + '\n'
                    + 'Device: ' + user_device
                    + '\n'
                    + 'To verify your account is safe, please use the following code to enable your new device — it will expire in 30 seconds.'
                    + '\n'
                    + 'Verification code: ' + one_time_password
                    + '\n \n'
                    + 'Best Regards'
                    + '\n'
                    + 'QA Tek Admin',
                    'qatek.lms@gmail.com',
                    [user_email],
                    fail_silently=False
                )
            url = device.config_url

            response_status = status.HTTP_201_CREATED
        else:
            url = {}
            response_status = status.HTTP_401_UNAUTHORIZED

        return Response(url, status=response_status)


class TOTPVerifyView(APIView):
    permission_classes = []

    def post(self, request):
        username = request.data['username']
        token = request.data['token']

        user = get_user(username)
        device = get_user_totp_device(self, user)

        if not user.is_anonymous:
            device_registered = device.verify_token(token)
            if device_registered:
                if not device.confirmed:
                    device.confirmed = True
                    device.save()
                data = True
                response_status = status.HTTP_200_OK
            else:
                data = {'error': 'Verification code is not valid.'}
                response_status = status.HTTP_400_BAD_REQUEST
        else:
            data = False
            response_status = status.HTTP_401_UNAUTHORIZED

        return Response(data, status=response_status)


class TOTPAuthenticatedView(APIView):
    permission_classes = []

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')

        user = get_user(username)
        if user:
            user_password = user.password

            device = get_user_totp_device(self, user)
            if check_password(password, user_password):
                ########### Commenting out to temporarily turn off 2FA #########

                # if not user.is_anonymous:
                #     if device:
                #         if device.confirmed == False:
                #             device_not_recognized = True
                #         else:
                #             device_not_recognized = False
                #
                #         data = {'device_not_recognized': device_not_recognized}
                #         response_status = status.HTTP_200_OK
                #     else:
                #         data = {'not_found': 'Device not found'}
                #         response_status = status.HTTP_404_NOT_FOUND
                # else:
                #     device_not_recognized = True
                #     data = {'device_not_recognized': device_not_recognized}
                #     response_status = status.HTTP_401_UNAUTHORIZED

                ################# End temporary turn off 2FA ###################

                # Below part is temporary
                data = {'device_not_recognized': False}
                response_status = status.HTTP_200_OK
            else:
                data = {'password': 'Usernamae or password incorrect'}
                response_status = status.HTTP_400_BAD_REQUEST
        else:
            data = {'password': 'Usernamae or password incorrect'}
            response_status = status.HTTP_400_BAD_REQUEST

        return Response(data, status=response_status)


class UserSessionView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = self.request.user
        user_information = UserInformation.objects.get(user=user.id)

        data = []
        if not user.is_anonymous:
            if user_information.role == 'Admin':
                user_login_sessions = UserLoginSession.objects.filter(
                    user__userinformation__role='Student')
                device = 1
                for user_login_session in user_login_sessions:
                    data.append({
                        'device_count': device,
                        'address': user_login_session.address,
                        'login_time': user_login_session.login_time.strftime("%d %B, %Y %H:%M"),
                        'logout_time': user_login_session.logout_time.strftime("%d %B, %Y %H:%M"),
                        'status': user_login_session.is_logged_in
                    })
                    device += 1
                response_status = status.HTTP_200_OK
            else:
                response_status = status.HTTP_401_UNAUTHORIZED
        else:
            response_status = status.HTTP_401_UNAUTHORIZED

        return Response(data, status=response_status)

    def post(self, request):
        is_logged_in = request.data['is_logged_in']
        address = request.data['address']
        user = self.request.user
        user_device = request.META.get('HTTP_USER_AGENT', '')
        if is_logged_in == "isLoggedIn" or is_logged_in:
            is_logged_in = True
        else:
            is_logged_in = False
        if not user.is_anonymous:
            if not UserLoginSession.objects.filter(user=user, device=user_device).exists():
                UserLoginSession.objects.create(
                    user=user,
                    address=address,
                    device=user_device,
                    is_logged_in=is_logged_in
                )
                response_status = status.HTTP_201_CREATED
            else:
                user_login_session = UserLoginSession.objects.get(
                    user=user, device=user_device)
                # user_login_session.user = user
                # user_login_session.device = user_device
                if is_logged_in:
                    user_login_session.login_time = timezone.now()
                    user_login_session.address = address  # entry location only for login
                else:
                    user_login_session.logout_time = timezone.now()
                    user_login_session.token_lifespan = 0

                user_login_session.is_logged_in = is_logged_in

                user_login_session.save()

                response_status = status.HTTP_200_OK
        else:
            response_status = status.HTTP_401_UNAUTHORIZED

        return Response(status=response_status)


class UsernameAPIView(APIView):
    permission_classes = []

    def get(self, request):
        username = request.GET.get('username')

        try:
            user = User.objects.get(username=username)
            data = {'username': user.username}
            return Response(data, status=status.HTTP_200_OK)
        except:
            user = User.objects.get(email=username)
            data = {'username': user.username}
            return Response(data, status=status.HTTP_200_OK)


class UserLoggedInView(APIView):
    permission_classes = []

    def get(self, request):
        username = request.GET.get('username')

        user = get_user(username)
        if user:
            logged_in_device_count = UserLoginSession.objects.filter(
                user=user.id, is_logged_in=True).count()

            data = {
                'logged_in_device_count': logged_in_device_count
            }

            return Response(data, status=status.HTTP_200_OK)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)