# coding=utf-8
import traceback
import json
import datetime
from django.db.models import Q
from rest_framework.decorators import action
from django.db import transaction
from rest_framework.views import APIView
from rest_framework.serializers import ValidationError
from utils.permission import permission_required, isLogin, check_permission
from django.contrib.auth.models import Group, Permission
from rest_framework_jwt.views import ObtainJSONWebToken, RefreshJSONWebToken
from utils import response_error, response_ok
from django.contrib.auth import get_user_model

User = get_user_model()
from apps.account.serializers import JWTSerializer, EmployeeSerializer, \
    WechatLoginSerializer, WechatBindSerializer, GroupDictSerializer, GroupSerializer
from utils.custom_modelviewset import CustomModelViewSet
from apps.account.filters import UserFilter, GroupFilter
from apps.log.models import BizLog
from utils.exceptions import CustomError
from apps.account.models import CustomerWechat
from utils.wx.WXBizDataCrypt import WXBizDataCrypt
from apps.account.consts import PermissionMenu
from collections import OrderedDict

class LoginView(ObtainJSONWebToken):
    serializer_class = JWTSerializer

    def post(self, request, *args, **kwargs):
        try:
            ser = self.serializer_class(data=request.data)
            ser.request = request
            if ser.is_valid(raise_exception=True):
                return response_ok(ser.validated_data)
        except ValidationError as e:
            return response_error(e.detail['error'][0])
        except CustomError as e:
            return response_error(str(e))

class RefreshTokenView(RefreshJSONWebToken):

    def post(self, request, *args, **kwargs):
        try:
            ser = self.serializer_class(data=request.data)
            if ser.is_valid(raise_exception=True):
                return response_ok({'token': ser.validated_data['token']})
        except ValidationError as e:
            return response_ok({'error':True})
        except CustomError as e:
            return response_error(str(e))

class ChangePassword(APIView):

    def post(self, request, *args, **kwargs):
        id = request.GET.get('id')
        data = json.loads(request.body)
        try:
            with transaction.atomic():
                user = User.objects.filter(id=id).first()
                if not user:
                    raise CustomError(u'用户信息错误，请刷新重试！')
                user.change_password(data['new_password'], data['confirm_password'], data['old_password'])
                BizLog.objects.addnew(request.user, BizLog.UPDATE, u"修改密码[%s],id=%d" % (user.username, user.id))
        except CustomError as e:
            return response_error(str(e))
        except Exception as e:
            traceback.print_exc()
            return response_error(u'保存失败！')
        return response_ok()


class EmployeeViewSet(CustomModelViewSet):
    permission_classes = [isLogin, ]
    queryset = User.objects.filter(type__lte=User.AGENT)
    serializer_class = EmployeeSerializer

    @permission_required('account.browse_user')
    def filter_queryset(self, queryset):
        queryset = queryset.filter()
        user = self.request.user
        queryset = queryset.filter(
            Q(id=user.id) |
            Q(create_user=user)
        )

        f = UserFilter(self.request.GET, queryset=queryset)
        return f.qs

    @permission_required('account.add_user')
    def perform_create(self, serializer):
        super(EmployeeViewSet, self).perform_create(serializer)
        instance = serializer.instance
        validated_data = serializer.validated_data
        BizLog.objects.addnew(self.request.user, BizLog.INSERT,
                              u'添加用户[%s]，id=%d' % (instance.name, instance.id), validated_data)

    @permission_required('account.add_user')
    def perform_update(self, serializer):
        super(EmployeeViewSet, self).perform_update(serializer)
        instance = serializer.instance
        validated_data = serializer.validated_data
        BizLog.objects.addnew(self.request.user, BizLog.UPDATE,
                              u'修改用户[%s]，id=%d' % (instance.name, instance.id), validated_data)

