#!/usr/bin/env python
# -*- coding: utf-8 -*-

from urllib.parse import urljoin

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

from gm_dataquery.dataquery import DataBuilder, DataSQLQuery
from gm_dataquery.db import DB
from gm_dataquery.dict_mixin import to_dict
from gm_types.gaia import DOCTOR_TYPE, MEMBERSHIP_LEVEL, USER_CLASSIFY

from gm_types.mimas import (
    TRACTATE_CONTENT_LEVEL,
    TRACTATE_STATUS,
    TRACTATE_PLATFORM,
    SOFT_ARTICLE_RELATION_TYPE,
    SOFT_ARTICLE_TYPE,
)

from talos.models.soft_article import SoftArticleReply
from talos.models.tractate import (
    Tractate,
    TractateExtra,
    TractateTag,
    TractateImages,
    TractateVideo,
    TractateReply,
    TractateCheck,
    TractateNewTag,
    TractateTagV3,
)
from talos.rpc import get_current_rpc_invoker
from talos.services import DoctorService
from talos.models.diary.diary import Diary
from talos.models.soft_article.soft_article import SoftArticle, SoftArticleRelation, SoftArticleImages, SoftArticleVideo
from talos.models.soft_article.check import SoftArticleCheck
from talos.services.agile_tag import AgileTagService
from talos.services.tag import TagService
from talos.services.user import UserService
from talos.services.hospital import HospitalService
from talos.services.goods import GoodsService


rpc_client = get_current_rpc_invoker()


class TractateDB(DataBuilder):
    def getval_tags(self, obj):
        tags = list(TractateTag.objects.filter(
            tractate_id=obj.id).values_list("tag_id", flat=True))
        return tags

    def getval_new_tags(self, obj):
        tags = list(TractateNewTag.objects.filter(
            tractate_id=obj.id).values_list("tag_id", flat=True))
        return tags

    def getval_tags_name(self, obj):
        relation_tags = list(TractateTag.objects.filter(tractate_id=obj.id).values_list("tag_id", flat=True))
        tag_info_list = TagService.get_tags_by_tag_ids(relation_tags)
        return "、".join([tag.name for tag in tag_info_list])

    def getval_new_tags_name(self, obj):
        relation_tags = list(TractateNewTag.objects.filter(tractate_id=obj.id).values_list("tag_id", flat=True))
        tag_info_dic = AgileTagService.get_agile_tags_by_agile_tag_ids(relation_tags)
        return "、".join([tag.name for tag in tag_info_dic.values()])

    def getval_like_num(self, obj):
        return obj.vote_amount

    def getval_favor_num(self, obj):
        return obj.favor_amount

    def getval_reply_num(self, obj):
        return obj.reply_amount

    def getval_fake_reply_num(self, obj):
        return TractateReply.objects.filter(tractate_id=obj.id, is_fake=True).count()

    def getval_images(self, obj):
        return list(TractateImages.objects.filter(tractate_id=obj.id).values_list("image_url", flat=True))

    def getval_video_url(self, obj):
        video_obj = TractateVideo.objects.filter(tractate_id=obj.id, is_online=True).first()
        video_url = ''
        if video_obj:
            _url = video_obj.raw_video_url
            if _url:
                video_url = urljoin(settings.VIDEO_HOST, _url)
        return video_url

    def getval_tractate_id(self, obj):
        return obj.id

    def getval_user_name(self, obj):
        user = UserService.get_user_by_user_id(user_id=obj.user_id)
        return user.nickname

    def getval_is_talent(self, obj):
        user = UserService.get_user_by_user_id(user_id=obj.user_id)
        return True if user.membership_level == MEMBERSHIP_LEVEL.STAR else False

    def getval_user_level(self, obj):
        user = UserService.get_user_by_user_id(user_id=obj.user_id)
        return user.user_rights_level

    def getval_status_desc(self, obj):
        return TRACTATE_STATUS.getDesc(key=obj.status)

    def getval_doctor_type(self, obj):
        doctor = DoctorService.get_doctor_by_user_id(obj.user_id)
        return DOCTOR_TYPE.getDesc(key=doctor.doctor_type)

    def getval_low_quality(self, obj):
        return obj.low_quality

    def getval_low_quality_deal(self, obj):
        return obj.low_quality_deal

    def getval_platform(self, obj):
        return obj.platform

    def getval_tag_v3_ids(self, obj):
        return list(TractateTagV3.objects.filter(tractate_id=obj.id).values_list("tag_v3_id", flat=True))


