# coding:utf-8
"""名医大赏service"""

import os
import json
import StringIO
from datetime import datetime

from gm_types.gaia import FAMOUS_DOCTOR_JOIN_TYPE, DOCTOR_TYPE
from gm_upload import upload, IMG_TYPE

from api.tool.image_utils import get_full_path, get_w_path
from rpc.tool.log_tool import logging_exception
from rpc.tool.error_code import gen
from api.models.activities import FamousDoctorsRegistrationer
from api.models.activities import FamousDoctorRegisterItem
from api.models.activities import FamousDoctorsItemVote
from hippo.models import Hospital, Doctor
from rpc.cache import famous_doctors_cache
from api.util.wechat_util import create_wx_qarcode

from .famous_doctors_conf import list_items, get_items_dict_info


class FamousDoctorService(object):

    vote_sum = 20
    vote_item_sum = 5
    vote_info_cache_key = "famous_doctors:uv:{day}:{is_app}:{user_id}"
    vote_item_info_cache_key = "famous_doctors:uv:{day}:{doc_type}:{doc_id}:{item_id}:{is_app}:{user_id}"

    @classmethod
    def list_docs_info(cls, doc_type, doc_ids):

        docs_info = {}

        if doc_type == FAMOUS_DOCTOR_JOIN_TYPE.DOCTOR:
            doctors = Doctor.objects.filter(pk__in=doc_ids).select_related("hospital")
            for doctor in doctors:
                docs_info[doctor.id] = {
                    'id': doctor.id,
                    'name': doctor.name,
                    'portrait': doctor.portrait,
                    'hospital_id': doctor.hospital_id,
                    'hospital_name': doctor.hospital.name,
                    'hospital_portrait': doctor.hospital.portrait,
                    'good_at':  doctor.good_at or "",
                }

        elif doc_type == FAMOUS_DOCTOR_JOIN_TYPE.HOSPITAL:
            doctors = Doctor.objects.filter(doctor_type=DOCTOR_TYPE.OFFICER, hospital_id__in=doc_ids)

            docs_dict = {}
            for doctor in doctors:
                docs_dict[doctor.hospital_id] = {
                    'id': doctor.id,
                    'name': doctor.name,
                    'portrait': doctor.portrait,
                    'good_at':  doctor.good_at or "",
                }

            hospitals = Hospital.objects.filter(pk__in=doc_ids)
            for hospital in hospitals:

                officer = hospital.officer
                if officer and officer.portrait:
                    portrait = get_full_path(officer.portrait)
                elif hospital.portrait:
                    portrait = get_full_path(hospital.portrait)
                else:
                    portrait = get_w_path(u'img%2Fyiyuan.png')
                docs_info[hospital.id] = {
                    'id': hospital.id,
                    'name': hospital.name,
                    'portrait': portrait,
                    'good_at': docs_dict.get(hospital.id, {}).get('good_at', "")
                }

        return docs_info

    @classmethod
    def get_items_dict_info(cls):
        return get_items_dict_info()

    @classmethod
    def list_doctor_item_ids(cls, doc_type, doc_id):
        """获取用户参加的项目列表"""

        registrationer = cls.get_registrationer_by_doc_id(doc_type, doc_id)
        if not registrationer:
            return []

        item_ids = FamousDoctorRegisterItem.objects.filter(register_id=registrationer.id).values_list("item_id", flat=True)
        return list(item_ids)

    @classmethod
    def list_items(cls):
        return list_items()

    @classmethod
    def get_registrationer_by_doc_id(cls, doc_type, doc_id):
        try:
            return FamousDoctorsRegistrationer.objects.get(doctor_type=doc_type, doctor_id=doc_id)
        except FamousDoctorsRegistrationer.DoesNotExist:
            logging_exception()
            return None

    @classmethod
    def get_registrationer_by_id(cls, reg_id):
        try:
            return FamousDoctorsRegistrationer.objects.get(id=reg_id)
        except FamousDoctorsRegistrationer.DoesNotExist:
            logging_exception()
            return None

    @classmethod
    def join(cls, doc_type, doc_id, item_ids):
        FamousDoctorsRegistrationer.join(doc_id, doc_type, item_ids)

    @classmethod
    def clear_record(cls, doc_type, doc_id):
        FamousDoctorsRegistrationer.remove_record(doc_type, doc_id)

    @classmethod
    def is_joined(cls, doc_type, doc_id):
        """判断医生有没有报名。"""

        return FamousDoctorsRegistrationer.is_joined(doc_type, doc_id)

    @classmethod
    def init_rank(cls, doc_type, doc_id, item_ids):
        """医生报名后, 进入排行榜, 票数为0"""

        FamousDoctorsRegistrationer.init_rank(doc_type, doc_id, item_ids)

    @classmethod
    def update_rank(cls, doc_type, doc_id, item_ids, cnt=1):
        """用户投票后, 更新排行榜, 票数自增"""
        FamousDoctorsRegistrationer.update_rank(doc_type, doc_id, item_ids, cnt)

    @classmethod
    def init_rank_cache(cls):
        """全量刷新缓存。"""

        FamousDoctorsRegistrationer.init_rank_cache()

    @classmethod
    def vote_rank_and_gap(cls, doc_type, doc_id, item_id):
        '''
        根据医生id, 及奖项id获取排名 及与上一名的差距
        return: tuple(rank, gap)
            eg: (999, 5, 100)   # 999票, 第五名, 距离上一名差距100票
        '''

        vote_cnt, rank, gap = FamousDoctorsRegistrationer.vote_rank_and_gap(doc_type, doc_id, item_id)

        return vote_cnt, rank, gap

    @classmethod
    def list_rank_info(cls, doc_type, item_ids=None, offset=None, limit=None):
        """
        获取排行信息
        return {'{item_id}': [doc_id1, doc_id2...]}
        """

        return FamousDoctorsRegistrationer.list_rank_info(doc_type, item_ids, offset, limit=limit)

    @classmethod
    def list_rank_info_by_item_id(cls, doc_type, item_id, offset=0, cnt=None):
        """获取排名医生或者医院 id 列表。

        @return: list: [{"doc_id": "121212", "vote_cnt": 1}, ...]
        """

        if cnt in [None, -1]:
            limit = -1
        else:
            limit = offset + cnt

        return FamousDoctorsRegistrationer.list_rank_info_by_item_id(doc_type, item_id, offset, limit=limit)

    ##### 投票相关 #####

    @classmethod
    def vote(cls, user_id, item_id, reg_id, platform):
        """投票"""

        return FamousDoctorsItemVote.do_vote(user_id, item_id, reg_id, platform)

    @classmethod
    def add_virtual_vote(cls, doc_type, doc_id, item_id, reg_id, cnt=1):

        FamousDoctorsItemVote.add_virtual_vote(item_id, reg_id, cnt)
        cls.update_rank(doc_type, doc_id, [item_id], cnt)

    ##### 用户票数相关 #####

    @classmethod
    def user_vote_info(cls, user_id, doc_type, doc_id, item_id, is_app=True):
        """用户票数信息"""

        today = str(datetime.today().date())
        key = cls.vote_info_cache_key.format(day=today, is_app=int(is_app), user_id=user_id)
        item_key = cls.vote_item_info_cache_key.format(
            day=today, item_id=item_id, is_app=int(is_app),
            user_id=user_id, doc_type=doc_type, doc_id=doc_id,
        )

        used_vote_cnt = famous_doctors_cache.get(key)
        used_vote_cnt = int(used_vote_cnt) if used_vote_cnt else 0

        used_vote_item_cnt = famous_doctors_cache.get(item_key)
        used_vote_item_cnt = int(used_vote_item_cnt) if used_vote_item_cnt else 0

        return {
            "vote_sum": cls.vote_sum,
            "vote_item_sum": cls.vote_item_sum,
            "used_vote_cnt": used_vote_cnt,
            "used_vote_item_cnt": used_vote_item_cnt,
        }

    @classmethod
    def incr_used_vote_cnt(cls, doc_type, doc_id, user_id, item_id, is_app=True):

        today = str(datetime.today().date())
        key = cls.vote_info_cache_key.format(day=today, is_app=int(is_app), user_id=user_id)
        item_key = cls.vote_item_info_cache_key.format(
            day=today, doc_type=doc_type, doc_id=doc_id, item_id=item_id, is_app=int(is_app), user_id=user_id
        )

        cnt = famous_doctors_cache.incr(key)
        if cnt == 1:
            famous_doctors_cache.expire(key, 24 * 60 * 60)

        item_cnt = famous_doctors_cache.incr(item_key)
        if item_cnt == 1:
            famous_doctors_cache.expire(item_key, 24 * 60 * 60)

        return cnt, item_cnt

    @classmethod
    def create_wx_qr(cls, doc_type, doc_id, reg_id):

        qr_key = "famous_doctor:qr_code:{doc_type}:{doc_id}".format(doc_id=doc_id, doc_type=doc_type)
        qr_url = famous_doctors_cache.get(qr_key)
        if qr_url:
            return qr_url

        path = "packageActivity/pages/canvassing/main"
        scene = "id={reg_id}&type={doc_type}".format(reg_id=reg_id, doc_type=doc_type)

        res = create_wx_qarcode(path, scene)
        if res["errcode"] != 0:
            return ""

        wx_qr = res["buffer"]
        save_name = "famous_doctors/" + "{doc_type}_{doc_id}_qr.png".format(doc_type=doc_type, doc_id=doc_id)
        img = StringIO.StringIO(wx_qr)
        try:
            url = upload(img, IMG_TYPE.NOWATERMARK, save_name=save_name)
            famous_doctors_cache.set(qr_key, url)
            return url
        except:
            logging_exception()
            return ""
