# coding=utf-8

import json
import hashlib
import six

import redis
from django.conf import settings


class _PoolMinx(object):
    pool = redis.ConnectionPool(**settings.REDIS['view'])
    client = redis.Redis(connection_pool=pool)


class ViewRecord(_PoolMinx):
    def __init__(self, model_name):
        self.model_name = model_name

    def __getitem__(self, item):
        return self.client.hget(self.model_name, item) or 0

    def __setitem__(self, key, value):
        return self.client.hset(self.model_name, key, value)


# class DiaryPV(_PoolMinx):
#     _prefix = 'diary_pv'
#
#     def get_k(self, diary_id):
#         k = '%s:%s' % (self._prefix, diary_id)
#         return k
#
#     def get(self, diary_id):
#         k = self.get_k(diary_id)
#         return self.client.get(k)
#
#     def set(self, diary_id, value):
#         k = self.get_k(diary_id)
#         return self.client.set(k, value)
#
#     def incrby(self, diary_id, num=1):
#         k = self.get_k(diary_id)
#         self.client.incrby(k, num)


class _RedisProxy(object):
    """redis proxy add prefix automatically."""

    __connect_class = redis.StrictRedis
    __pool = redis.ConnectionPool(**settings.DEFAULT_REDIS)
    _client = __connect_class(connection_pool=__pool)

    # add methods those are need to be hacked here
    _hacked_methods = [
        'set', 'get', 'setex', 'hget', 'hset', 'hincrby', 'hdel', 'hgetall',
        'smembers', 'sadd', 'incr', 'delete', 'expire', 'expireat', 'decr',
        'lpush', 'lrange', 'lrem', 'llen', 'sadd', 'srem', 'scard',
        'sismember', 'rpop', 'keys', 'rpush', 'lpop', 'hmset', 'hmget',
        'exists', 'mget', 'hkeys', 'srandmember'
    ]

    def __getattribute__(self, name):
        attr = getattr(object.__getattribute__(self, '_client'), name)

        if name in _RedisProxy._hacked_methods:
            def newfunc(k, *args, **kwargs):
                prefix = object.__getattribute__(self, 'prefix')
                if isinstance(k, six.string_types):
                    k = prefix + ':' + k
                elif isinstance(k, list):
                    k = [prefix + ':' + _k for _k in k]
                else:
                    raise TypeError("must be str or list")
                result = attr(k, *args, **kwargs)
                return result

            return newfunc

        return attr

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

    @classmethod
    def get_client(cls, prefix=''):
        return cls(prefix)


class _LiveRedisProxy(object):
    """redis proxy add prefix automatically."""
    __connect_class = redis.StrictRedis
    __pool = redis.ConnectionPool(**settings.LIVE_REDIS)
    _client = __connect_class(connection_pool=__pool)

    # add methods those are need to be hacked here
    _hacked_methods = [
        'set', 'get', 'setex', 'hget', 'hset', 'hincrby', 'hdel', 'hgetall',
        'smembers', 'sadd', 'incr', 'delete', 'expire', 'decr',
        'lpush', 'lrange', 'lrem', 'llen', 'sadd', 'srem', 'scard',
        'sismember', 'rpop', 'keys', 'rpush', 'zadd', 'lpop', 'hmset'
    ]

    def __getattribute__(self, name):
        attr = getattr(_LiveRedisProxy._client, name)

        if name in _LiveRedisProxy._hacked_methods:
            def newfunc(k, *args, **kwargs):
                prefix = object.__getattribute__(self, 'prefix')
                k = prefix + ':' + k
                result = attr(k, *args, **kwargs)
                return result

            return newfunc

        return attr

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

    @classmethod
    def get_client(cls, prefix=''):
        return cls(prefix)


class _PunishmentProxy(_RedisProxy):
    _pool = redis.ConnectionPool(**settings.PUNISHMENT_REDIS)
    _client = redis.StrictRedis(connection_pool=_pool)


class _UserInfoProxy(_RedisProxy):
    _pool = redis.ConnectionPool(**settings.REDIS['user_cache'])
    _client = redis.StrictRedis(connection_pool=_pool)


def add_limit_num(key, timeout, max_num):
    """
    固定时间限制次数公共缓存 key最好带上模块名
    """
    times = get_limit_num(key)
    if times < max_num:
        limit_num_cache.setex(key, timeout, times + 1)
    else:
        pass


