from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.contrib import messages
from django.shortcuts import get_object_or_404
from .models import Tag
from .forms import TagForm
from django.db.models import Count
from django.core.cache import cache
from django.utils import timezone
import json
import random

def get_tag_cloud_data():
    """
    Get tag cloud data with caching.
    Returns a list of tags with name, count, slug, and size attributes.
    The size is a value from 1-10 based on the tag's usage count.
    """
    # Try to get from cache first
    tag_cloud = cache.get('tag_cloud_data')
    if tag_cloud is not None:
        return tag_cloud
    
    # If not in cache, generate the data
    tags = Tag.objects.annotate(
        links_count=Count('links', distinct=True),
        pages_count=Count('pages', distinct=True),
        posts_count=Count('posts', distinct=True),
        image_collections_count=Count('image_collections', distinct=True)
    )
    
    # Calculate total count for each tag
    tag_data = []
    for tag in tags:
        count = (
            tag.links_count +
            tag.pages_count +
            tag.posts_count +
            tag.image_collections_count
        )
        if count > 0:  # Only include tags that are used
            tag_data.append({
                'name': tag.name,
                'slug': tag.slug,
                'count': count
            })
    
    # Sort by count in descending order
    tag_data.sort(key=lambda x: x['count'], reverse=True)
    
    # Calculate size based on count (for font sizing in the cloud)
    if tag_data:
        max_count = max(item['count'] for item in tag_data)
        min_count = min(item['count'] for item in tag_data)
        range_count = max(1, max_count - min_count)  # Avoid division by zero
        
        for item in tag_data:
            # Calculate a size value between 1 and 10
            if range_count == 1:
                item['size'] = 5  # If all tags have the same count
            else:
                item['size'] = 1 + int(9 * (item['count'] - min_count) / range_count)
    
    # Store in cache for 1 minute
    cache.set('tag_cloud_data', tag_data, 60)
    
    return tag_data

class TagListView(ListView):
    model = Tag
    context_object_name = 'tags'
    template_name = 'links/tag_list.html'
    
    def get_queryset(self):
        queryset = super().get_queryset()
        # Annotate each tag with its usage count
        queryset = queryset.annotate(
            links_count=Count('links', distinct=True),
            pages_count=Count('pages', distinct=True),
            posts_count=Count('posts', distinct=True),
            image_collections_count=Count('image_collections', distinct=True),
        )
        # Add a total_count attribute to each tag
        for tag in queryset:
            tag.total_count = (
                tag.links_count + 
                tag.pages_count + 
                tag.posts_count + 
                tag.image_collections_count
            )
        
        # Get sort parameter from request
        sort_by = self.request.GET.get('sort', 'name')
        
        # Sort the queryset based on the sort parameter
        if sort_by == 'count':
            # Sort by total count (descending)
            queryset = sorted(queryset, key=lambda x: x.total_count, reverse=True)
        elif sort_by == 'count_asc':
            # Sort by total count (ascending)
            queryset = sorted(queryset, key=lambda x: x.total_count)
        elif sort_by == 'name_desc':
            # Sort by name (descending)
            queryset = sorted(queryset, key=lambda x: x.name, reverse=True)
        else:
            # Default: sort by name (ascending)
            queryset = sorted(queryset, key=lambda x: x.name)
            
        return queryset
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['tag_cloud'] = get_tag_cloud_data()
        # Pass the tag colors to the template
        context['tag_colors'] = [
            '#3498db', '#2ecc71', '#e74c3c', '#f39c12', '#9b59b6',
            '#1abc9c', '#d35400', '#34495e', '#16a085', '#27ae60'
        ]
        # Pass the current sort parameter to the template
        context['current_sort'] = self.request.GET.get('sort', 'name')
        return context

class TagDetailView(DetailView):
    model = Tag
    context_object_name = 'tag'
    template_name = 'links/tag_detail.html'
    slug_url_kwarg = 'slug'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # Get all resource types that have this tag
        context['links'] = self.object.links.all()
        context['pages'] = self.object.pages.all()
        context['posts'] = self.object.posts.all()
        context['image_collections'] = self.object.image_collections.all()
        
        # Calculate total usage count
        total_count = (
            context['links'].count() + 
            context['pages'].count() + 
            context['posts'].count() + 
            context['image_collections'].count()
        )
        context['total_usage_count'] = total_count
        return context

class TagCreateView(CreateView):
    model = Tag
    form_class = TagForm
    template_name = 'links/tag_form.html'
    success_url = reverse_lazy('tag-list')

    def form_valid(self, form):
        messages.success(self.request, 'Tag created successfully.')
        return super().form_valid(form)

class TagUpdateView(UpdateView):
    model = Tag
    form_class = TagForm
    template_name = 'links/tag_form.html'
    slug_url_kwarg = 'slug'

    def get_success_url(self):
        return reverse_lazy('tag-detail', kwargs={'slug': self.object.slug})

    def form_valid(self, form):
        messages.success(self.request, 'Tag updated successfully.')
        return super().form_valid(form)

class TagDeleteView(DeleteView):
    model = Tag
    template_name = 'links/tag_confirm_delete.html'
    success_url = reverse_lazy('tag-list')
    slug_url_kwarg = 'slug'

    def delete(self, request, *args, **kwargs):
        messages.success(request, 'Tag deleted successfully.')
        return super().delete(request, *args, **kwargs)
