#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 3月 
# author: NinEveN
# date: 2021/3/29
import logging
import random

from django.db.models import Q
from django.http.response import HttpResponse
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_xml.parsers import XMLParser

from api.models import ThirdWeChatUserInfo, UserInfo, UserCertificationInfo, WeChatInfo
from api.utils.modelutils import PageNumber, get_wx_nickname
from api.utils.response import BaseResponse
from api.utils.serializer import WeixinInfoSerializer
from api.views.login import get_login_type
from common.core.auth import ExpiringTokenAuthentication
from common.core.sysconfig import Config
from common.libs.mp.chat import reply, receive
from common.libs.mp.wechat import check_signature, WxMsgCrypt, get_userinfo_from_openid, WxTemplateMsg
from common.utils.caches import set_wx_ticket_login_info_cache, get_wx_ticket_login_info_cache

logger = logging.getLogger(__name__)

GOOD_XX = [
    '您是一位有恒心有毅力的人，我很佩服您！',
    '越有内涵的人越虚怀若谷，像您这样有内涵的人我十分敬佩！',
    '你像天上的月亮，也像那闪烁的星星，可惜我不是诗人，否则，当写一万首诗来形容你的美丽！',
    '据考证，你是世界上最大的宝藏，里面藏满了金子、钻石和名画！',
    '虽然你没有一簇樱唇两排贝齿，但你的谈吐高雅脱俗，机智过人，令我折服！',
    '您是一位有恒心有毅力的人，我很佩服您！',
    '我很荣幸，认识你这样有内涵的漂亮朋友！',
    '春花秋月，是诗人们歌颂的情景，可是我对于它，却感到十分平凡。只有你嵌着梨涡的笑容，才是我眼中最美的景象！',
    '你像一片轻柔的云在我眼前飘来飘去，你清丽秀雅的脸上荡漾着春天般美丽的笑容。在你那双又大又亮的眼睛里，我总能捕捉到你的宁静，你的热烈，你的聪颖，你的敏感！',
    '人生旅程上，您丰富我的心灵，开发我得智力，为我点燃了希望的光芒，谢谢您！',
]


class TextXMLParser(XMLParser):
    media_type = 'text/xml'  # 微信解析的是 text/xml


def reply_login_msg(rec_msg, to_user, from_user):
    content = f'还未绑定用户，请通过手机或者邮箱登录账户之后进行绑定'
    u_data_id = -1
    ids = []
    wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user, enable_login=True).all()

    wx_ticket_info = get_wx_ticket_login_info_cache(rec_msg.Ticket)

    wx_user_count = wx_user_obj_queryset.count()
    if 0 <= wx_user_count <= 1:
        wx_user_obj = wx_user_obj_queryset.first()
        if wx_user_obj:
            user_obj = wx_user_obj.user_id
            u_data_id = user_obj.pk
            content = f'用户 {user_obj.first_name} 登录成功'
            WxTemplateMsg(to_user, get_wx_nickname(to_user)).login_success_msg(user_obj.first_name)
        # else:
        #     wx_user_info = update_or_create_wx_userinfo(to_user)
        #     WxTemplateMsg(to_user, wx_user_info.get('nickname', '')).login_failed_msg()
    elif wx_user_count > 1:
        ids = [x['user_id__id'] for x in wx_user_obj_queryset.values('user_id__id')]
        u_data_id = wx_user_obj_queryset.first().user_id.pk
        content = f'您刚才进行了扫码登录，多用户登录中'
    if wx_ticket_info and wx_ticket_info.get('ip_addr'):
        ip_addr = wx_ticket_info.get('ip_addr')
        logger.info(f"{content} ip:{ip_addr}")

    set_wx_ticket_login_info_cache(rec_msg.Ticket, {'pk': u_data_id, 'to_user': to_user, "ids": ids})
    reply_msg = reply.TextMsg(to_user, from_user, content)
    return reply_msg.send()


