#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import, print_function
import datetime

from django.conf import settings
from django.db.models import Q
from itertools import chain

from gm_rpcd.all import bind
from gm_types.error import ERROR
from gm_types.mimas import TRACTATE_PLATFORM, SOFT_ARTICLE_TYPE, SOFT_ARTICLE_RELATION_TYPE, TRACTATE_STATUS, SOFT_ARTICLE_ORDER
from gm_types.error import ERROR as CODES
from gm_rpcd.all import RPCDFaultException

from qa.utils.decorator import listing
from talos.models.diary.diary import Diary
from talos.services import UserService, TagService, GoodsService, DoctorService
from talos.services.soft_article.soft_article import (
    SoftArticleService, SoftArticleRelation, SoftArticle, SoftArticleImages, SoftArticleVideo
)
from talos.models.soft_article.check import SoftArticleCheck
from talos.services.soft_article.vote import SoftArticleVoteService
from talos.services.soft_article.favor import SoftArticleFavorService
from utils.rpc import get_current_user, gen


def handle_args(conditions, merchant_id):
    base_query = Q()
    if conditions.get("id"):
        base_query &= Q(id=int(conditions.get("id")))
    if conditions.get("doctor_id"):
        base_query &= Q(doctor_id=conditions.get("doctor_id"))
    if conditions.get("status", None) != None:
        base_query &= Q(status=conditions.get("status"))
    if conditions.get("start_time"):
        times = datetime.datetime.fromtimestamp(conditions.get("start_time"))
        base_query &= Q(create_time__gte=times)
    if conditions.get("end_time"):
        times = datetime.datetime.fromtimestamp(conditions.get("end_time"))
        base_query &= Q(create_time__lte=times)
    if conditions.get("is_online", None) != None:
        base_query &= Q(hera_is_online=int(conditions.get("is_online")))
    if conditions.get("title"):
        s_ids = SoftArticle.objects.using(settings.SLAVE_DB_NAME).filter(merchant_id=merchant_id,
                                                                         title__contains=conditions.get("title")).\
                                                                  values_list('id', flat=True)
        base_query &= Q(id__in=s_ids)

    return base_query


def handle_realtions_args(conditions):
    """美购、日记本筛选"""
    base_query = Q()

    if conditions.get("diary_id"):
        dairy_relations = SoftArticleRelation.objects.filter(relation_id=conditions.get("diary_id"),
                                                             relation_type=SOFT_ARTICLE_RELATION_TYPE.DIARY)\
                                                     .values_list('id', flat=True)
        base_query &= Q(id__in=list(dairy_relations))
    if conditions.get("service_id"):
        service_relations = SoftArticleRelation.objects.filter(relation_id=conditions.get("service_id"),
                                                               relation_type=SOFT_ARTICLE_RELATION_TYPE.SERVICE) \
                                                       .values_list('id', flat=True)
        base_query &= Q(id__in=list(service_relations))

    return base_query


@bind("mimas/soft_article/list")
def get_soft_article_list(merchant_id, article_type, page=1, count=10, conditions={}):
    """医生后台专用"""
    result, doctor_ids = [], []
    r_query = handle_realtions_args(conditions)
    s_query = handle_args(conditions, merchant_id)
    offset = (page - 1) * count

    if conditions.get("service_id") or conditions.get("diary_id"):
        s_ids = SoftArticleRelation.objects.filter(r_query).values_list('softarticle_id', flat=True)
        s_ids = list(set(s_ids))
        s_query &= Q(id__in=s_ids)
    s_all = SoftArticle.objects.filter(s_query, merchant_id=merchant_id, article_type=article_type).order_by('show_order', '-id')
    s_infos = s_all[offset:offset+count]
    soft_article_ids = []

    for s_info in s_infos:
        doctor_ids.append(s_info.doctor_id)
        soft_article_ids.append(s_info.id)
        result.append(SoftArticleService.get_base_info(s_info))

    doctor_infos = DoctorService.get_doctor_by_doctor_ids_v1(doctor_ids)

    s_relations = SoftArticleService.get_relation_data(soft_article_ids=soft_article_ids)
    check_status = SoftArticleCheck.objects.filter(softarticle_id__in=soft_article_ids).values('softarticle_id', 'is_online')
    check_dict = {status.get('softarticle_id'): status.get('is_online') for status in check_status}

    _relation_default_dic = {
        'tag_data': [],
        'service': {},
        'diary': {},
    }
    for info in result:
        s_id = info.get('softarticle_id')
        info['doctor_name'] = doctor_infos[info.get('doctor_id')]['meta']['name'] if doctor_infos.get(info.get('doctor_id')) else ''
        info['hera_is_online'] = check_dict.get(s_id) or False
        _relation_dic = s_relations.get(s_id) or _relation_default_dic
        info.update(_relation_dic)

    return {'total': s_all.count(), 'data': result}


