"""
API views для промокодов.
"""
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from .services import PromoCodeService
from .models import PromoCode
from rest_framework import serializers


class PromoCodeValidateSerializer(serializers.Serializer):
    """Сериализатор валидации промокода."""
    code = serializers.CharField(max_length=50, required=True)
    plan_id = serializers.IntegerField(required=False)
    student_count = serializers.IntegerField(required=False, default=0, min_value=0)
    duration_days = serializers.IntegerField(required=False, default=30, min_value=1)


@api_view(['POST'])
@permission_classes([AllowAny])
def validate_promo_code(request):
    """
    Валидация промокода и расчет скидки.
    
    POST /api/subscriptions/promo-codes/validate/
    Body: {
        "code": "PROMO2024",
        "plan_id": 1,
        "student_count": 5,
        "duration_days": 30
    }
    """
    serializer = PromoCodeValidateSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    
    code = serializer.validated_data['code']
    plan_id = serializer.validated_data.get('plan_id')
    student_count = serializer.validated_data.get('student_count', 0)
    duration_days = serializer.validated_data.get('duration_days', 30)
    
    # Валидация промокода
    user = request.user if request.user.is_authenticated else None
    promo_result = PromoCodeService.validate_promo_code(code, user)
    
    if not promo_result['valid']:
        return Response(
            {
                'valid': False,
                'error': promo_result['error']
            },
            status=status.HTTP_400_BAD_REQUEST
        )
    
    promo_code = promo_result['promo_code']
    
    # Если указан план, рассчитываем скидку
    if plan_id:
        from .models import SubscriptionPlan
        try:
            plan = SubscriptionPlan.objects.select_related().get(id=plan_id, is_active=True)
            price_data = plan.calculate_price(
                student_count=student_count,
                duration_days=duration_days,
                promo_code=promo_code
            )
            
            return Response({
                'valid': True,
                'promo_code': {
                    'code': promo_code.code,
                    'discount_type': promo_code.discount_type,
                    'discount_value': float(promo_code.discount_value),
                },
                'price': {
                    'original_amount': float(price_data['original_amount']),
                    'discount_amount': float(price_data['discount_amount']),
                    'final_amount': float(price_data['final_amount']),
                }
            })
        except SubscriptionPlan.DoesNotExist:
            return Response(
                {
                    'valid': True,
                    'promo_code': {
                        'code': promo_code.code,
                        'discount_type': promo_code.discount_type,
                        'discount_value': float(promo_code.discount_value),
                    },
                    'price': None
                }
            )
    
    # Если план не указан, просто возвращаем информацию о промокоде
    return Response({
        'valid': True,
        'promo_code': {
            'code': promo_code.code,
            'discount_type': promo_code.discount_type,
            'discount_value': float(promo_code.discount_value),
        }
    })


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def calculate_price(request):
    """
    Расчет цены подписки с учетом промокода.
    
    GET /api/subscriptions/calculate-price/?plan_id=1&student_count=5&duration_days=30&promo_code=PROMO2024
    """
    from .models import SubscriptionPlan
    from .services import SubscriptionService
    
    plan_id = request.query_params.get('plan_id')
    student_count = int(request.query_params.get('student_count', 0))
    duration_days = int(request.query_params.get('duration_days', 30))
    promo_code_str = request.query_params.get('promo_code')
    remaining_days = request.query_params.get('remaining_days')
    is_renewal = request.query_params.get('is_renewal') == 'true'
    is_add_students = request.query_params.get('is_add_students') == 'true'
    current_student_count = request.query_params.get('current_student_count')
    
    if not plan_id:
        return Response(
            {'error': 'Необходимо указать plan_id'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    try:
        plan = SubscriptionPlan.objects.select_related().get(id=plan_id, is_active=True)
    except SubscriptionPlan.DoesNotExist:
        return Response(
            {'error': 'Тарифный план не найден'},
            status=status.HTTP_404_NOT_FOUND
        )
    
    # Проверяем доступность периода
    if not plan.is_duration_available(duration_days):
        available = plan.get_available_durations()
        return Response(
            {'error': f'Период {duration_days} дней недоступен для этого тарифа. Доступные периоды: {", ".join(map(str, available))}'},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    # Валидация промокода если указан
    promo_code = None
    if promo_code_str:
        promo_result = PromoCodeService.validate_promo_code(promo_code_str, request.user)
        if promo_result['valid']:
            promo_code = promo_result['promo_code']
        else:
            return Response(
                {'error': promo_result['error']},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    # Если это продление и есть оставшиеся дни, учитываем их
    remaining_days_int = None
    if (is_renewal or is_add_students) and remaining_days:
        try:
            remaining_days_int = int(remaining_days)
        except (ValueError, TypeError):
            pass
    
    # Получаем текущее количество учеников для расчета доплаты
    current_student_count_int = 0
    if current_student_count:
        try:
            current_student_count_int = int(current_student_count)
        except (ValueError, TypeError):
            pass
    elif is_renewal and request.user.is_authenticated:
        # Если не передано, пытаемся получить из активной подписки
        from .models import Subscription
        try:
            subscription = Subscription.objects.filter(
                user=request.user,
                plan=plan,
                status__in=['active', 'trial']
            ).select_related('plan').order_by('-end_date').first()
            if subscription:
                current_student_count_int = subscription.student_count or 0
        except:
            pass
    
    # Рассчитываем цену
    price_data = SubscriptionService.calculate_subscription_price(
        plan=plan,
        student_count=student_count,
        duration_days=duration_days,
        promo_code=promo_code,
        remaining_days=remaining_days_int,
        is_add_students=is_add_students,
        current_student_count=current_student_count_int
    )
    
    response_data = {
        'original_amount': float(price_data['original_amount']),
        'discount_amount': float(price_data['discount_amount']),
        'final_amount': float(price_data['final_amount']),
    }
    
    # Добавляем информацию о доплате за новых учеников
    if 'extra_students_payment' in price_data:
        response_data['extra_students_payment'] = price_data['extra_students_payment']
        response_data['extra_students_count'] = price_data.get('extra_students_count', 0)
        response_data['remaining_days_payment'] = price_data.get('remaining_days_payment', 0)
    
    # Добавляем информацию о скидке за длительность
    if 'duration_discount' in price_data:
        response_data['duration_discount'] = price_data['duration_discount']
    
    # Добавляем дату окончания подписки
    if 'end_date' in price_data:
        response_data['end_date'] = price_data['end_date']
    if 'end_date_display' in price_data:
        response_data['end_date_display'] = price_data['end_date_display']
    
    if promo_code:
        response_data['promo_code'] = {
            'code': promo_code.code,
            'discount_type': promo_code.discount_type,
            'discount_value': float(promo_code.discount_value),
        }
    
    return Response(response_data)

