#! /usr/bin/env python3
# -*- coding:utf-8 -*-
import logging

from django.contrib.auth.hashers import make_password, check_password
from django.core.cache import cache

from apollo.settings import EXPIRE_TIME
from utils.sign import SignManager
from utils.defines import ResponseCode, RedisKey, IsValid, IsAdmin
from perm.dao.user_dao import UserDao
from perm.models import UserModel
import utils.session


class UserService(object):
    """
    用户逻辑
    """

    def __init__(self):
        self.user_dao = UserDao()
        self.sign_manager = SignManager()

    @staticmethod
    def make_password(password):
        """
        生成密文密码
        :param str password: 明文密码
        :return str: 密文密码
        """
        return make_password(str(password), None, "pbkdf2_sha256")

    @staticmethod
    def check_password(password, encry_password):
        """
        校验密码
        :param str password: 明文密码
        :param str encry_password: 密文密码
        :return bool: True|False
        """
        return check_password(password, encry_password)

    @staticmethod
    def _format_cache_key(uid):
        """
        拼接sid缓存key
        :param int uid: 用户uid
        :return str: redis key
        """
        key = RedisKey.USER_SID.value.format(uid=uid)
        return key

    def cache_sign(self, uid, sid):
        """
        缓存sid; 有效期12小时
        :param int uid: 用户uid
        :param str sid: sid
        :return:
        """
        key = self._format_cache_key(uid)
        cache.set(key, sid, EXPIRE_TIME)

    def get_cache_sign(self, uid):
        """
        读取sid
        :param int uid: 用户uid
        :return str: sid or ""
        """
        key = self._format_cache_key(uid)
        sid = cache.get(key)
        return sid or ""

    def del_cache_sign(self, uid):
        """
        删除sid缓存
        :param int uid: 用户uid
        :return:
        """
        key = self._format_cache_key(uid)
        cache.delete(key)

    def check_user(self):
        pass

    def login(self, user_name, password, **kwargs):
        """
        登录
        :param str user_name: 用户名
        :param str password: 密码
        :return tuple: code, desc, data
        """
        host = kwargs.get("host")
        if (not user_name) or (not password):
            return ResponseCode.PARAM_ERROR.value, "用户名、密码不能为空!", {}

        user_info = self.user_dao.read_by_name(user_name)
        if (not user_info) or (not check_password(password, user_info["password"])) \
                or user_info["status"] == IsValid.INVALID.value:
            return ResponseCode.PARAM_ERROR.value, "账号或密码错误！", {}

        if host == "open.sh-senyu.com":
            is_third_party = user_info.get("is_third_party", 0)
            if is_third_party == 0:
                return ResponseCode.OPEN_ERROR.value, "此账户属于运营系统，不可登录此系统", {}

        utils.session.cache_user(user_info)
        uid = user_info["id"]

        # 生成sid
        sid = self.sign_manager.make()

        # 缓存sid，有效期12小时
        self.cache_sign(uid, sid)
        del user_info["password"]
        user_info.update({
            "uid": uid,
            "sid": sid,
        })

        return ResponseCode.SUCCESS.value, ResponseCode.SUCCESS.desc, user_info

    def logout(self, uid):
        """
        用户退出
        :param int uid: 用户uid
        :return int: code
        """
        # 删除缓存的sid
        self.del_cache_sign(uid)
        return ResponseCode.SUCCESS.value

    def add_relation(self, uid, role_id_list):
        """
        添加用户和角色对应关系
        :param uid:
        :param role_id_list:
        :return:
        """
        if not role_id_list:
            return ResponseCode.PARAM_ERROR.value

        if role_id_list:
            # 插入对应关系表 UserRoleRelationModel
            self.user_dao.insert_relation(uid, role_id_list)

        return ResponseCode.SUCCESS.value

    def add(self, user_info, lsp_ids=None):
        """
        添加用户
        :param lsp_ids:
        :param dict user_info: {
                                    "name": 账户,
                                    "real_name": 姓名,
                                    "status": 状态,
                                    "is_admin": 是否是admin,
                                    "password": 密码,
                                    "phone": 手机号,
                                    "email": 邮箱,
                                }
        :return tuple: code, desc
        """
        name, password = user_info["name"], user_info["password"]
        if (not name) or (not password):
            return ResponseCode.PARAM_ERROR.value, "账户名、密码不能为空!"

        # 添加用户
        user_info["password"] = self.make_password(password)
        user_obj = self.user_dao.insert(user_info)

        if lsp_ids:
            self.user_dao.insert_lsp_relation(user_obj.id, lsp_ids)

        return ResponseCode.SUCCESS.value, ResponseCode.SUCCESS.desc

    def edit(self, update_info, uid, lsp_ids=None):
        """
        编辑
        :param dict update_info: {
                "name": 账号,
                "real_name": 姓名
                "status": int(status),
                "is_admin": int(is_admin),
                "phone": phone,
                "email": email,
            }
        :param int uid: 待修改的用户的id
        :return tuple: code, desc
        """
        name = update_info["name"]
        if not name:
            return ResponseCode.PARAM_ERROR.value, "账户名不能为空!"

        self.user_dao.update(update_info, uid)
        if int(update_info["is_admin"]) == IsAdmin.ADMIN.value:
            self.user_dao.delete_relation(uid)

        self.user_dao.delete_lsp_relation(uid)
        if lsp_ids:
            self.user_dao.insert_lsp_relation(uid, lsp_ids)

        self.del_cache_sign(uid)
        return ResponseCode.SUCCESS.value, ResponseCode.SUCCESS.desc

    def edit_user_roles(self, uid, role_ids):
        """
        编辑用户角色
        :param int uid: 用户id
        :param str role_ids: 角色id，多个以逗号分割
        :return tuple: code, desc
        """
        user_info = self.user_dao.read_user_by_id(uid)
        if user_info["is_admin"] == IsAdmin.ADMIN.value:
            return ResponseCode.FORBID.value, "该用户是管理员，不需要添加角色！"

        if role_ids:
            self.user_dao.delete_relation(uid)

            role_id_list = role_ids.split(",")
            self.add_relation(uid, role_id_list)

        return ResponseCode.SUCCESS.value, ResponseCode.SUCCESS.desc

    def modify_password(self, uid, password):
        """
        修改密码
        :param int uid: 用户id
        :param str password: 密码
        :return:
        """
        if not password:
            return ResponseCode.PARAM_ERROR.value, "密码不能为空!"

        update_info = {"password": self.make_password(password)}
        self.user_dao.update(update_info, uid)
        self.del_cache_sign(uid)
        return ResponseCode.SUCCESS.value, ResponseCode.SUCCESS.desc

    def get_relation_by_uid(self, uid):
        """
        :param int uid:
        :return list:
        """
        relation_list = self.user_dao.read_relation_by_uid(uid)
        return relation_list

    def get_user_role_list(self, uid):
        """
        获取某用户所有的角色列表
        :param int uid: 用户id
        :return:
        """
        user_info = self.detail(uid)
        return user_info["role_list"]

    def get_list(self, page, page_size=20, status=None):
        """
        列表
        :param status:
        :param int page: 页码
        :param int page_size: 每页条数
        :return tuple: total_page:总页数, user_list:用户列表
        """
        _, total_page, user_list = self.user_dao.read_list(page, page_size, status)
        return total_page, user_list

    def search(self, wd, status, page, page_size=20):
        """
        匹配姓名或账号
        :param str status: 状态
        :param str wd: 查询关键字
        :param int page: 当前页码
        :param int page_size: 每页条数，默认20
        :return list: 用户信息列表
        """
        if not wd:
            total_page, user_list = self.get_list(page, page_size, status)
            return total_page, user_list

        _, total_page, user_list = self.user_dao.search(wd, page, page_size, status)
        return total_page, user_list

    def detail(self, uid):
        """
        用户详情
        :param int uid: 用户id
        :return dict: {user_info}
        """
        user_info = self.user_dao.read_user_by_id(uid)
        user_info.pop("password", "")
        role_list = user_info.pop("role", [])
        user_info["role_list"] = role_list
        user_info["lsp_list"] = self.user_dao.read_lsp_relation_by_uid(uid)
        logging.warning("HTTP_user_info:{}".format(user_info))
        if user_info["is_third_party"] == 1:
            role_list = self.user_dao.read_yunwei_role(uid)
            user_info["role_list"] = role_list

        return user_info

    @staticmethod
    def is_admin(uid):
        if UserModel.objects.filter(pk=uid, is_admin=IsAdmin.ADMIN.value).exists():
            return True

        return False

    @staticmethod
    def is_read_all(uid):
        if uid in [209]:
            return True
        return False