@bind("mimas/soft_article/create_update")
def create_update_artcle(merchant_id, doctor_id, soft_article_info, article_type, soft_article_id=None):
    """医生后台创建or修改"""
    if not soft_article_id:
        article = SoftArticleService.create(content=soft_article_info.get('content'), article_type=article_type,
                                            title=soft_article_info.get('title'), doctor_id=doctor_id,
                                            extra=soft_article_info, merchant_id=merchant_id)
    else:
        article = SoftArticleService.update(merchant_id=merchant_id,
                                            soft_article_id=soft_article_id,
                                            content=soft_article_info.get('content'),
                                            title=soft_article_info.get('title'),
                                            doctor_id=doctor_id, extra=soft_article_info)

    return article


@bind('mimas/soft_article/article_top')
def content_top(soft_article_id, show_order):
    """
    医生后台置顶操作
    :return:
    """

    if not soft_article_id or not show_order:
        return gen(CODES.PARAMS_INCOMPLETE)

    s_article = SoftArticle.objects.filter(id=int(soft_article_id)).first()
    if not s_article.doctor_id:
        return gen(CODES.DOCTOR_NOT_FOUND)

    order_count = SoftArticle.objects.filter(doctor_id=s_article.doctor_id, show_order=int(show_order)).count()

    if int(show_order) != SOFT_ARTICLE_ORDER.UNSET and order_count >= 5:
        raise RPCDFaultException(
            code=ERROR.UNIVERSAL,
            message="置顶数目超过限制",
        )

    SoftArticle.objects.filter(id=int(soft_article_id)).update(show_order=int(show_order),
                                                               last_modified=datetime.datetime.now())

    return {"status": 1}


@bind('mimas/soft_article/control_online')
def control_online(soft_article_id):
    s_article = SoftArticle.objects.filter(id=int(soft_article_id)).first()
    if not s_article:
        return gen(CODES.PARAMS_INCOMPLETE)

    s_article.is_online = False if s_article.is_online else True
    s_article.online_time = datetime.datetime.now()

    s_check = SoftArticleCheck.objects.filter(softarticle_id=int(soft_article_id)).first()
    if s_check and s_check.is_online and s_article.is_online:
        s_article.hera_is_online = True
        s_article.save()
    else:
        s_article.hera_is_online = False
        s_article.save()
    return {"status": 1}


def update_article_special_info(soft_article_list, soft_article_ids, user_id):
    """
    更新新帖子交互数据
    :param tractate_list:
    :param tractate_ids:
    :param user_id:
    :return:
    """
    softarticle_ids = list(map(int, filter(None, soft_article_ids)))
    voted_dic = user_id and SoftArticleVoteService.get_softarticle_voted_info_for_user(softarticle_ids, user_id) or {}
    favored_dic = user_id and SoftArticleFavorService.get_soft_article_favord_info_for_user(soft_article_ids, user_id) or {}

    for article_info in soft_article_list:
        _article_id = article_info.get("softarticle_id", 0)
        article_info.update({
            "is_voted": voted_dic.get(_article_id, False),
            "is_favored": favored_dic.get(_article_id, False),
        })

    return soft_article_list


