from django.shortcuts import render
from rest_framework import viewsets, mixins, status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from django.db import transaction, models
from django.utils import timezone
from userapp.authentication import RedisTokenAuthentication

from .models import Achievement, UserAchievement
from .serializers import (
    AchievementSerializer, 
    UserAchievementSerializer,
    UserAchievementCreateSerializer,
    UserAchievementListSerializer
)

class IsAdminOrReadOnly(permissions.BasePermission):
    """管理员可写，其他人只读"""
    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return request.user and request.user.is_authenticated
        return request.user and request.user.is_staff


class AchievementViewSet(viewsets.ModelViewSet):
    """
    成就相关视图集
    管理员可增删改查，普通用户只读
    """
    serializer_class = AchievementSerializer
    permission_classes = [IsAdminOrReadOnly]
    authentication_classes = [RedisTokenAuthentication]
    
    def get_queryset(self):
        """根据请求过滤成就列表"""
        queryset = Achievement.objects.all()
        
        # 排除隐藏成就（除非客户端特别请求）
        show_hidden = self.request.query_params.get('show_hidden', 'false').lower() == 'true'
        if not show_hidden:
            # 过滤出用户已获得的隐藏成就和非隐藏成就
            user_achievement_ids = UserAchievement.objects.filter(
                user=self.request.user
            ).values_list('achievement_id', flat=True)
            
            queryset = queryset.filter(
                # 非隐藏成就或已经获得的隐藏成就
                models.Q(is_hidden=False) | models.Q(id__in=user_achievement_ids)
            )
        
        # 按类型过滤
        achievement_type = self.request.query_params.get('type')
        if achievement_type:
            queryset = queryset.filter(achievement_type=achievement_type)
        
        # 按稀有度过滤
        rarity = self.request.query_params.get('rarity')
        if rarity:
            queryset = queryset.filter(rarity=rarity)
            
        return queryset
    
    @action(detail=True, methods=['get'])
    def check_achievement(self, request, pk=None):
        """
        检查当前用户是否获得了指定成就
        """
        achievement = self.get_object()
        has_achievement = UserAchievement.objects.filter(
            user=request.user,
            achievement=achievement
        ).exists()
        
        return Response({
            'has_achievement': has_achievement,
            'achievement': AchievementSerializer(achievement).data
        })


class UserAchievementViewSet(mixins.ListModelMixin,
                            mixins.RetrieveModelMixin,
                            viewsets.GenericViewSet):
    """
    用户成就相关视图集
    """
    permission_classes = [permissions.IsAuthenticated]
    authentication_classes = [RedisTokenAuthentication]
    
    def get_serializer_class(self):
        if self.action == 'create_achievement':
            return UserAchievementCreateSerializer
        elif self.action == 'list':
            return UserAchievementListSerializer
        return UserAchievementSerializer
    
    def get_queryset(self):
        """获取当前用户的成就"""
        return UserAchievement.objects.filter(user=self.request.user)
    
    @action(detail=False, methods=['post'], permission_classes=[permissions.IsAdminUser])
    def create_achievement(self, request):
        """
        管理员手动授予用户成就
        """
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    
    @action(detail=False, methods=['post'])
    def check_and_grant(self, request):
        """
        检查并授予成就
        前端传递相关数据，后端根据成就条件检查是否满足条件并授予成就
        """
        achievement_id = request.data.get('achievement_id')
        check_data = request.data.get('check_data', {})
        
        if not achievement_id:
            return Response(
                {"detail": "必须提供成就ID"}, 
                status=status.HTTP_400_BAD_REQUEST
            )
            
        # 获取成就
        achievement = get_object_or_404(Achievement, id=achievement_id)
        
        # 检查用户是否已经获得该成就
        if UserAchievement.objects.filter(
            user=request.user,
            achievement=achievement
        ).exists():
            return Response(
                {"detail": "用户已获得该成就"},
                status=status.HTTP_200_OK
            )
        
        # TODO: 根据成就的conditions字段和前端传递的check_data检查是否满足条件
        # 这部分逻辑需要根据具体成就类型和条件来实现
        # 这里只是一个简化的示例
        conditions_met = True  # 默认满足条件
        
        if conditions_met:
            # 满足条件，授予成就
            user_achievement = UserAchievement.objects.create(
                user=request.user,
                achievement=achievement,
                acquisition_data=check_data
            )
            
            return Response({
                "detail": "成就获得成功",
                "achievement": AchievementSerializer(achievement).data
            }, status=status.HTTP_201_CREATED)
        else:
            return Response({
                "detail": "未满足成就条件"
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=False, methods=['get'])
    def unread_notifications(self, request):
        """
        获取用户未读的成就通知
        """
        unread_achievements = UserAchievement.objects.filter(
            user=request.user,
            notification_shown=False
        )
        
        serializer = UserAchievementSerializer(unread_achievements, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def mark_notification_shown(self, request, pk=None):
        """
        标记成就通知为已显示
        """
        user_achievement = self.get_object()
        user_achievement.notification_shown = True
        user_achievement.save()
        
        return Response({"detail": "成功标记为已显示"})
        
    @action(detail=False, methods=['post'])
    def mark_all_notifications_shown(self, request):
        """
        标记所有成就通知为已显示
        """
        UserAchievement.objects.filter(
            user=request.user,
            notification_shown=False
        ).update(notification_shown=True)
        
        return Response({"detail": "所有通知已标记为已显示"})
        
    @action(detail=False, methods=['get'])
    def stats(self, request):
        """
        获取用户成就统计信息
        """
        user = request.user
        
        # 获取成就总数
        total_achievements = Achievement.objects.count()
        hidden_achievements = Achievement.objects.filter(is_hidden=True).count()
        visible_achievements = total_achievements - hidden_achievements
        
        # 获取用户已获得的成就数
        user_achievements = UserAchievement.objects.filter(user=user).count()
        
        # 按稀有度统计
        rarity_stats = {}
        for rarity_code, rarity_name in Achievement.RARITY_CHOICES:
            total = Achievement.objects.filter(rarity=rarity_code).count()
            acquired = UserAchievement.objects.filter(
                user=user,
                achievement__rarity=rarity_code
            ).count()
            rarity_stats[rarity_code] = {
                'name': rarity_name,
                'total': total,
                'acquired': acquired,
                'percentage': round(acquired / total * 100, 2) if total > 0 else 0
            }
            
        # 按类型统计
        type_stats = {}
        for type_code, type_name in Achievement.TYPE_CHOICES:
            total = Achievement.objects.filter(achievement_type=type_code).count()
            acquired = UserAchievement.objects.filter(
                user=user,
                achievement__achievement_type=type_code
            ).count()
            type_stats[type_code] = {
                'name': type_name,
                'total': total,
                'acquired': acquired,
                'percentage': round(acquired / total * 100, 2) if total > 0 else 0
            }
            
        return Response({
            'total_achievements': total_achievements,
            'visible_achievements': visible_achievements,
            'hidden_achievements': hidden_achievements,
            'user_achievements': user_achievements,
            'completion_percentage': round(user_achievements / total_achievements * 100, 2) if total_achievements > 0 else 0,
            'rarity_stats': rarity_stats,
            'type_stats': type_stats
        })
