# -*- coding: utf-8 -*-

import datetime
from hashlib import sha1 as sha_constructor
from email.header import make_header

from django.db import IntegrityError
from django.core.mail import send_mail, EmailMessage, get_connection
from django.conf import settings
from django.contrib.auth.models import User

# Enumeration is deprecated, reference: http://git.gengmei.cc/backend/gm-types
# from rpc.tool.enumeration import Enumeration
from gm_types.gaia import BUSINESS_TYPE

from api.models import OperateTeam, OperateTeamRealatedOperate, OperateTeamReleatedBusiness
from hera.models import BackendGroup
from themis.models import Team
from rpc.tool.random_tool import random_str
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException
from rpc.tool.log_tool import logging_exception

salt = lambda: sha_constructor(
    "jFcSFdQvbDkN9fsc" + str(datetime.date.today())
).hexdigest()[:5]


def send_user_passwd_email(useremail, username, passwd):
    title = u'后台帐号'
    content = u'用户名: {}\n密码: {}\n'.format(username, passwd)
    send_mail(title, content,
              from_email=settings.HERA_EMAIL_USER,
              recipient_list=[useremail],
              auth_user=settings.HERA_EMAIL_USER,
              auth_password=settings.HERA_EMAIL_PSWD,
              )


def send_user_passwd_email_v2(useremail, username, passwd):
    title = u'更美账户密码'
    content = u'用户名: {}\n密码: {}\n'.format(username, passwd)
    send_mail(title, content,
              from_email=settings.HERA_EMAIL_USER,
              recipient_list=[useremail],
              auth_user=settings.HERA_EMAIL_USER,
              auth_password=settings.HERA_EMAIL_PSWD,
              )


def send_passwd_reset_email(useremail, passwd):
    title = u'后台帐号重置密码'
    content = u'新密码: {}\n'.format(passwd)
    send_mail(
        title, content,
        from_email=settings.HERA_EMAIL_USER,
        recipient_list=[useremail],
        auth_user=settings.HERA_EMAIL_USER,
        auth_password=settings.HERA_EMAIL_PSWD,
    )


def get_mail_instance(title, body, to_list):
    conn = get_connection(
        username=settings.HERA_EMAIL_USER,
        password=settings.HERA_EMAIL_PSWD,
    )
    mail = EmailMessage(connection=conn)
    mail.from_email = settings.HERA_EMAIL_USER
    mail.subject = title
    mail.to = to_list
    mail.body = body
    return mail


def attach_title(title):
    title = make_header([(title, 'utf-8')]).encode('utf-8')
    return title


def get_choices(query, page=1, num=30, src_map=None):
    page = int(page)
    num = int(num)
    total_count = query.count()
    start_pos = (page - 1) * num
    start_pos = start_pos if start_pos >= 0 else 0
    if src_map is None:
        src_map = {'id': 'id', 'text': 'name'}
    results = [{k: getattr(obj, v) for k, v in src_map.iteritems()}
               for obj in query[start_pos: start_pos + num]
               ]
    return {'total_count': total_count, 'results': results, 'page': page, 'num': num}


def remote_choices(model, qry_item, fetch_seleted=False, page=1, num=30, src_map=None):
    if fetch_seleted:
        # get initial options
        if isinstance(qry_item['val'], (list, tuple)):
            qs = {'{}__in'.format(qry_item['key']): qry_item['val']}
        else:
            qs = {qry_item['key']: qry_item['val']}
    else:
        qs = {'{}__contains'.format(qry_item['key']): qry_item['val']}
    query = model.objects.filter(**qs)
    return get_choices(query, page, num, src_map)


def calc_activation_num(username):
    if isinstance(username, unicode):
        username = username.encode('utf8')
    activation_num = int(sha_constructor(
        salt() + username).hexdigest(), 16) % 10000
    return activation_num


def shorten_text(text, width=30):
    placeholder = '...'
    if len(text) > width - len(placeholder):
        pad = placeholder
    else:
        pad = ''
    return text[:27] + pad