@bind('mimas/soft_article/get_by_id')
def get_article_by_id(soft_article_id):
    """获取基础数据"""
    if not soft_article_id:
        return gen(CODES.PARAMS_INCOMPLETE)
    article = SoftArticleService.get_by_id(pk=soft_article_id)
    article_info = SoftArticleService.get_base_info(article)
    relation_data = SoftArticleService.get_relation_data(soft_article_ids=[article.id])
    article_info['service'] = relation_data[article.id].get('service')
    article_info['diary'] = relation_data[article.id].get('diary')
    article_info['tag_data'] = relation_data[article.id].get('tag_data')
    doctor_dic = DoctorService.get_doctor_by_doctor_ids_v1(doctor_ids=[article_info.get('doctor_id')])
    article_info['doctor_name'] = doctor_dic[article.doctor_id]['meta']['name'] if doctor_dic.get(article.doctor_id) else ''
    if article.article_type == SOFT_ARTICLE_TYPE.VIDEO:
        video_info = SoftArticleVideo.objects.filter(softarticle_id=article.id).first()
        article_info.update({
            "video_url": video_info.raw_video_url,
            "img_url": video_info.upload_img_cover,
        })
    else:
        img_info = SoftArticleImages.objects.filter(softarticle_id=article.id).first()
        article_info.update({
            "img_url": img_info.image_url
        })

    if article.status == TRACTATE_STATUS.AUDIT_REJECT:
        check = SoftArticleCheck.objects.filter(softarticle_id=article.id).first()
        article_info['reason'] = check.check_content if check else ""
    return article_info


@bind('mimas/soft_article/list_by_ids')
def soft_article_list_by_ids(soft_article_ids, need_special_info=False, list_for_detail=False):
    """
    医生帖，卡片列表
    :param soft_article_ids:
    :param need_special_info: 是否需要交互信息
    :param list_for_detail: 是否是详情页展示的数据
    :return:
    """
    result = {
        "article_list": [],
    }

    if soft_article_ids:
        assert len(soft_article_ids) <= settings.COUNT_LIMIT, 'too many soft_article_ids'

        user = get_current_user()
        _user_id = user and user.id or None
        # 先获取有序对象
        soft_article_queryset = SoftArticleService.get_soft_article_objs_by_ids(soft_article_ids)
        # 在处理数据
        if list_for_detail:
            article_info_dic = SoftArticleService.get_soft_article_info_for_detail_by_obj_list(
                soft_article_queryset,
                user_id=_user_id,
                need_special_info=need_special_info
            )
        else:
            article_info_dic = SoftArticleService.get_soft_article_info_for_card_by_obj_list(
                soft_article_queryset,
                user_id=_user_id,
                need_special_info=need_special_info
            )
        article_info_list = article_info_dic.get("soft_article_list", [])
        valid_soft_article_ids = article_info_dic.get("valid_soft_article_ids", [])

        if need_special_info:
            article_info_list = update_article_special_info(article_info_list, valid_soft_article_ids, _user_id)

        # 增加帖子浏览量
        SoftArticleService.soft_article_view_increase_num(valid_soft_article_ids)

        result["article_list"] = article_info_list

    return result


@bind('mimas/soft_article/only_achieve_relation_ids')
def only_get_soft_article_relation_ids_by_ids(soft_article_ids, relation_type, return_dic=False):
    """
    仅获取医生帖关联的 标签，美购 id
    :param soft_article_ids:
    :param relation_type:
    :return:
    """
    if not soft_article_ids:
        return []

    if relation_type not in [SOFT_ARTICLE_RELATION_TYPE.SERVICE, SOFT_ARTICLE_RELATION_TYPE.DIARY, SOFT_ARTICLE_RELATION_TYPE.TAG]:
        return gen(ERROR.DATA_SOURCE_NOT_CORRECT)

    result = SoftArticleService.get_soft_article_relation_ids_by_soft_acticle_ids(
        soft_article_ids,
        relation_type
    )

    if return_dic:
        return result
    else:
        return list(chain(*result.values()))