@DB
class TractateDQ(DataSQLQuery):
    model = Tractate
    data_model = TractateDB
    default_using = getattr(settings, 'SLAVE_DB_NAME', '')

    def filter_user_id(self, srch_key, srch_val, regex=False):
        return Q(user_id=srch_val)

    def filter_last_modified(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_content_level(self, srch_key, srch_val, regex=False):
        return Q(content_level=srch_val)

    def filter_user_type(self, srch_key, srch_val, regex=False):
        if srch_val == USER_CLASSIFY.NORMAL:
            resp = rpc_client['api/user_classify/ids']().unwrap()
            user_ids = resp.get('user_ids', [])
            resp = rpc_client['api/person/puppet_user']().unwrap()
            user_ids.extend(resp.get('puppet_ids', []))
            return ~Q(user_id__in=user_ids)

        elif srch_val == USER_CLASSIFY.MODEL:
            resp = rpc_client['api/user_classify/ids']().unwrap()
            user_ids = resp.get('user_ids', [])
            return Q(user_id__in=user_ids)
        else:
            return Q()

    def filter_low_quality(self, srch_key, srch_val, regex=False):
        if srch_val == '1':
            return Q(low_quality__gte=1)
        elif srch_val == '0':
            return Q(low_quality=0)

    def filter_low_quality_deal(self, srch_key, srch_val, regex=False):
        if srch_val == '1':
            return Q(low_quality_deal=True)
        elif srch_val == '0':
            return Q(low_quality_deal=False)

    def filter_tags(self, srch_key, srch_val, regex=False):
        tractate_ids = list(TractateTag.objects.filter(
            tag_id=int(srch_val)
        ).values_list('tractate_id', flat=True))
        return Q(id__in=tractate_ids)

    def filter_new_tags(self, srch_key, srch_val, regex=False):
        tractate_ids = list(TractateNewTag.objects.filter(
            tag_id=int(srch_val)
        ).values_list('tractate_id', flat=True))
        return Q(id__in=tractate_ids)

    def filter_tag_v3_ids(self, srch_key, srch_val, regex=False):
        tractate_ids = list(TractateTagV3.objects.filter(
            tag_v3_id=int(srch_val)
        ).values_list('tractate_id', flat=True))
        return Q(id__in=tractate_ids)

    def filter_platform(self, srch_key, srch_val, regex=False):
        return Q(platform=srch_val)

    def filter_tag_type(self, srch_key, srch_val, regex=False):
        # 根据标签类型筛选
        resp = rpc_client['api/tag_v3/by_type'](tag_type=int(srch_val)).unwrap()
        tag_v3_ids = resp.get('tag_v3_ids', [])
        tractate_ids = list(TractateTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
            tag_v3_id__in=tag_v3_ids
        ).values_list('tractate_id', flat=True))

        return Q(id__in=tractate_ids)


class ReplyDB(DataBuilder):

    def getval_action(self, obj):
        tractate = Tractate.objects.get(id=obj.tractate_id)
        reply = TractateReply.objects.filter(replied_id=obj.id, tractate_id=tractate.id, source_id=TRACTATE_PLATFORM.HERA, is_online=True, user_id=tractate.user_id).exists()

        if reply:
            return "已回复"
        else:
            return "回复"

    def getval_reply_id(self, obj):
        return str(obj.id)

    def getval_tractate_user_id(self, obj):
        return Tractate.objects.get(id=obj.tractate_id).user_id

    def getval_tractate_platform(self, obj):
        tractate = Tractate.objects.filter(id=obj.tractate_id, platform=TRACTATE_PLATFORM.HERA).exists()

        if tractate:
            return 1
        else:
            return 0

    def getval_tractate_title(self, obj):
        t = Tractate.objects.get(id=obj.tractate_id)
        return t.title or t.content[:20]

    def getval_replied_user_id(self, obj):
        if obj.replied_id:
            return TractateReply.objects.get(id=obj.replied_id).user_id
        return ''