def business_checker(user, groups):
    """判断是否商务成员及其商务角色

    :return: BUSINESS_TYPE, perm_users(可查看的用户)
    """
    from hera.models import BackendGroup
    if 'business_leader' in groups:
        # 商务Leader
        return BUSINESS_TYPE.LEADER, None
    if 'business' in groups:
        business_groups = BackendGroup.objects.filter(members=user)
        perm_users = set([user])
        business_type = BUSINESS_TYPE.GROUP_MEMBER
        for bgroup in business_groups:
            if bgroup.leader == user:
                # 如果是组长，允许查看组员的业务
                business_type = BUSINESS_TYPE.GROUP_LEADER
                perm_users.update(list(bgroup.members.all()))
        return business_type, list(perm_users)
    return None, None


def check_business(user_groups):
    # 判断是商务并且非商务leader
    flag = 'business' in user_groups and "business_leader" not in user_groups
    return flag


def reset_username(user):
    """如果清空或重置手机号, username为手机号时, 需要在username里加随机字符.

    NTOE: wrap this in transaction.
    """
    username = user._get_full_field_content_('username')
    if username.isdigit() and username == user.person.phone:
        un = username
        user.username = '%s_phone_%s' % (un, random_str(8))
        user.save()
        return True

    return False


def model_edit(model_class, object_id=None, data=None):
    if object_id is None:
        obj = model_class()
    elif isinstance(object_id, model_class):
        obj = object_id
    else:
        try:
            obj = model_class.objects.get(id=object_id)
        except:
            logging_exception()
            raise RPCNotFoundException
    for k, v in data.iteritems():
        setattr(obj, k, v)
    try:
        obj.save()
    except IntegrityError:
        raise RPCIntegrityError
    except:
        logging_exception()
        raise
    return obj


def m2m_save(model_class, m2m_field, m2m_ids):
    new_objs = model_class.objects.filter(id__in=m2m_ids)
    old_objs = m2m_field.all()
    add_objs = set(new_objs) - set(old_objs)
    del_objs = set(old_objs) - set(new_objs)
    m2m_field.add(*add_objs)
    m2m_field.remove(*del_objs)


def check_operate(userid):
    """
    判断当前用户是不是在kefu这个运营大组里面
    :param userid: 用户id
    :return:
    """
    return BackendGroup.objects.filter(members=userid, name=settings.OPERATE_TEAM_TIYLE).exists()


def operate_business(userid):
    """
    获取当前运营用户通过小组相关联的商务用户的id集合
    :param userid: 用户id
    :return:
    """
    operateteams_rela = OperateTeamRealatedOperate.objects.filter(user__id=userid).values_list('operate__id',
                                                                                               flat=True)
    operateteam_ids = list(operateteams_rela)
    operateteams = OperateTeamReleatedBusiness.objects.filter(operate__id__in=operateteam_ids).values_list('user__id',
                                                                                                           flat=True)
    business_ids = set(operateteams)
    return business_ids


def make_tag_dic():
    # deprecated
    # 时间紧， 从mars抄过来的
    from api.models import Tag
    from gm_types.gaia import TAG_TYPE
    secod_tag_dic, third_tag_dic = {}, {}
    secod_tags = Tag.objects.filter(
        is_online=True,
        tag_type=TAG_TYPE.BODY_PART_SUB_ITEM
    )
    for o in secod_tags:
        secod_tag_dic[o.id] = '--'
        for t in o.parent_tags():
            if t.tag_type == TAG_TYPE.BODY_PART:
                secod_tag_dic[o.id] = t.name
                break

    third_tags = Tag.objects.filter(
        is_online=True,
        tag_type=TAG_TYPE.ITEM_WIKI
    )
    for o in third_tags:
        third_tag_dic[o.id] = {
            'second_tag': '',
            'first_tag': ''
        }
        dic = third_tag_dic[o.id]
        for t in o.parent_tags():
            if t.tag_type == TAG_TYPE.BODY_PART_SUB_ITEM:
                try:
                    first_tag = secod_tag_dic[t.id]
                except KeyError:
                    first_tag = u'此3级Tag关联的二级Tag不在 secod_tag_dic 里'
                dic['second_tag'] = t.name
                dic['first_tag'] = first_tag
                break
    # 不考虑 3级tag，直接关联1级tag
    return secod_tag_dic, third_tag_dic


