میخوام این کد جوری تغییر کنه که اگر طرف با این کد ملی ثبت نام کرده بود و میخواست با یه شماره موبایل جدید با همون کد ملی بیاد ثبت نام کنه بهش ارور بده که با شماره تلفن دیگه ای ثبت نام کرده و از ثبت نام جلوگیری کنه

from django.contrib.auth import get_user_model
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from app_account.models import CustomUser
from app_account.serializers import UserSerializer, RequestOTPSerializer, VerifyOtpRequestSerializer, ObtainTokenSerializer
from rest_framework.decorators import action
import random
import string
from django.core.cache import cache
from .msg_sender import send_otp
from datetime import datetime, time, timedelta
from .models import DeviceFingerprint

# region ==> OTP

def get_difference_secound():
    # گرفتن زمان فعلی
    now = datetime.now()

    # تعیین زمان نیمه‌شب (ساعت 12 شب)
    midnight = datetime.combine(now.date(), time(0, 0))

    # اگر زمان فعلی بعد از نیمه‌شب است (در روز بعد) زمان نیمه‌شب روز بعد را بگیرید
    if now > midnight:
        midnight = datetime.combine(now.date() + timedelta(days=1), time(0, 0))

    # محاسبه اختلاف زمان
    difference = midnight - now
    sec_difference = int(difference.total_seconds()//1)

    return sec_difference - 10

def set_data_dic(data):

    if isinstance(data, dict):
        body_data = data
    else:
        body_data = data.dict()

    return body_data

class OTPViewSet(viewsets.ViewSet):

    @action(detail=False, methods=['post'])
    def request_otp(self, request):

        body_data = set_data_dic(request.data)

        serializer = RequestOTPSerializer(data=body_data)
        if serializer.is_valid():
            data = serializer.validated_data
            otp = self._generate_otp()
            
            # بررسی و به‌روزرسانی شمارنده در کش
            counter_otp = cache.get(f"otp_{data['phone_num']}_count")
            if counter_otp is None:
                cache.set(f"otp_{data['phone_num']}_count", 1, timeout=get_difference_secound())
            elif counter_otp is not None:
                if counter_otp <= 500:
                    cache.set(f"otp_{data['phone_num']}_count", counter_otp+1, timeout=get_difference_secound())
                else:
                    return Response({
                        'status': 'LIMIT_REACHED',
                        'message': 'شما به محدودیت تعداد کد در امروز رسیده‌اید. لطفاً فردا دوباره تلاش کنید.',
                        'suggestion': 'در صورت نیاز مبرم به دریافت کد، با پشتیبانی تماس بگیرید.',
                        'phone_num': data['phone_num']
                    }, status=status.HTTP_429_TOO_MANY_REQUESTS)
            
            # ذخیره و ارسال OTP
            cache.set(f"otp_{data['phone_num']}", otp, timeout=120)
            # send_otp(phone_number=data['phone_num'], password=otp)
            print(data['phone_num'], otp)
            
            return Response({
                'status': 'OTP_SENT',
                'message': 'کد تأیید با موفقیت ارسال شد.',
                'phone_num': data['phone_num']
            }, status=status.HTTP_200_OK)

        # نمایش خطاهای ولیدیشن سریالایزر
        return Response({
            'status': 'BAD_REQUEST',
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=False, methods=['post'])
    def verify_otp(self, request):
        
        body_data = set_data_dic(request.data)

        # فرض کنید فینگرپرینت از درخواست دریافت شود

        serializer = VerifyOtpRequestSerializer(data=body_data)
        if serializer.is_valid():
            data = serializer.validated_data
            cached_otp = cache.get(f"otp_{data['phone_num']}")

            if cached_otp and cached_otp == data['password']:
                user, created = self._get_or_create_user(data['national_id'])

                # اعتبارسنجی فینگرپرینت دستگاه
                if data['uniq_id_device'] in user.device_fingerprints.all():
                    token_data = self._generate_tokens_for_user(user, created)
                    
                    return Response({
                        'status': 'SUCCESS',
                        'message': 'کد تأیید صحیح است و شما با موفقیت وارد سیستم شدید.',
                        'user_data': token_data
                    }, status=status.HTTP_200_OK)
                
                elif len(user.device_fingerprints.all()) < 3:
                    fingerprint, created = DeviceFingerprint.objects.get_or_create(
                    user=user,
                    fingerprints=data['uniq_id_device']
                    )
                    if created:
                        fingerprint.save()
                        
                    token_data = self._generate_tokens_for_user(user, created)

                    return Response({
                        'status': 'SUCCESS_WITH_NEW_DEVICE',
                        'message': 'ورود موفق بود و دستگاه جدید اضافه شد.',
                        'user_data': token_data
                    }, status=status.HTTP_200_OK)

                else:
                    return Response({
                        'status': 'DEVICE_LIMIT_REACHED',
                        'message': 'شما به محدودیت دستگاه‌ رسیده‌اید. لطفاً ابتدا دستگاه دیگری را حذف کنید.',
                    }, status=status.HTTP_403_FORBIDDEN)

            return Response({
                'status': 'INVALID_OTP',
                'message': 'کد وارد شده نادرست است. لطفاً مجدد تلاش کنید.',
            }, status=status.HTTP_401_UNAUTHORIZED)

        # گسیل خطاهای ولیدیشن سریالایزر
        return Response({
            'status': 'BAD_REQUEST',
            'message': 'درخواست نامعتبر است. لطفاً خطاها را اصلاح کرده و مجدد تلاش کنید.',
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)

    def _get_or_create_user(self, national_id):
        User = get_user_model()
        user, created = User.objects.get_or_create(username=national_id)
        return user, created

    def _generate_tokens_for_user(self, user, created):
        refresh = RefreshToken.for_user(user)
        return ObtainTokenSerializer({
            'refresh': str(refresh),
            'token': str(refresh.access_token),
            'created': created
        }).data
    
    def _generate_otp(self):
        return ''.join(random.choices(string.digits, k=4))
    
    
class UsersViewSetApiView(viewsets.ModelViewSet):
    queryset = CustomUser.objects.all()
    serializer_class = UserSerializer