from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView from api.models import Aspect, Hero, Item from api.serializers import ( HeroSerializer, ItemSerializer, RandomizeBuildRequestSerializer, ) from .data import generate_skill_build class HeroesListView(APIView): """ GET: Return all available heroes for selection. """ def get(self, request): heroes = Hero.objects.all().order_by("name") return Response(HeroSerializer(heroes, many=True).data, status=status.HTTP_200_OK) class RandomizeBuildView(APIView): """ POST: Generate a random Dota 2 build with hero, items, and optionally skills/aspects. """ def get_serializer(self, *args, **kwargs): return RandomizeBuildRequestSerializer(*args, **kwargs) def post(self, request): serializer = RandomizeBuildRequestSerializer(data=request.data) if not serializer.is_valid(): return Response( {"message": self._format_errors(serializer.errors)}, status=status.HTTP_400_BAD_REQUEST, ) validated_data = serializer.validated_data include_skills = validated_data["includeSkills"] include_aspect = validated_data["includeAspect"] items_count = validated_data["itemsCount"] hero_id = validated_data.get("heroId") hero_count = Hero.objects.count() item_count = Item.objects.count() if hero_count == 0: return Response( {"message": "No heroes available. Load data first."}, status=status.HTTP_400_BAD_REQUEST, ) if item_count < items_count: return Response( {"message": f"Not enough items available. Requested {items_count}, found {item_count}."}, status=status.HTTP_400_BAD_REQUEST, ) if hero_id: hero_obj = Hero.objects.filter(id=hero_id).first() if not hero_obj: return Response( {"message": f"Hero with id {hero_id} not found."}, status=status.HTTP_400_BAD_REQUEST, ) else: hero_obj = Hero.objects.order_by("?").first() item_objs = Item.objects.order_by("?")[:items_count] response_data = { "hero": HeroSerializer(hero_obj).data, "items": ItemSerializer(item_objs, many=True).data, } if include_skills: response_data["skillBuild"] = generate_skill_build() if include_aspect: hero_aspects = Aspect.objects.filter(hero=hero_obj) if hero_aspects.exists(): aspect_obj = hero_aspects.order_by("?").first() response_data["aspect"] = aspect_obj.name return Response(response_data, status=status.HTTP_200_OK) def _format_errors(self, errors: dict) -> str: """Format serializer errors into a readable message.""" messages = [] for field, field_errors in errors.items(): for error in field_errors: if field == "itemsCount" and "greater than or equal to" in str(error): messages.append("itemsCount must be at least 1.") elif "valid" in str(error).lower() or "required" in str(error).lower(): if field in ("includeSkills", "includeAspect"): messages.append("includeSkills and includeAspect must be boolean.") elif field == "itemsCount": messages.append("itemsCount must be a number.") else: messages.append(f"{field}: {error}") return messages[0] if messages else "Invalid request data."