def get_tag_name(tag_id, tag_name):
    # deprecated
    # 时间紧， 从mars抄过来的

    second_tag_dic, third_tag_dic = make_tag_dic()
    if tag_id:
        second = second_tag_dic.get(tag_id)
        if second:
            return second, tag_name, ''

        third = third_tag_dic.get(tag_id)
        if third:
            return third['first_tag'], third['second_tag'], tag_name

        return tag_name, '', ''
    return '', '', ''


def get_parent_tag(tag):
    if not tag:
        return None
    parent_tags = tag.parent_tags()
    if parent_tags:
        return parent_tags[0]
    return None


def get_tag_chain(tag):
    # 获取tag 逐层级的tag name
    from gm_types.gaia import TAG_TYPE
    if not tag:
        return '', '', ''
    if tag.tag_type == TAG_TYPE.BODY_PART:
        # 一级tag
        return tag.name, '', ''
    elif tag.tag_type == TAG_TYPE.BODY_PART_SUB_ITEM:
        # 二级tag
        first_tag = get_parent_tag(tag)
        first_tag_name = first_tag.name if first_tag else ''
        return first_tag_name, tag.name, ''
    elif tag.tag_type == TAG_TYPE.ITEM_WIKI:
        # 三级tag
        second_tag = get_parent_tag(tag)
        first_tag = get_parent_tag(second_tag)
        second_tag_name = second_tag.name if second_tag else ''
        first_tag_name = first_tag.name if first_tag else ''
        return first_tag_name, second_tag_name, tag.name


def commastr_to_list(s):
    lst = s.replace(u'，', ',').split(',')
    return [l.strip() for l in lst]


def get_team_by_businessman(bn_id, recursive=True):
    '''
    获取商务人员，在组织架构中，可见的层级team信息

    '''
    located_teams = get_located_teams(bn_id)
    return get_child_teams(located_teams, recursive)


def get_child_teams(parent_team_ids, recursive=True):
    '''
    获取组织架构层级下的子组织

    parent_team_ids: 父组织架构ID列表
    recursive: boolean  是否递归
    '''
    visible_teams = set()
    iter_parent_teams = parent_team_ids[:]

    while iter_parent_teams:
        pt = iter_parent_teams.pop(0)
        child_teams = _get_child_teams(pt)
        if recursive:
            iter_parent_teams.extend(set(child_teams) - set(visible_teams))
        visible_teams.update(child_teams)
    return list(visible_teams)


def _get_child_teams(parent_team_id):
    return list(Team.objects.filter(parent_team=parent_team_id).values_list('id', flat=True))


def get_located_teams(bn_id):
    return list(Team.objects.filter(team_user=bn_id).values_list('id', flat=True))


def get_business_team(ctx, user_id=None):
    '''
    根据上下文信息，获取对应人员在组织架构中商务人员及可见组信息
    注: 是否属于组织架构--目前包含运营与商务。
    ctx: 请求环境上下文
    user_id: 用户id, 如果为空, 则从ctx的session中获取, 不为空则根据user_id获取用户信息
    @return: (boolean, businessman_list, team_list)
        eg: 是否属于组织架构, 商务人员列表, 组织架构组
    '''
    _in = True
    businessman_list = []
    team_groups = set()

    groups = []
    if user_id:
        groups = User.objects.get(id=user_id).belong_groups.values_list('name', flat=True)
    else:
        groups = ctx.session.groups
        user_id = ctx.session.user_id

    if check_business(groups):
        businessman_list.append(user_id)
    elif check_operate(user_id):
        businessman_list = operate_business(user_id)
    else:
        _in = False
    if businessman_list:
        for bn in businessman_list:
            team_groups.update(get_team_by_businessman(bn))

    return _in, businessman_list, list(team_groups)
