"""Validate-promo endpoint — gives the frontend a preview of price + discount.""" from django.shortcuts import get_object_or_404 from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer from rest_framework import serializers from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from apps.courses.models import Course, CourseStatus from apps.enrollments.api.permissions import IsStudent from apps.payments.services.orders import OrderError, _resolve_discount class PromoPreviewRequestSerializer(serializers.Serializer): promo_code = serializers.CharField(required=False, allow_blank=True) referral_code = serializers.CharField(required=False, allow_blank=True) class PromoPreviewResponseSerializer(serializers.Serializer): course_slug = serializers.CharField() base_amount_toman = serializers.IntegerField() discount_amount_toman = serializers.IntegerField() final_amount_toman = serializers.IntegerField() promo_code_applied = serializers.CharField(allow_null=True) referrer_code_applied = serializers.CharField(allow_null=True) class CheckoutPreviewView(APIView): """`POST /api/courses//checkout/preview/` — dry-run price computation.""" permission_classes = [IsAuthenticated, IsStudent] @extend_schema( tags=["payments"], summary="Preview checkout price (apply promo / referral code without committing)", request=PromoPreviewRequestSerializer, responses={ 200: PromoPreviewResponseSerializer, 400: OpenApiResponse(description="Code invalid / not applicable / both supplied / course is free."), 404: OpenApiResponse(description="Course not found or not published."), }, ) def post(self, request, slug): course = get_object_or_404(Course, slug=slug, status=CourseStatus.PUBLISHED) if course.is_free: return Response( {"detail": "Course is free; no checkout needed."}, status=400, ) ser = PromoPreviewRequestSerializer(data=request.data) ser.is_valid(raise_exception=True) base = int(course.price_toman or 0) try: discount, pc_obj, referrer, _credit = _resolve_discount( course, base, promo_code=ser.validated_data.get("promo_code") or None, referral_code=ser.validated_data.get("referral_code") or None, buyer=request.user, ) except OrderError as e: return Response({"detail": str(e)}, status=400) final = max(0, base - discount) body = { "course_slug": course.slug, "base_amount_toman": base, "discount_amount_toman": discount, "final_amount_toman": final, "promo_code_applied": pc_obj.code if pc_obj else None, "referrer_code_applied": referrer.referral_code if referrer else None, } return Response(PromoPreviewResponseSerializer(body).data)