def update_or_create_wx_userinfo(to_user, user_obj=None, w_type=''):
    code, wx_info = get_userinfo_from_openid(to_user)
    logger.info(f"get openid:{to_user} info:{to_user} code:{code}")
    if code:
        wx_info = {
            'openid': wx_info.get('openid'),
            # 'nickname': wx_user_info.get('nickname'),  # 最新微信接口已经取消该字段
            # 'sex': wx_user_info.get('sex'),  # 最新微信接口已经取消该字段
            'subscribe_time': wx_info.get('subscribe_time'),
            # 'head_img_url': wx_user_info.get('headimgurl'),  # 最新微信接口已经取消该字段
            'address': f"{wx_info.get('country')}-{wx_info.get('province')}-{wx_info.get('city')}",
            'subscribe': wx_info.get('subscribe'),
        }
    if user_obj:
        wx_obj, _ = WeChatInfo.objects.update_or_create(openid=to_user, defaults=wx_info)
        wx_user_info = {'weixin': wx_obj}
        if w_type == 'login':
            wx_user_info['enable_login'] = True
        if w_type == 'notify':
            wx_user_info['enable_notify'] = True
        ThirdWeChatUserInfo.objects.update_or_create(user_id=user_obj, weixin=wx_obj, defaults=wx_user_info)
        return wx_obj


def wx_bind_utils(rec_msg, to_user, from_user, content):
    w_type = rec_msg.Eventkey.split('.')[-1]
    uid = rec_msg.Eventkey.split('.')[-2]
    user_obj = UserInfo.objects.filter(uid=uid).first()
    wx_user_obj = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user, user_id__uid=uid).first()

    if wx_user_obj:
        wx_template_msg_obj = WxTemplateMsg(to_user, get_wx_nickname(to_user))
        if user_obj and user_obj.uid == wx_user_obj.user_id.uid:
            content = f'账户 {wx_user_obj.user_id.first_name} 已经绑定成功，感谢您的使用'
            update_or_create_wx_userinfo(to_user, user_obj, w_type)
            wx_template_msg_obj.bind_success_msg(user_obj.first_name)
        else:
            content = f'账户已经被 {wx_user_obj.user_id.first_name} 绑定'
            wx_template_msg_obj.bind_failed_msg(content)
    else:
        if user_obj:
            update_or_create_wx_userinfo(to_user, user_obj, w_type)
            content = f'账户绑定 {user_obj.first_name} 成功'
            WxTemplateMsg(to_user, get_wx_nickname(to_user)).bind_success_msg(user_obj.first_name)
    if user_obj:
        set_wx_ticket_login_info_cache(rec_msg.Ticket, {'pk': user_obj.pk, 'w_type': w_type, 'to_user': to_user})
    reply_msg = reply.TextMsg(to_user, from_user, content)
    return reply_msg.send()


