from django.conf import settings
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from apps.referrals.models import PointsBalance, Referral, ReferralCode
from apps.referrals.serializers import (
    ReferralApplySerializer,
    ReferralCodeSerializer,
    ReferralHistorySerializer,
)


class ReferralViewSet(viewsets.ViewSet):
    """ViewSet for referral system."""

    permission_classes = [IsAuthenticated]

    @action(detail=False, methods=["get"], url_path="my-code")
    def my_code(self, request):
        """GET /referrals/my-code/ — get or create referral code."""
        ref_code, _ = ReferralCode.objects.get_or_create(user=request.user)
        serializer = ReferralCodeSerializer(ref_code)
        return Response(serializer.data)

    @action(detail=False, methods=["post"], url_path="apply")
    def apply(self, request):
        """POST /referrals/apply/ — apply a friend's referral code."""
        serializer = ReferralApplySerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        code = serializer.validated_data["code"]

        # Find the referral code
        try:
            ref_code = ReferralCode.objects.select_related("user").get(code=code)
        except ReferralCode.DoesNotExist:
            return Response(
                {"detail": "Invalid referral code."}, status=status.HTTP_400_BAD_REQUEST
            )

        referrer = ref_code.user

        # Can't refer yourself
        if referrer == request.user:
            return Response(
                {"detail": "Cannot use your own referral code."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Check if already referred
        if Referral.objects.filter(referred=request.user).exists():
            return Response(
                {"detail": "You have already used a referral code."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Create referral
        points = getattr(settings, "DEFAULT_REFERRAL_POINTS", 20)
        Referral.objects.create(referrer=referrer, referred=request.user, awarded_points=points)

        # Award points to referrer
        balance, _ = PointsBalance.objects.get_or_create(user=referrer)
        balance.points += points
        balance.save(update_fields=["points"])

        return Response({"detail": "Referral applied successfully.", "points_awarded": points})

    @action(detail=False, methods=["get"], url_path="history")
    def history(self, request):
        """GET /referrals/history/ — referral history."""
        referrals = Referral.objects.filter(referrer=request.user).select_related("referred")
        serializer = ReferralHistorySerializer(referrals, many=True)
        return Response(serializer.data)