def get_limit_num(key):
    res = limit_num_cache.get(key)
    if res:
        return int(res)
    else:
        return 0


def make_cache_key(f, **kwargs):
    method_url = "%s.%s?%s" % (f.__module__, f.__name__, json.dumps(kwargs, sort_keys=True))
    method_md5 = hashlib.md5(method_url).hexdigest()
    cache_key = "cache:%s:rpc:%s" % (method_md5, settings.VERSION)
    return cache_key


_redis_proxy = _RedisProxy.get_client
_punishment_proxy = _PunishmentProxy.get_client
_user_info_proxy = _UserInfoProxy.get_client

user_cache = _redis_proxy("user_cache")
push_cache = _redis_proxy("push_cache")
code_cache = _redis_proxy("code")
count_cache = _redis_proxy("count")
servicehome_cache = _redis_proxy('servicehome')
filter_cache = _redis_proxy('filter')
hospital_cache = _redis_proxy("hospital")
req_data_cache = _redis_proxy("req_data")
feedback_msg_cache = _redis_proxy("feedback_msg")
topic_sug_cache = _redis_proxy('topic_sug')
itemwiki_hot_cache = _redis_proxy('itemwiki_hot')
itemwiki_cache = _redis_proxy('itemwiki')
send_cache = _redis_proxy('sms')
consult_cache = _redis_proxy('consult')
service_template_images = _redis_proxy('service_template_images')
doctor_switch_cache = _redis_proxy('doctor_switch')
business_select_cache = _redis_proxy('business_select')
recommend_cache = _redis_proxy("recommend")
gadget_cache = _redis_proxy('gadget')  # 首页/美购首页/社区首页组件化cache
index_func_cache = _redis_proxy('index_func') # 首页功能区
sideslip_cache = _redis_proxy('sideslip')   # 首页按钮横滑
doctor_tags_cache = _redis_proxy('doctor_tags')
doctor_tagv3s_cache = _redis_proxy('doctor_tagv3s')
hospital_tags_cache = _redis_proxy('hospital_tags')
doctor_patient_cache = _redis_proxy('doctor_patient')  # 医生患者缓存list
limit_num_cache = _redis_proxy('limit_num')  # 限制次数
data_transfer_cache = _redis_proxy('data_trans')  # 搜索data-transfer用cache
hospital_doctor_service_cache = _redis_proxy('hospital_doctor_service')
installment_cache = _RedisProxy('installment')
follow_cache = _RedisProxy('new_follow')
model_cache = _redis_proxy('model_c')
email_cache = _redis_proxy('email')
tag_child_tags_cache = _redis_proxy('tag_child_tags')
unread_cache = _redis_proxy('unread')
doctor_traffic_cache = _redis_proxy('real_traffic')
sleep_user_cache = _redis_proxy('sleep_user')
doctor_discount_cache = _redis_proxy('doctor_discount')
tag_top_sale_cache = _redis_proxy('tag_top_sale')
service_home_city_cache = _redis_proxy('service_home_city')
doctor_service_tags_distribution_cache = _redis_proxy('doctor_service_tags_distribution')
hospital_service_tags_distribution_cache = _redis_proxy('hospital_service_tags_distribution')
ai_pop_windows_cache = _redis_proxy('ai_pop_windows_cache')

shop_cart_cache = _redis_proxy('shopcart')

service_info_list_cache = _redis_proxy('service_info_list')

wechatpub_cache = _redis_proxy('wxpub')

search_dic_cache = _redis_proxy('search_dic')  # 搜索引擎词典用cache

sleep_action_fans_cache = _redis_proxy('sleep_action_fans_cache')
sleep_noaction_fans_cache = _redis_proxy('sleep_noaction_fans_cache')
# todo update in 7660 mimas 维护，不要再写入！不要再写入！不要再写入！  ******start*******
# _pool = redis.ConnectionPool(**settings.REDIS['vote_cache'])
# vote_cache = redis.StrictRedis(connection_pool=_pool)
diary_heat_score_cache = _redis_proxy('diary_heat')  # todo  等待hera迁移完
take_sofa_diary_cache = _redis_proxy('take_sofa_diary')  # todo  等待hera迁移完
# wechat_cache = _redis_proxy('wechat')
# diary_pv_cache = DiaryPV()