@DB
class ReplyDQ(DataSQLQuery):
    model = TractateReply
    data_model = ReplyDB

    def filter_create_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_user_type(self, srch_key, srch_val, regex=False):
        if srch_val == USER_CLASSIFY.NORMAL:
            resp = rpc_client['api/user_classify/ids']().unwrap()
            user_ids = resp.get('user_ids', [])
            resp = rpc_client['api/person/puppet_user']().unwrap()
            user_ids.extend(resp.get('puppet_ids', []))
            return ~Q(user_id__in=user_ids)

        elif srch_val == USER_CLASSIFY.MODEL:
            resp = rpc_client['api/user_classify/ids']().unwrap()
            user_ids = resp.get('user_ids', [])
            return Q(user_id__in=user_ids)

        elif srch_val == USER_CLASSIFY.PUPPET:
            resp = rpc_client['api/person/puppet_user']().unwrap()
            puppet_ids = resp.get('puppet_ids', [])
            return Q(user_id__in=puppet_ids)

        else:
            return Q()

    def filter_tractate_id(self, srch_key, srch_val, regex=False):
        tractate = Tractate.objects.using(settings.SLAVE_DB_NAME).filter(
            id=int(srch_val)
        ).first()

        if tractate:
            return Q(tractate_id=tractate.id)
        return Q()

    def update(self, updates, **kwargs):
        user_id = updates.get('tractate_user_id')
        tractate_id = updates.get('tractate_id')
        content = updates.get('reply_content')
        replied_id = kwargs.get('id') or 0
        if not all([user_id, tractate_id, content]):
            return
        init_obj = {
            "user_id": user_id,
            "tractate_id": tractate_id,
            "content": content,
            'replied_id': replied_id,
            "top_id": 0,
            "platform": TRACTATE_PLATFORM.HERA,
        }
        TractateReply.objects.create(**init_obj)

        return super().update(updates, **kwargs)


class TractatecheckDB(DataBuilder):
    def getval_content(self, obj):
        return TRACTATE_CONTENT_LEVEL.getDesc(obj.content_level)

    def getval_audit_status(self, obj):
        return TRACTATE_STATUS.getDesc(obj.status)

    def getval_send_message(self, obj):
        return obj.title + obj.send_message

    def getval_check_time(self, obj):
        return str(obj.check_time).split('.')[0]

    def getval_user_nick_name(self, obj):
        user = UserService.get_user_by_user_id(obj.user_id)
        return user and user.nickname or ""

@DB
class TractatecheckDQ(DataSQLQuery):
    model = TractateCheck
    data_model = TractatecheckDB


