# apps/users/views/otp.py
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import AllowAny
from rest_framework.viewsets import GenericViewSet
from django.utils import timezone

from apps.users.serializers.otp import (
    OTPSendSerializer,
    OTPVerifySerializer,
    OTPResendSerializer
)

from apps.core.services import send_email_otp, verify_otp, resend_otp
from apps.users.models import User


class OTPViewSet(GenericViewSet):
    permission_classes = [AllowAny]
    
    serializer_class = OTPSendSerializer
    
    def get_serializer_class(self):
        """Return appropriate serializer based on action"""
        if self.action == 'send':
            return OTPSendSerializer
        elif self.action == 'verify':
            return OTPVerifySerializer
        elif self.action == 'resend':
            return OTPResendSerializer
        return OTPSendSerializer  # default
    
    @action(detail=False, methods=['post'])
    def send(self, request):
        """Send OTP to user's email"""
        serializer = self.get_serializer(data=request.data)
        
        if not serializer.is_valid():
            errors = []
            for field, error_list in serializer.errors.items():
                if isinstance(error_list, list):
                    for error in error_list:
                        errors.append({
                            "field": field,
                            "description": str(error)
                        })
                else:
                    errors.append({
                        "field": field,
                        "description": str(error_list)
                    })
            
            return Response({
                "success": False,
                "error": {'details': errors},
                "message": "Validation failed",
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_400_BAD_REQUEST)
        
        user = serializer.validated_data['user']
        
        # Send OTP to email (no channel parameter needed)
        success, message = send_email_otp(user, user.email)
        
        if success:
            return Response({
                "success": True,
                "message": message,
                "data": {
                    "email": user.email,
                    "expires_in": "5 minutes"
                },
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_200_OK)
        else:
            return Response({
                "success": False,
                "error": {'details': [{"description": message}]},
                "message": "Failed to send OTP",
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'])
    def verify(self, request):
        """Verify OTP"""
        serializer = self.get_serializer(data=request.data)
        
        if not serializer.is_valid():
            errors = []
            for field, error_list in serializer.errors.items():
                if isinstance(error_list, list):
                    for error in error_list:
                        errors.append({
                            "field": field,
                            "description": str(error)
                        })
                else:
                    errors.append({
                        "field": field,
                        "description": str(error_list)
                    })
            
            return Response({
                "success": False,
                "error": {'details': errors},
                "message": "Validation failed",
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_400_BAD_REQUEST)
        
        user = serializer.validated_data['user']
        otp = serializer.validated_data['otp']
        
        success, message = verify_otp(user, otp)
        
        if success:
            return Response({
                "success": True,
                "message": message,
                "data": {
                    "user_id": str(user.id),
                    "email": user.email,
                    "name": user.name,
                    "is_email_verified": True,
                    "is_active": True
                },
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_200_OK)
        else:
            return Response({
                "success": False,
                "error": {'details': [{"description": message}]},
                "message": message,
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=False, methods=['post'])
    def resend(self, request):
        """Resend OTP"""
        serializer = self.get_serializer(data=request.data)
        
        if not serializer.is_valid():
            errors = []
            for field, error_list in serializer.errors.items():
                if isinstance(error_list, list):
                    for error in error_list:
                        errors.append({
                            "field": field,
                            "description": str(error)
                        })
                else:
                    errors.append({
                        "field": field,
                        "description": str(error_list)
                    })
            
            return Response({
                "success": False,
                "error": {'details': errors},
                "message": "Validation failed",
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_400_BAD_REQUEST)
        
        user = serializer.validated_data['user']
        
        # Resend OTP (no channel parameter needed)
        success, message = resend_otp(user, user.email)
        
        if success:
            return Response({
                "success": True,
                "message": message,
                "data": {
                    "email": user.email,
                    "expires_in": "5 minutes"
                },
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_200_OK)
        else:
            return Response({
                "success": False,
                "error": {'details': [{"description": message}]},
                "message": "Failed to resend OTP",
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['get'])
    def status(self, request):
        """Check OTP status for a user"""
        email = request.query_params.get('email')
        
        if not email:
            return Response({
                "success": False,
                "error": {'details': [{"description": "Email is required"}]},
                "message": "Email is required",
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            user = User.objects.get(email__iexact=email)
            
            status_data = {
                "email": user.email,
                "is_email_verified": user.is_email_verified,
                "is_active": user.is_active,
                "has_otp": bool(user.otp),
            }
            
            if user.otp_expires_at:
                status_data["otp_expires_at"] = user.otp_expires_at.strftime("%d-%B-%Y %H:%M:%S")
                status_data["is_otp_expired"] = user.otp_expires_at < timezone.now()
            
            return Response({
                "success": True,
                "message": "OTP status retrieved",
                "data": status_data,
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_200_OK)
            
        except User.DoesNotExist:
            return Response({
                "success": False,
                "error": {'details': [{"description": "User not found"}]},
                "message": "User not found",
                "timestamp": timezone.now().strftime("%d-%B-%Y %H:%M:%S")
            }, status=status.HTTP_404_NOT_FOUND)