"""
REST API Views for User Management and Authentication
"""
from rest_framework import generics, status, viewsets
from rest_framework.decorators import action, api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
# from rest_framework_simplejwt.tokens import RefreshToken  # Optional - install if needed
from django.contrib.auth import authenticate, login
from .models import User, Address, Wishlist, VerificationCode
from .serializers import (
    UserSerializer,
    UserProfileSerializer,
    AddressSerializer,
    WishlistSerializer,
    ChangePasswordSerializer
)
from .permissions import IsOwnerOrReadOnly
from django.core.mail import send_mail
from django.conf import settings
from django.utils import timezone
import random


class RegisterView(generics.CreateAPIView):
    """User registration endpoint"""
    
    queryset = User.objects.all()
    permission_classes = (AllowAny,)
    serializer_class = UserSerializer
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        
        # Auto-send verification codes
        _send_verification_code(user, 'email', user.email)
        if user.phone:
            _send_verification_code(user, 'phone', user.phone)
        
        return Response({
            'user': UserProfileSerializer(user).data,
            'message': 'Registration successful! Verification codes sent to your email and phone.'
        }, status=status.HTTP_201_CREATED)


@api_view(['POST'])
@permission_classes([AllowAny])
def login_view(request):
    """User login endpoint"""
    
    email = request.data.get('email')
    password = request.data.get('password')
    
    if not email or not password:
        return Response(
            {'error': 'Please provide both email and password'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    user = authenticate(email=email, password=password)
    
    if user is None:
        return Response(
            {'error': 'Invalid credentials'},
            status=status.HTTP_401_UNAUTHORIZED
        )
    
    if not user.is_active:
        return Response(
            {'error': 'Account is deactivated'},
            status=status.HTTP_401_UNAUTHORIZED
        )
    if not user.email_verified or not user.phone_verified:
        _send_verification_code(user, 'email', user.email)
        if user.phone:
            _send_verification_code(user, 'phone', user.phone)
        return Response({
            'error': 'Verification required',
            'email_verified': bool(user.email_verified),
            'phone_verified': bool(user.phone_verified),
            'message': 'Six-digit codes have been sent to your email and phone.'
        }, status=status.HTTP_403_FORBIDDEN)
    login(request, user)
    return Response({'user': UserProfileSerializer(user).data, 'message': 'Login successful!'})


class UserProfileView(generics.RetrieveUpdateAPIView):
    """User profile view and update"""
    
    serializer_class = UserProfileSerializer
    permission_classes = (IsAuthenticated,)
    
    def get_object(self):
        return self.request.user


class ChangePasswordView(generics.UpdateAPIView):
    """Change password endpoint"""
    
    serializer_class = ChangePasswordSerializer
    permission_classes = (IsAuthenticated,)
    
    def update(self, request, *args, **kwargs):
        user = request.user
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # Check old password
        if not user.check_password(serializer.validated_data.get('old_password')):
            return Response(
                {'old_password': 'Wrong password'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Set new password
        user.set_password(serializer.validated_data.get('new_password'))
        user.save()
        
        return Response({
            'message': 'Password updated successfully'
        }, status=status.HTTP_200_OK)


class AddressViewSet(viewsets.ModelViewSet):
    """Address CRUD operations"""
    
    serializer_class = AddressSerializer
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    
    def get_queryset(self):
        return Address.objects.filter(user=self.request.user)
    
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)
    
    @action(detail=True, methods=['post'])
    def set_default(self, request, pk=None):
        """Set address as default"""
        address = self.get_object()
        address.is_default = True
        address.save()
        return Response({'status': 'Address set as default'})


def _send_verification_code(user, channel, contact_value=None):
    code = f"{random.randint(100000, 999999)}"
    expiry = timezone.now() + timezone.timedelta(minutes=10)
    VerificationCode.objects.filter(user=user, channel=channel, is_used=False).update(is_used=True)
    VerificationCode.objects.create(
        user=user,
        channel=channel,
        code=code,
        contact_value=contact_value or (user.email if channel == 'email' else user.phone or ''),
        expires_at=expiry,
        max_attempts=5
    )
    subj = 'Your Verification Code'
    body = f'Your {channel} verification code is: {code}. It expires in 10 minutes.'
    if channel == 'email' and user.email:
        try:
            send_mail(subj, body, getattr(settings, 'DEFAULT_FROM_EMAIL', 'no-reply@aibimagics.com'), [user.email], fail_silently=True)
        except Exception:
            pass
    elif channel == 'phone' and user.phone:
        try:
            from twilio.rest import Client as TwilioClient
            sid = getattr(settings, 'TWILIO_ACCOUNT_SID', '')
            token = getattr(settings, 'TWILIO_AUTH_TOKEN', '')
            from_number = getattr(settings, 'TWILIO_PHONE_NUMBER', '')
            if sid and token and from_number:
                client = TwilioClient(sid, token)
                client.messages.create(
                    body=body,
                    from_=from_number,
                    to=user.phone
                )
        except Exception:
            pass


@api_view(['POST'])
@permission_classes([AllowAny])
def send_verification(request):
    """Send six-digit code for email/phone"""
    email = request.data.get('email')
    channel = request.data.get('channel')
    if channel not in ('email', 'phone'):
        return Response({'error': 'channel must be email or phone'}, status=400)
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist:
        return Response({'error': 'user not found'}, status=404)
    contact_value = request.data.get('contact_value')
    if channel == 'phone':
        contact_value = contact_value or user.phone
        if not contact_value:
            return Response({'error': 'phone number required'}, status=400)
    _send_verification_code(user, channel, contact_value)
    return Response({'message': 'Verification code sent'})


@api_view(['POST'])
@permission_classes([AllowAny])
def verify_code(request):
    """Verify six-digit code"""
    email = request.data.get('email')
    channel = request.data.get('channel')
    code = request.data.get('code')
    if not (email and channel and code):
        return Response({'error': 'email, channel, and code required'}, status=400)
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist:
        return Response({'error': 'user not found'}, status=404)
    vc = VerificationCode.objects.filter(user=user, channel=channel, is_used=False).order_by('-created_at').first()
    if not vc:
        return Response({'error': 'no code found, send again'}, status=404)
    if vc.is_expired():
        return Response({'error': 'code expired'}, status=400)
    if vc.attempts >= vc.max_attempts:
        return Response({'error': 'too many attempts'}, status=429)
    vc.attempts += 1
    if vc.code != str(code).strip():
        vc.save(update_fields=['attempts'])
        return Response({'error': 'invalid code'}, status=400)
    vc.is_used = True
    vc.save(update_fields=['attempts', 'is_used'])
    if channel == 'email':
        user.email_verified = True
    elif channel == 'phone':
        user.phone_verified = True
    user.is_verified = bool(user.email_verified and user.phone_verified)
    user.save(update_fields=['email_verified', 'phone_verified', 'is_verified'])
    return Response({'message': 'Verification successful', 'email_verified': user.email_verified, 'phone_verified': user.phone_verified})


class WishlistViewSet(viewsets.ModelViewSet):
    """Wishlist CRUD operations"""
    
    serializer_class = WishlistSerializer
    permission_classes = (IsAuthenticated,)
    
    def get_queryset(self):
        return Wishlist.objects.filter(user=self.request.user)
    
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)
    
    @action(detail=False, methods=['post'])
    def toggle(self, request):
        """Add or remove product from wishlist"""
        product_id = request.data.get('product_id')
        
        if not product_id:
            return Response(
                {'error': 'product_id is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        wishlist_item, created = Wishlist.objects.get_or_create(
            user=request.user,
            product_id=product_id
        )
        
        if not created:
            wishlist_item.delete()
            return Response({
                'status': 'removed',
                'message': 'Product removed from wishlist'
            })
        
        return Response({
            'status': 'added',
            'message': 'Product added to wishlist'
        }, status=status.HTTP_201_CREATED)