class SoftArticleDB(DataBuilder):

    def getval_article_id(self, obj):
        return obj.id

    def getval_service_id(self, obj):
        s_relation = SoftArticleRelation.objects.filter(softarticle_id=obj.id, relation_type=SOFT_ARTICLE_RELATION_TYPE.SERVICE).first()
        return s_relation.relation_id if s_relation else ""

    def getval_diary_id(self, obj):
        s_relation = SoftArticleRelation.objects.filter(softarticle_id=obj.id, relation_type=SOFT_ARTICLE_RELATION_TYPE.DIARY).first()
        return s_relation.relation_id if s_relation else ""

    def getval_diary_name(self, obj):
        s_relation = SoftArticleRelation.objects.filter(softarticle_id=obj.id, relation_type=SOFT_ARTICLE_RELATION_TYPE.DIARY).first()
        diary = Diary.objects.filter(id=s_relation.relation_id).first()
        return diary.title

    def getval_tags_name(self, obj):
        relation_ids = SoftArticleRelation.objects.filter(softarticle_id=obj.id, relation_type=1).values_list('relation_id', flat=True)
        tag_infos = TagService.get_tags_by_tag_ids(ids=relation_ids)
        tag_name = ""
        for tag in tag_infos:
            tag_name += tag.name + ",    "
        return tag_name

    def getval_item_words(self, obj):
        relation_ids = SoftArticleRelation.objects.filter(softarticle_id=obj.id, relation_type=1).values_list('relation_id', flat=True)
        return list(relation_ids)

    def getval_like_num(self, obj):
        article = SoftArticle.objects.filter(id=obj.id).first()
        return article.vote_amount

    def getval_favor_num(self, obj):
        article = SoftArticle.objects.filter(id=obj.id).first()
        return article.favor_amount

    def getval_reply_num(self, obj):
        article = SoftArticle.objects.filter(id=obj.id).first()
        return article.reply_amount

    def getval_last_handle(self, obj):
        article = SoftArticle.objects.filter(id=obj.id).first()
        check_article = SoftArticleCheck.objects.filter(softarticle_id=obj.id).first()
        if check_article and check_article.online_time and check_article.online_time > article.online_time:
            return "运营"
        elif check_article and check_article.online_time and check_article.online_time <= article.online_time:
            return "商家"

        return "商家"

    def getval_hospital(self, obj):
        hospital = HospitalService.get_hospital_from_doctor_id(id=obj.doctor_id)
        return hospital.name if hospital else ""

    def getval_service(self, obj):
        relation = SoftArticleRelation.objects.filter(softarticle_id=obj.id, relation_type=SOFT_ARTICLE_RELATION_TYPE.SERVICE).first()
        service_info = GoodsService.get_service_by_service_id(relation.relation_id)
        return service_info.name if service_info else ""

    def getval_author(self, obj):
        doctor = DoctorService.get_doctor_from_doctor_id(obj.doctor_id)
        return doctor.name if doctor else ""

    def getval_content_level(self, obj):
        return obj.content_level

    def getval_img(self, obj):
        if obj.article_type == SOFT_ARTICLE_TYPE.VIDEO:
            video = SoftArticleVideo.objects.filter(softarticle_id=obj.id).first()
            return video.upload_img_cover
        else:
            img_info = SoftArticleImages.objects.filter(softarticle_id=obj.id).first()
            return img_info.image_url

    def getval_doctor_user_id(self, obj):
        return UserService.get_user_id_by_doctor_id(obj.doctor_id)

    def getval_user_name(self, obj):
        user_id = UserService.get_user_id_by_doctor_id(obj.doctor_id)
        user = UserService.get_user_by_user_id(user_id=user_id)
        return user.nickname

    def getval_is_talent(self, obj):
        user_id = UserService.get_user_id_by_doctor_id(obj.doctor_id)
        user = UserService.get_user_by_user_id(user_id=user_id)
        return True if int(user.membership_level) else False

    def getval_user_level(self, obj):
        user_id = UserService.get_user_id_by_doctor_id(obj.doctor_id)
        user = UserService.get_user_by_user_id(user_id=user_id)
        return user.user_rights_level

    def getval_status_desc(self, obj):
        return TRACTATE_STATUS.getDesc(key=obj.status)

    def getval_check_reason(self, obj):
        s_check = SoftArticleCheck.objects.filter(softarticle_id=obj.id).first()
        return s_check.check_content

    def getval_video_url(self, obj):
        s_video = SoftArticleVideo.objects.filter(softarticle_id=obj.id).first()
        return urljoin(settings.VIDEO_HOST, s_video.water_video_url)

    def getval_doctor_type(self, obj):
        doctor = DoctorService.get_doctor_from_doctor_id(obj.doctor_id)
        return DOCTOR_TYPE.getDesc(key=doctor.doctor_type)

@DB
class SoftArticleDQ(DataSQLQuery):
    model = SoftArticle
    data_model = SoftArticleDB

    def filter_create_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_diary_id(self, srch_key, srch_val, regex=False):
        s_relations = SoftArticleRelation.objects.filter(relation_id=int(srch_val),
                                                         relation_type=SOFT_ARTICLE_RELATION_TYPE.DIARY)\
                                                 .values_list('softarticle_id', flat=True)
        return Q(id__in=list(set(s_relations)))

    def filter_service_id(self, srch_key, srch_val, regex=False):
        s_relations = SoftArticleRelation.objects.filter(relation_id=int(srch_val),
                                                         relation_type=SOFT_ARTICLE_RELATION_TYPE.SERVICE) \
                                                 .values_list('softarticle_id', flat=True)
        return Q(id__in=list(set(s_relations)))

    def filter_doctor_user_id(self, srch_key, srch_val, regex=False):
        doctor_id = DoctorService.get_doctor_by_user_id_v1(user_id=srch_val)
        if not doctor_id:
            return Q()

        return Q(doctor_id=doctor_id)

    def filter_tags_name(self, srch_key, srch_val, regex=False):
        s_relations = SoftArticleRelation.objects.filter(relation_id=int(srch_val),
                                                         relation_type=SOFT_ARTICLE_RELATION_TYPE.TAG) \
            .values_list('softarticle_id', flat=True)
        return Q(id__in=list(set(s_relations)))


class SoftArticleCheckDB(DataBuilder):
    pass


@DB
class SoftArticleCheckDQ(DataSQLQuery):
    model = SoftArticleCheck
    data_model = SoftArticleCheckDB


class SoftArticleReplyDB(DataBuilder):
    def getval_user_name(self, obj):
        user = UserService.get_user_by_user_id(user_id=obj.user_id)
        return user.nickname


@DB
class SoftArticleReplyDQ(DataSQLQuery):
    model = SoftArticleReply
    data_model = SoftArticleReplyDB