import pytz
from datetime import datetime, time
from django.db.models import Sum, Max
from django.core.cache import cache
from rest_framework.generics import (
    ListAPIView,
    RetrieveAPIView,
    CreateAPIView
)
from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework.permissions import IsAuthenticated
from rest_framework.filters import SearchFilter, OrderingFilter
from mosquito.api.pagination import PostLimitOffsetPagination, PostPageNumberPagination
from .serializers import (
    DeviceCountSerializer,
    DeviceInfoSerializer,
    LogHistorySerializer,
    DeviceLogHistorySerializer,
)
from ..models import DeviceCount, DeviceInfo
from mosquito.models import MosqPostStatistic, DevicePostStatistic


class DeviceLogListAPIView(ListAPIView):
    serializer_class = DeviceCountSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    pagination_class = PostPageNumberPagination
    search_fields = ['device_id']

    def get_queryset(self, *args, **kwargs):
        queryset_list = DeviceCount.objects.get_queryset().order_by('-data_time')
        device_id = self.request.GET.get('device_id')
        if device_id:
            queryset_list = queryset_list.filter(device_id__icontains=device_id)
        return queryset_list


class DeviceInfoListAPIView(ListAPIView):
    serializer_class = DeviceInfoSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    pagination_class = PostPageNumberPagination
    search_fields = ['device_id', 'online']

    def get_queryset(self, *args, **kwargs):
        queryset_list = DeviceInfo.objects.get_queryset().order_by('-online')
        device_id = self.request.GET.get('device_id')
        status = self.request.GET.get('status')
        if device_id:
            queryset_list = queryset_list.filter(device_id__icontains=device_id)

        if status:
            queryset_list = queryset_list.filter(online=int(status))
        return queryset_list


class DeviceLogStatisticAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        # calc total count, no cache
        total_count_queryset = [DeviceCount.objects.filter(device_id=x['device_id'],
                                                           data_time=x['max_time']).order_by('-count')[0]
                                for x in DeviceCount.objects.values('device_id').annotate(max_time=Max('data_time'))]
        if total_count_queryset:
            total_count = sum(map(lambda x: int(x.count), total_count_queryset))
        else:
            total_count = 0

        # calc daily count, put it in redis as cache.
        if cache.has_key('daily_count'):
            daily_count = cache.get('daily_count')
            pass
        else:
            tz = pytz.timezone("UTC")
            today = datetime.now(tz).date()
            midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
            one_day_ago_queryset = [DeviceCount.objects.filter(device_id=x['device_id'], data_time=x['max_time']).order_by('-count')[0]
                                    for x in DeviceCount.objects.filter(
                                        data_time__lt=midnight).values('device_id').annotate(max_time=Max('data_time'))]
            if one_day_ago_queryset:
                one_day_ago_count = sum(map(lambda x: int(x.count), one_day_ago_queryset))
                daily_count = total_count - one_day_ago_count
            else:
                daily_count = 0
            cache.set('daily_count', daily_count, 60 * 60)
        data = {'total_count': total_count, 'daily_count': daily_count}
        return Response(data)


class DeviceInfoStatisticAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        online_count = DeviceInfo.objects.filter(online=1).count()
        offline_count = DeviceInfo.objects.filter(online=0).count()
        data = {'online_count': online_count, 'offline_count': offline_count}
        return Response(data)


class LogHistoryListAPIView(ListAPIView):
    serializer_class = LogHistorySerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    pagination_class = PostLimitOffsetPagination
    search_fields = ['date']
    queryset = MosqPostStatistic.objects.all().order_by('-date')


class DeviceLogHistoryListAPIView(ListAPIView):
    serializer_class = DeviceLogHistorySerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    pagination_class = PostPageNumberPagination
    search_fields = ['device_id', 'date']

    def get_queryset(self, *args, **kwargs):
        queryset_list = DevicePostStatistic.objects.get_queryset().order_by('-date')
        device_id = self.request.GET.get('device_id')
        if device_id:
            queryset_list = queryset_list.filter(device_id__icontains=device_id)
        return queryset_list