class ValidWxChatToken(APIView):
    parser_classes = (XMLParser, TextXMLParser)

    def get(self, request):
        params = request.query_params
        return HttpResponse(check_signature(params))

    def post(self, request):
        params = request.query_params
        data = request.data
        encrypt_obj = WxMsgCrypt()
        ret, encrypt_xml = encrypt_obj.decrypt_msg(data, params.get("msg_signature"), params.get("timestamp"),
                                                   params.get("nonce"))
        logger.info(f"code:{ret}, result {encrypt_xml}")
        result = "success"
        if ret == 0:
            content = '欢迎使用fly应用分发平台，感谢您的关注'
            rec_msg = receive.parse_xml(encrypt_xml)
            logger.info(f"code:{ret}, parse_xml result {rec_msg.__dict__ if rec_msg else rec_msg}")
            if isinstance(rec_msg, receive.Msg):
                to_user = rec_msg.FromUserName
                from_user = rec_msg.ToUserName

                if rec_msg.MsgType == 'text':
                    msg = rec_msg.Content.decode('utf-8')
                    if msg and (msg.startswith('解除登录绑定') or msg.startswith('解除消息绑定')):
                        msg_list = msg.split(' ')
                        if len(msg_list) == 2:
                            uid = msg_list[-1]
                            wx_user_obj = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user,
                                                                             user_id__uid=uid).first()
                            data = {}
                            w_msg = []
                            if msg.startswith('解除登录绑定'):
                                data.update({'enable_login': False})
                                w_msg.append('扫码登录')
                            if msg.startswith('解除消息绑定'):
                                w_msg.append('消息推送')
                                data.update({'enable_notify': False})
                            if data:
                                ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user, user_id__uid=uid).update(
                                    **data)
                                WxTemplateMsg(to_user, get_wx_nickname(to_user)).unbind_success_msg(
                                    wx_user_obj.user_id.first_name, f"{' '.join(w_msg)} 解绑成功",
                                    "如需重新绑定，请登陆平台，进行绑定。感谢您的关注")
                            return HttpResponse("success")

                    content = random.choices([*GOOD_XX, content, rec_msg.Content.decode('utf-8')])[0]
                    reply_msg = reply.TextMsg(to_user, from_user, f'{get_wx_nickname(to_user)} ♥ {content}')
                    result = reply_msg.send()

                elif rec_msg.MsgType == 'image':
                    media_id = rec_msg.MediaId
                    reply_msg = reply.ImageMsg(to_user, from_user, media_id)
                    result = reply_msg.send()
                else:
                    result = reply.Msg().send()
                logger.info(f"replay msg: {result}")
                return HttpResponse(result)
            elif isinstance(rec_msg, receive.EventMsg):
                to_user = rec_msg.FromUserName
                from_user = rec_msg.ToUserName
                if rec_msg.Event == 'CLICK':  # 公众号点击事件
                    if rec_msg.Eventkey == 'good':
                        content = random.choices(GOOD_XX)[0]
                        reply_msg = reply.TextMsg(to_user, from_user, f'{get_wx_nickname(to_user)} ♥ {content}')
                        result = reply_msg.send()
                        logger.info(f"replay msg: {result}")
                        return HttpResponse(result)
                    elif rec_msg.Eventkey == 'flyapps':
                        reply_msg = reply.TextMsg(to_user, from_user, Config.WEB_DOMAIN)
                        result = reply_msg.send()
                        logger.info(f"replay msg: {result}")
                        return HttpResponse(result)
                    elif rec_msg.Eventkey in ['query_bind', 'unbind', 'unbind_all']:
                        wx_user_obj_queryset = ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user).filter(
                            Q(enable_login=True) | Q(enable_notify=True)).all()
                        if rec_msg.Eventkey == 'query_bind':
                            for wx_user_obj in wx_user_obj_queryset:
                                if wx_user_obj:
                                    user_obj = wx_user_obj.user_id
                                    content = f'绑定用户 {user_obj.first_name} '
                                    if user_obj.email:
                                        content += f' 登录邮箱：{user_obj.email} '
                                    if user_obj.mobile:
                                        content += f' 登录手机：{user_obj.mobile}'
                                    user_cert_obj = UserCertificationInfo.objects.filter(user_id=user_obj,
                                                                                         status=1).first()
                                    if user_cert_obj:
                                        name = user_cert_obj.name
                                    else:
                                        name = user_obj.first_name
                                    description = f'绑定了'
                                    if wx_user_obj.enable_login:
                                        description += " 微信登录 "
                                    if wx_user_obj.enable_notify:
                                        description += " 消息通知 "
                                    description += "功能"

                                    WxTemplateMsg(to_user, get_wx_nickname(to_user)).bind_query_success_msg(
                                        user_obj.first_name,
                                        name,
                                        user_obj.mobile,
                                        user_obj.email,
                                        description)
                            if wx_user_obj_queryset.count() == 0:
                                WxTemplateMsg(to_user, get_wx_nickname(to_user)).query_bind_info_failed_msg(
                                    "查询绑定", '暂无绑定信息')

                        elif rec_msg.Eventkey == 'unbind_all':
                            for wx_user_obj in wx_user_obj_queryset:
                                if wx_user_obj:
                                    content = f'解绑用户 {wx_user_obj.user_id.first_name} 成功'
                                    WxTemplateMsg(to_user, get_wx_nickname(to_user)).unbind_success_msg(
                                        wx_user_obj.user_id.first_name,
                                        "解除绑定成功，您将无法使用微信扫描登录平台和微信消息推送功能",
                                        "如需重新绑定，请登陆平台，在个人资料进行登录绑定。感谢您的关注")
                                    ThirdWeChatUserInfo.objects.filter(weixin__openid=to_user).update(
                                        enable_login=False,
                                        enable_notify=False)
                            if wx_user_obj_queryset.count() == 0:
                                WxTemplateMsg(to_user, get_wx_nickname(to_user)).query_bind_info_failed_msg(
                                    "解除绑定", '暂无绑定信息')
                        elif rec_msg.Eventkey == 'unbind':
                            if wx_user_obj_queryset.count() == 0:
                                content = f'暂无绑定信息'
                            else:
                                content = ''
                                for wx_user_obj in wx_user_obj_queryset:
                                    user_obj = wx_user_obj.user_id
                                    user_content = f'用户昵称 {user_obj.first_name} '
                                    if user_obj.email:
                                        user_content += f' 登录邮箱：{user_obj.email} '
                                    if user_obj.mobile:
                                        user_content += f' 登录手机：{user_obj.mobile}'

                                    content += f'♥{user_content}♥\n'
                                    if wx_user_obj.enable_login:
                                        login_info = f'解除登录绑定 {user_obj.uid}'
                                        content += f'<a href="weixin://bizmsgmenu?msgmenuid=1&msgmenucontent={login_info}">【解除登录绑定】</a>'
                                    if wx_user_obj.enable_notify:
                                        notify_info = f'解除消息绑定 {user_obj.uid}'
                                        content += f'<a href="weixin://bizmsgmenu?msgmenuid=1&msgmenucontent={notify_info}">【解除消息绑定】</a>'
                                    content += '\n\n'
                                content += '请点击您要解除绑定的信息\n'
                        logger.info(f"to_user:{to_user} from_user:{from_user} reply msg: {content}")
                        reply_msg = reply.TextMsg(to_user, from_user, content)
                        result = reply_msg.send()
                        if rec_msg.Eventkey == 'unbind':
                            return HttpResponse(result)

                elif rec_msg.Event in ['subscribe', 'unsubscribe']:  # 订阅
                    reply_msg = reply.TextMsg(to_user, from_user, content)
                    result = reply_msg.send()
                    if rec_msg.Event == 'subscribe':
                        if rec_msg.Eventkey == 'qrscene_web.login':  # 首次关注，登录认证操作
                            result = reply_login_msg(rec_msg, to_user, from_user)
                        elif rec_msg.Eventkey.startswith('qrscene_web.bind.'):
                            result = wx_bind_utils(rec_msg, to_user, from_user, content)
                    if rec_msg.Event == 'unsubscribe':
                        WeChatInfo.objects.filter(openid=to_user).update(subscribe=False)

                elif rec_msg.Event == 'SCAN':
                    if rec_msg.Eventkey == 'web.login':  # 已经关注，然后再次扫码，登录认证操作
                        result = reply_login_msg(rec_msg, to_user, from_user)
                    elif rec_msg.Eventkey.startswith('web.bind.'):
                        result = wx_bind_utils(rec_msg, to_user, from_user, content)
        else:
            logger.error('密文解密失败')
        logger.info(f"replay msg: {result}")
        # 直接回复修改为微信模板消息回复
        # return HttpResponse(result)
        return HttpResponse("success")


class ThirdWxAccount(APIView):
    authentication_classes = [ExpiringTokenAuthentication, ]

    def get(self, request):
        res = BaseResponse()
        if get_login_type().get('third', '').get('wxp'):
            wx_obj_lists = WeChatInfo.objects.filter(thirdwechatuserinfo__user_id=request.user,
                                                     thirdwechatuserinfo__enable_login=True)
            page_obj = PageNumber()
            info_serializer = page_obj.paginate_queryset(queryset=wx_obj_lists.order_by("-subscribe_time"),
                                                         request=request,
                                                         view=self)
            wx_user_info = WeixinInfoSerializer(info_serializer, many=True, )
            res.data = wx_user_info.data
            res.count = wx_obj_lists.count()
        return Response(res.dict)

    def post(self, request):
        data = request.data
        openid = data.get("openid")
        if get_login_type().get('third', '').get('wxp') and openid:
            if request.user.check_password(data.get('confirm_pwd', '')):
                ThirdWeChatUserInfo.objects.filter(user_id=request.user, weixin__openid=openid).update(
                    enable_login=False)
            else:
                res = BaseResponse()
                res.code = 1001
                res.msg = "密码有误，请检查"
                return Response(res.dict)
        return self.get(request)
