from collections import defaultdict, OrderedDict
from django.views.generic import TemplateView
from django.urls import reverse_lazy
from django.db.models import Count, Q, Prefetch, Sum, F, IntegerField, Value, BooleanField, Case, When
from django.db.models.functions import Coalesce
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from trades.models import TradeOffer, TradeAcceptance, TradeOfferHaveCard, TradeOfferWantCard
from cards.models import Card
from django.utils.decorators import method_decorator
from django.template.response import TemplateResponse
from django.http import HttpResponseRedirect
import logging
#from silk.profiling.profiler import silk_profile

logger = logging.getLogger(__name__)

class HomePageView(TemplateView):
    template_name = "home/home.html"

    #@silk_profile(name='Home Page')
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        try:
            # Get all cards ordered by name
            context["cards"] = Card.objects.all().order_by("name")
            
            # Reuse base trade offer queryset for market stats
            base_offer_qs = TradeOffer.objects.filter(is_closed=False)
            
            # Recent Offers
            try:
                recent_offers_qs = base_offer_qs.order_by("-created_at")
                context["recent_offers"] = recent_offers_qs[:6]
            except Exception as e:
                logger.error(f"Error fetching recent offers: {str(e)}")
                context["recent_offers"] = []
            
            # Most Offered Cards
            try:
                context["most_offered_cards"] = (
                    Card.objects.filter(tradeofferhavecard__isnull=False)
                    .annotate(offer_count=Sum("tradeofferhavecard__quantity"))
                    .order_by("-offer_count")[:6]
                )
            except Exception as e:
                logger.error(f"Error fetching most offered cards: {str(e)}")
                context["most_offered_cards"] = []
            
            # Most Wanted Cards
            try:
                context["most_wanted_cards"] = (
                    Card.objects.filter(tradeofferwantcard__isnull=False)
                    .annotate(offer_count=Sum("tradeofferwantcard__quantity"))
                    .order_by("-offer_count")[:6]
                )
            except Exception as e:
                logger.error(f"Error fetching most wanted cards: {str(e)}")
                context["most_wanted_cards"] = []
            
            # Least Offered Cards
            try:
                context["least_offered_cards"] = (
                    Card.objects.annotate(
                        offer_count=Coalesce(Sum("tradeofferhavecard__quantity"), 0)
                    )
                    .order_by("offer_count")[:6]
                )
            except Exception as e:
                logger.error(f"Error fetching least offered cards: {str(e)}")
                context["least_offered_cards"] = []
            
            # Build featured offers with custom ordering
            featured = OrderedDict()
            # Featured "All" offers remains fixed at the top
            try:
                featured["All"] = base_offer_qs.order_by("created_at")[:6]
            except Exception as e:
                logger.error(f"Error fetching 'All' featured offers: {str(e)}")
                featured["All"] = []
                
            try:
                # Pull out distinct (rarity_level, rarity_icon) tuples
                distinct_rarities = base_offer_qs.values_list("rarity_level", "rarity_icon").distinct()
                
                # Prepare a list that holds tuples of (rarity_level, rarity_icon, offers)
                rarity_offers = []
                for rarity_level, rarity_icon in distinct_rarities:
                    offers = base_offer_qs.filter(rarity_level=rarity_level).order_by("created_at")[:6]
                    rarity_offers.append((rarity_level, rarity_icon, offers))
                
                # Sort by rarity_level (from greatest to least)
                rarity_offers.sort(key=lambda x: x[0], reverse=True)
            
                # Add the sorted offers to the OrderedDict
                for rarity_level, rarity_icon, offers in rarity_offers:
                    featured[rarity_icon] = offers
            except Exception as e:
                logger.error(f"Error processing rarity-based featured offers: {str(e)}")

            context["featured_offers"] = featured
        except Exception as e:
            logger.error(f"Unhandled error in HomePageView.get_context_data: {str(e)}")
            # Provide fallback empty data
            context["cards"] = []
            context["recent_offers"] = []
            context["most_offered_cards"] = []
            context["most_wanted_cards"] = []
            context["least_offered_cards"] = []
            context["featured_offers"] = OrderedDict([("All", [])])
            
        return context
        
    def get(self, request, *args, **kwargs):
        """Override get method to add caching"""
        return super().get(request, *args, **kwargs)