#!/usr/bin/env python
# coding=utf-8
import datetime

from django.conf import settings

from api.models import Doctor, Order, RefundOrder, Reservation, Service

from rpc.cache import unread_cache
from rpc.tool.log_tool import doctor_unread_logger

from gm_types.gaia import NOTIFY_EVENT
from gm_types.gaia import ORDER_STATUS, REFUND_STATUS, RESERVATION_STATUS

from services.unread.base import BaseUnread


class _Unread(BaseUnread):
    """
        1. event有新的operation，删除缓存未读数，并通知poll
        2. get由client主动请求，缓存没有，计算一次
    """

    def _get_unread(self, event, *args, **kwargs):
        key = self.gen_cache_key(event, *args, **kwargs)
        unread = unread_cache.get(key)
        if unread is not None:
            unread = int(unread)
        else:
            unread_info = u'get_unread_from_cache, key is {}, cache is delete'.format(key)
            doctor_unread_logger.info(unread_info)

        return key, unread


class UserUnread(_Unread):

    def __init__(self, user_id):
        self.user_id = user_id

    def _get_user_unread(self, event, *args, **kwargs):
        """
            !!! 用户使用 _get_user_unread 获取未读
            不要使用 _get_unread
        """
        return self._get_unread(event, *args, is_user=True, **kwargs)

    def get_conversation_unread(self, conversation_id, default=0):
        """
            返回单个私信未读数
        """
        name, key = self.gen_conversation_key(conversation_id)
        unread = unread_cache.hget(name, key) or 0
        if unread == 0 and default > 0:
            unread = default
            unread_cache.hsetnx(name, key, default)
        else:
            unread = int(unread)
        return unread

    def get_conversation_all_unread(self):
        """
            返回私信所有未读总数
            1. 先get取缓存看是否有
            2. 再考虑取出hgetall所有缓存进行计算一次
        """
        self._reload_user()
        key, unread = self._get_user_unread(NOTIFY_EVENT.CONVERSATION)
        if unread is None:
            name, _ = self.gen_conversation_key()
            info = unread_cache.hgetall(name)
            unread = 0
            for (k, v) in info.items():
                unread += int(v)
            unread_cache.set(key, unread, ex=self._cache_time, nx=True)
        return unread

    @classmethod
    def get_all_conversation_unread_num_by_ids(cls, user_ids):
        """批量获取所有未读数  针对拜博大集团优化"""
        result = {}
        cache_key_format = 'user:{}' + ':{}'.format(NOTIFY_EVENT.CONVERSATION)
        cache_key_list = []
        for user_id in user_ids:
            _cache_key = cache_key_format.format(user_id)
            cache_key_list.append(_cache_key)
        if not cache_key_list:
            return result
        cache_res = unread_cache.mget(cache_key_list)
        for user_id, unread_num in zip(user_ids, cache_res):
            if unread_num is None:
                unread_num = cls(user_id=user_id).get_conversation_all_unread()
            result[user_id] = int(unread_num)
        return result


class DoctorUnread(UserUnread):

    def __init__(self, doctor_id):
        self.user_id = None
        self.doctor_id = doctor_id

    def get_order_unread(self):
        # 20200306优化： service 表 inner join order表查询  改成 分两步查询，同时针对 order.status 字段加索引
        # 修改方案wiki：
        key, unread = self._get_unread(NOTIFY_EVENT.ORDER)
        if unread is None:
            services = Service.objects.filter(doctor_id=self.doctor_id).values('id')
            services_ids = [s['id'] for s in services]
            orders = Order.objects.filter(service_id__in=services_ids, status=ORDER_STATUS.PAID)
            order_time_key = self.gen_order_viewtime_key(key)
            time_record = unread_cache.get(order_time_key)
            if time_record:  # 若是查看过，从上次看的时间开始计算
                orders = orders.filter(pay_time__gt=datetime.datetime.strptime(time_record, self._time_fmt))
            unread = orders.count()
            unread_cache.set(key, unread, self._cache_time)
        return unread

    def get_refund_unread(self):
        key, unread = self._get_unread(NOTIFY_EVENT.REFUND)
        if unread is None:
            # 医生只能处理48小时之内的
            time_limit = datetime.datetime.now() - datetime.timedelta(hours=settings.DOCTOR_HANDLE_TIME)
            unread = RefundOrder.objects.filter(
                order__service__doctor_id=self.doctor_id,
                status=REFUND_STATUS.PROCESSING,
                lastest_apply_refund__gte=time_limit,
            ).count()
            unread_cache.set(key, unread, self._cache_time)
        return unread

    def get_reserve_unread(self):
        """
            预约的未读数目
        """
        key, unread = self._get_unread(NOTIFY_EVENT.RESERVE)
        if unread is None:
            unread = Reservation.objects.filter(
                schedule__doctor_id=self.doctor_id,
                status=RESERVATION_STATUS.RESERVING,
            ).count()
            unread_cache.set(key, unread, self._cache_time)
        return unread

    @classmethod
    def get_all_conversation_unread_num_by_ids(cls, doctor_ids):
        """批量获取所有未读数  针对拜博大集团优化"""
        user_ids = list(Doctor.objects.filter(id__in=doctor_ids).values_list('user_id', flat=True))
        return UserUnread.get_all_conversation_unread_num_by_ids(user_ids)
