from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.db import IntegrityError from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils import timezone from django.views import View from django.views.generic import ListView, TemplateView, UpdateView from .forms import SavedSearchForm from .models import FavoritePlayer, SavedSearch from .services.saved_searches import extract_filters_from_params, saved_search_to_querystring class ScoutingHomeView(LoginRequiredMixin, TemplateView): template_name = "scouting/index.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["saved_searches"] = SavedSearch.objects.filter(user=self.request.user).order_by("-updated_at") context["favorites"] = ( FavoritePlayer.objects.filter(user=self.request.user) .select_related("player", "player__nationality", "player__nominal_position", "player__inferred_role") .order_by("-created_at") ) return context class SavedSearchCreateView(LoginRequiredMixin, View): def post(self, request, *args, **kwargs): form = SavedSearchForm(request.POST) if not form.is_valid(): if request.headers.get("HX-Request") == "true": return render( request, "scouting/partials/save_search_feedback.html", {"ok": False, "message": "Invalid name or visibility values."}, ) messages.error(request, "Could not save search.") return redirect("players:index") filters = extract_filters_from_params(request.POST) if not filters: message = "No valid filters to save from current search." if request.headers.get("HX-Request") == "true": return render( request, "scouting/partials/save_search_feedback.html", {"ok": False, "message": message}, ) messages.error(request, message) return redirect("players:index") saved_search = form.save(commit=False) saved_search.user = request.user saved_search.filters = filters try: saved_search.save() except IntegrityError: message = "A saved search with this name already exists." if request.headers.get("HX-Request") == "true": return render( request, "scouting/partials/save_search_feedback.html", {"ok": False, "message": message}, ) messages.error(request, message) return redirect("players:index") message = f"Saved search '{saved_search.name}' created." if request.headers.get("HX-Request") == "true": return render( request, "scouting/partials/save_search_feedback.html", {"ok": True, "message": message}, ) messages.success(request, message) return redirect("scouting:index") class SavedSearchUpdateView(LoginRequiredMixin, UpdateView): model = SavedSearch form_class = SavedSearchForm template_name = "scouting/saved_search_edit.html" def get_queryset(self): return SavedSearch.objects.filter(user=self.request.user) def get_success_url(self): messages.success(self.request, "Saved search updated.") return reverse("scouting:index") class SavedSearchDeleteView(LoginRequiredMixin, View): def post(self, request, pk, *args, **kwargs): saved_search = get_object_or_404(SavedSearch, pk=pk, user=request.user) saved_search.delete() messages.success(request, "Saved search deleted.") return redirect("scouting:index") class SavedSearchRunView(LoginRequiredMixin, View): def get(self, request, pk, *args, **kwargs): saved_search = get_object_or_404(SavedSearch, pk=pk, user=request.user) query = saved_search_to_querystring(saved_search.filters) saved_search.last_run_at = timezone.now() saved_search.save(update_fields=["last_run_at"]) target = reverse("players:index") return redirect(f"{target}?{query}" if query else target) class WatchlistView(LoginRequiredMixin, ListView): model = FavoritePlayer context_object_name = "favorites" template_name = "scouting/watchlist.html" def get_queryset(self): return ( FavoritePlayer.objects.filter(user=self.request.user) .select_related("player", "player__nationality", "player__nominal_position", "player__inferred_role") .order_by("-created_at") ) class FavoriteToggleView(LoginRequiredMixin, View): def post(self, request, player_id, *args, **kwargs): from apps.players.models import Player player = get_object_or_404(Player, pk=player_id) next_url = request.POST.get("next") or request.META.get("HTTP_REFERER") or reverse("players:index") favorite, created = FavoritePlayer.objects.get_or_create(user=request.user, player=player) if not created: favorite.delete() is_favorite = created if request.headers.get("HX-Request") == "true": return render( request, "scouting/partials/favorite_button.html", { "player": player, "is_favorite": is_favorite, "next_url": next_url, }, ) return redirect(next_url) class SavedSearchListView(LoginRequiredMixin, ListView): model = SavedSearch context_object_name = "saved_searches" template_name = "scouting/saved_search_list.html" def get_queryset(self): return SavedSearch.objects.filter(user=self.request.user).order_by("-updated_at")