# todo update in 7660 mimas 维护，不要再写入！不要再写入！不要再写入！  ******end*******
page_cache = redis.StrictRedis(**settings.REDIS['page_cache'])
price_cache = _redis_proxy('price_cache')
service_feature_cache = _redis_proxy('service_feature_cache')

# add for young_doctor vote
yd_vote = _redis_proxy('yd_vote')

seo_cache = _redis_proxy('seo')

service_config_cache = _redis_proxy('service_config')
addfans_config_cache = _redis_proxy('addfans_config')

doctor_search_tags_cache = _redis_proxy('doctor_search_tags')
hospital_search_tags_cache = _redis_proxy('hospital_search_tags')
special_service_list_cache = _redis_proxy('special_service_list')
service_score_tag_avg = _redis_proxy('service_score_tag_avg')
share_diary_num_cache = _redis_proxy('share_diary_num_cache')

coupon_cache = _redis_proxy('coupon')

index_tab_cache = _redis_proxy('index_tab')  # 首页顶部横滑tab配置
multitopic_cache = _redis_proxy('multitopic')
coupon_badge_cache = _redis_proxy('coupon_badge')
doctor_badge_cache = _redis_proxy('doctor_badge')

# high_quality_question_cache = _redis_proxy('high_quality_question_cache')
doctor_sell_amount_cache = _redis_proxy('doctor_sell_amount_cache')
hospital_sell_amount_cache = _redis_proxy('hospital_sell_amount_cache')

mid_autumn_answer_record_cache = _redis_proxy('mid_autumn_answer_record')  # 中秋活动，只有成功的才记录

punishment_cache = _punishment_proxy('pilot:m')  # 美购纬度
punishment_diary_cache = _punishment_proxy('pilot:d:m')  # 日记纬度

billapplyrecord_cache = _redis_proxy('billapplyrecord')

citycache = _redis_proxy('index_city')

popup_cache = _redis_proxy('popup')

rankcache = _redis_proxy("rank")

recommend_college_cache = _redis_proxy("recommend_colleges")  # 推荐大学

serviceregister_activity_status_cache = _redis_proxy("serviceregister_activity_status")  # 美购提报状态

common_cache = _redis_proxy("common")
qq_city_cache = _redis_proxy("qq_city_name")  # 记录经纬度与城市名称映射
city_info_cache = _redis_proxy("city_info")  # 城市信息

variety_cache = _redis_proxy("variety_vote")
groupbuy_cache = _redis_proxy('groupbuy')
lipstick_cache = _redis_proxy('lipstick')
diary_cache = _redis_proxy('diary')
sign_cache = _redis_proxy('sign')
new_spring_click = _redis_proxy('newspring_click')
wechat_auth_cache = _redis_proxy('wechat_auth')
hera_feeds_cache = _redis_proxy('hera_feeds')  #首页二期改版，feed策略
young_doc_cache = _redis_proxy('yd')           # 青年医生1905
famous_doctors_cache = _redis_proxy('famous_doctors')  # famous_doctors
browsing_message_cache = _redis_proxy('browsing_message')    #商户每日主动私信
old_new_tag_mapping_cache = _redis_proxy('old_new_tag_mapping')

smark_rank_cache = _redis_proxy('smark_rank')
channel_cache=_redis_proxy('channel_cache')
slide_cache=_redis_proxy('slide_cache')
sign_rush_cache = _redis_proxy('sign_rush_cache')
sign_task_cache = _redis_proxy('sign_task_cache')
sku_stock_lock = _redis_proxy('sku_stock_lock')
group_cache = _redis_proxy("group_cache")

personal_slide_cache = _redis_proxy("personal_slide_cache")
personal_slide_cache_image = _redis_proxy("personal_slide_cache_image")

tag_map_tag3_record = _redis_proxy("tag_map_tag3_record")
ai_qa_msg_cache = _redis_proxy("ai_qa_msg_cache")  # AI问答相关缓存

scan_skin_video_unlock_cache = _redis_proxy("scan_skin_video_unlock")  # AI精选视频解锁缓存

user_directional_push_cache = _redis_proxy("user_directional_push_cache")  # 关闭用户使用定向推送功能
user_cancellation_cache = _redis_proxy("user_cancellation")  # 用户注销记录
conversation_cache = redis.StrictRedis(**settings.REDIS['conversation_cache'])
puppet_users_cache = _redis_proxy("puppet_users_cache")  # 马甲用户池缓存
user_fundamental_cache = _user_info_proxy("user_fundamental")