class GroupsViewSet(CustomModelViewSet):
    permission_classes = [isLogin, ]
    queryset = Group.objects.filter()
    serializer_class = GroupSerializer

    @permission_required('account.manager_permissions')
    def filter_queryset(self, queryset):
        if not self.request.user.is_superuser:
            groups = self.request.user.groups.all()
            queryset = queryset.filter(id__in=[g.id for g in groups])
        f = GroupFilter(self.request.GET, queryset=queryset)
        return f.qs

    @permission_required('account.manager_permissions')
    def perform_create(self, serializer):
        super(GroupsViewSet, self).perform_create(serializer)
        instance = serializer.instance
        validated_data = serializer.validated_data
        BizLog.objects.addnew(self.request.user, BizLog.INSERT,
                              u'添加权限组[%s]，id=%d' % (instance.name, instance.id), validated_data)

    @permission_required('account.manager_permissions')
    def perform_update(self, serializer):
        super(GroupsViewSet, self).perform_update(serializer)
        instance = serializer.instance
        validated_data = serializer.validated_data
        BizLog.objects.addnew(self.request.user, BizLog.UPDATE,
                              u'修改权限组[%s]，id=%d' % (instance.name, instance.id), validated_data)

    @permission_required('account.manager_permissions')
    def destroy(self, request, *args, **kwargs):
        with transaction.atomic():
            instance = self.get_object()
            # user_count = instance.user_set.all().count()
            # if user_count:
            #     raise CustomError(u'该权限组已分配给用户，禁止删除！')

            BizLog.objects.addnew(self.request.user, BizLog.DELETE,
                                  u'删除权限组[%s]，id=%d' % (instance.name, instance.id))
            instance.delete()
        return response_ok()


class SetUserInfoView(APIView):
    permission_classes = [isLogin, ]

    def post(self, request, *args, **kwargs):
        appid = request.POST.get('appid')
        openid = request.POST.get('openid')
        encryptedData = request.POST.get('encryptedData')
        iv = request.POST.get('iv')

        customer_wechat = CustomerWechat.objects.filter(openid=openid, wechat_app__authorizer_appid=appid).first()
        if not customer_wechat:
            raise CustomError(u'未找到相应的微信客户！')

        employee = self.request.user
        if customer_wechat.customer and customer_wechat.customer != employee:
            # 用户用手机号、密码登录后，同步微信信息时，customer可能会不一样
            #张三、李四都是注册、同步用户。 张三的账号，在李四小程序上登录，同步的李四微信信息，可能会两个用户不同。
            raise CustomError(u'该微信已同步其他客户！')
        if not customer_wechat.customer:
            customer_wechat.customer = employee
            customer_wechat.save()
        pc = WXBizDataCrypt(appid, customer_wechat.session_key)
        result = pc.decrypt(encryptedData, iv)
        with transaction.atomic():
            if employee.name == employee.tel:
                employee.name = result['nickName']
            employee.gender = result['gender']
            employee.face = result['avatarUrl']
            employee.save()
        return response_ok({'face':employee.face,'name':employee.name})

class WxLoginView(APIView):
    serializer_class = WechatLoginSerializer

    def post(self, request, *args, **kwargs):
        ser = self.serializer_class(data=request.data)
        if ser.is_valid():
            return response_ok(ser.validated_data)
        else:
            return response_error('参数错误')


class WxBindView(APIView):
    serializer_class = WechatBindSerializer

    def post(self, request, *args, **kwargs):
        ser = self.serializer_class(data=request.data)
        if ser.is_valid():
            return response_ok(ser.validated_data)
        else:
            return response_error('参数错误')


class PermissionsListView(APIView):
    permission_classes = [isLogin, ]

    @permission_required('account.manager_permissions')
    def get(self, request):
        rows = Permission.objects.all().exclude(name__startswith='Can')
        perms_menus = PermissionMenu()
        rows = perms_menus.sort_perms(rows)
        menus = OrderedDict()
        for row in rows:
            item = {'id': row.id, 'name': row.name}
            mn = perms_menus.get_menuname_of_contenttype(row.content_type.app_label, row.content_type.model)
            if mn in menus:
                permissions = menus[mn]
            else:
                permissions = menus[mn] = OrderedDict()
            if row.content_type.name in permissions:
                if not item in permissions[row.content_type.name]:
                    permissions[row.content_type.name].append(item)
            else:
                permissions[row.content_type.name] = [item, ]
        return response_ok(menus)


class PermissionDictView(APIView):
    permission_classes = [isLogin, ]

    @permission_required('account.add_user')
    def get(self, request):
        rows = Group.objects.filter()
        if not request.user.is_superuser:
            groups = request.user.groups.all()
            rows = rows.filter(id__in=[g.id for g in groups])
        serializer = GroupDictSerializer(rows, many=True)
        return response_ok(serializer.data)
