import random
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import status, permissions
from django.utils import timezone
from datetime import timedelta
from rest_framework.permissions import IsAuthenticated

from user.models import Verification, User as Customuser
from user.serializers import SendOtpSerializer, VerifyOtpSerializer, UserRegistrationSerializer, UserSerializer

from utility.utility import send_otp_via_whatsapp

def generate_otp():
    return str(random.randint(1000, 9999))

def send_otp_to_mobile(country_code, mobile, otp):
    print(f"Sending OTP {otp} to {country_code}{mobile}")

class SendOtpView(APIView):
    @swagger_auto_schema(
        request_body=SendOtpSerializer,
        responses={200: openapi.Response('OTP Sent', SendOtpSerializer)},
        operation_description="Send OTP to a mobile number via WhatsApp"
    )
    def post(self, request):
        serializer = SendOtpSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        country_code = serializer.validated_data['country_code']
        mobile = serializer.validated_data['mobile']

        now = timezone.now()
        cooldown_time = now - timedelta(seconds=1)

        try:
            verification = Verification.objects.get(country_code=country_code, mobile=mobile)
            if verification.created_at >= cooldown_time:
                return Response({
                    "status": "error",
                    "message": "OTP already sent. Please wait 60 seconds before requesting again."
                }, status=status.HTTP_429_TOO_MANY_REQUESTS)
        except Verification.DoesNotExist:
            verification = None 

        otp = generate_otp()

        try:
            send_otp_via_whatsapp(country_code, mobile, otp)
        except Exception as e:
            return Response({
                "status": "error",
                "message": f"Failed to send OTP: {str(e)}"
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        Verification.objects.update_or_create(
            country_code=country_code,
            mobile=mobile,
            defaults={
                'otp': otp,
                'created_at': now,
                'updated_at': now
            }
        )

        return Response({
            "status": "success",
            "message": "OTP sent successfully",
            "otp": otp 
        }, status=status.HTTP_200_OK)


class VerifyOtpView(APIView):
    @swagger_auto_schema(
        request_body=VerifyOtpSerializer,
        responses={
            200: openapi.Response('OTP Verified Successfully'),
            400: 'Invalid OTP',
            404: 'Verification not found',
        },
        operation_description="Verify the OTP received on the mobile number"
    )
    def post(self, request):
        serializer = VerifyOtpSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        country_code = serializer.validated_data['country_code']
        mobile = serializer.validated_data['mobile']
        otp = serializer.validated_data['otp']

        try:
            verification = Verification.objects.get(country_code=country_code, mobile=mobile)
        except Verification.DoesNotExist:
            return Response({
                "status": "error",
                "message": "Verification record not found"
            }, status=status.HTTP_404_NOT_FOUND)

        expiry_time = verification.created_at + timedelta(seconds=60)
        if timezone.now() > expiry_time:
            return Response({
                "status": "error",
                "message": "OTP has expired"
            }, status=status.HTTP_400_BAD_REQUEST)

        if verification.otp != otp:
            return Response({
                "status": "error",
                "message": "Invalid OTP"
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            user = Customuser.objects.get(mobile=mobile, country_code=country_code)
            customuser = User.objects.get(username=user)

            if user.deleted_at is None:
                user.status = 1
                user.save()
            else:
                pass

            token, _ = Token.objects.get_or_create(user=customuser)
            user_data = UserSerializer(user).data

            return Response({
                "status": "success",
                "message": "OTP verified and user exists",
                "user_exists": True,
                "token": token.key,
                "user": user_data
            }, status=status.HTTP_200_OK)

        except Customuser.DoesNotExist:
            return Response({
                "status": "success",
                "message": "OTP verified successfully",
                "user_exists": False
            }, status=status.HTTP_200_OK)


class RestoreUserView(APIView):
    @swagger_auto_schema(
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['user_id'],
            properties={
                'user_id': openapi.Schema(type=openapi.TYPE_INTEGER)
            }
        ),
        responses={
            200: openapi.Response('User restored successfully'),
            404: 'User not found',
        },
        operation_description="Set deleted_at = NULL for a user using user_id"
    )
    def post(self, request):
        user_id = request.data.get('user_id')

        if not user_id:
            return Response({
                "status": "error",
                "message": "user_id is required"
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            user = Customuser.objects.get(id=user_id)
            user.status = 1
            user.deleted_at = None
            user.save()

            return Response({
                "status": "success",
                "message": "User restored successfully"
            }, status=status.HTTP_200_OK)

        except Customuser.DoesNotExist:
            return Response({
                "status": "error",
                "message": "User not found"
            }, status=status.HTTP_404_NOT_FOUND)

class UserRegisterView(APIView):
    @swagger_auto_schema(
        operation_description="Register a new user.",
        request_body=UserRegistrationSerializer,
        responses={201: openapi.Response('User registered successfully', UserRegistrationSerializer)}
    )
    def post(self, request):
        serializer = UserRegistrationSerializer(data=request.data)
        
        if serializer.is_valid():
            customuser = serializer.save()

            user, created = User.objects.get_or_create(username=customuser)
            token, created = Token.objects.get_or_create(user=user)

            user_data = UserRegistrationSerializer(customuser).data

            return Response({
                "status": "success",
                "message": "User registered successfully",
                "user_id": customuser.id,
                "user": user_data,
                "token": token.key,
            }, status=status.HTTP_201_CREATED)

        else:
            return Response({
                "status": "error",
                "message": "Username already exists",
            }, status=status.HTTP_400_BAD_REQUEST)

class DeleteUserAPIView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    @swagger_auto_schema(
        operation_description="Delete user account if inactive for 60+ days. If active within 60 days, sets status to offline. Requires a reason and OTP.",
        manual_parameters=[
            openapi.Parameter('pk', openapi.IN_PATH, description="User ID", type=openapi.TYPE_INTEGER),
        ],
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['reason', 'otp'],
            properties={
                'reason': openapi.Schema(type=openapi.TYPE_STRING, description='Reason for account deletion'),
                'otp': openapi.Schema(type=openapi.TYPE_STRING, description='OTP sent to mobile'),
            },
        ),
        responses={
            200: openapi.Response(description="Success message"),
            400: openapi.Response(description="Bad request"),
            404: openapi.Response(description="User not found or OTP invalid"),
        }
    )
    def post(self, request, pk):
        reason = request.data.get("reason")
        otp = request.data.get("otp")

        if not reason or not otp:
            return Response({"error": "Reason and OTP are required."}, status=status.HTTP_400_BAD_REQUEST)

        try:
            user = Customuser.objects.get(pk=pk)
        except Customuser.DoesNotExist:
            return Response({"error": "User not found."}, status=status.HTTP_404_NOT_FOUND)

        # OTP verification
        try:
            verification = Verification.objects.get(mobile=user.mobile, country_code=user.country_code)
        except Verification.DoesNotExist:
            return Response({"error": "OTP verification record not found."}, status=status.HTTP_404_NOT_FOUND)

        if verification.otp != otp:
            return Response({"error": "Invalid OTP."}, status=status.HTTP_400_BAD_REQUEST)

        # Proceed with deletion or soft delete logic
        if user.deleted_at is None:
            user.status = 3
            user.deleted_at = now()
            user.delete_reason = reason
            user.save()
            return Response({
                "message": "User marked as deleted. Will be permanently deleted after 60 days.",
                "deleted_at": user.deleted_at,
            }, status=status.HTTP_200_OK)

        inactive_days = (now() - user.deleted_at).days
        if inactive_days >= 60:
            user.delete()
            return Response({
                "message": "User permanently deleted after 60+ days of inactivity."
            }, status=status.HTTP_200_OK)

        return Response({
            "message": f"User marked for deletion, but only {inactive_days} days have passed.",
            "deleted_at": user.deleted_at,
        }, status=status.HTTP_200_OK)
    
class UserLogoutView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logged_in_user = request.user

        user = Customuser.objects.get(display_name=logged_in_user)

        user.status = 3
        user.save(update_fields=["status"])

        request.auth.delete()

        return Response({
            "status": "success",
            "message": "Logged out successfully"
        }, status=status.HTTP_200_OK)
