# coding=utf-8

import requests
from rest_framework.exceptions import NotFound
from django.db import transaction
from rest_framework.views import APIView
from rest_framework import generics
from rest_framework.decorators import action
from django.db.models import Q
from rest_framework_jwt.views import ObtainJSONWebToken,VerifyJSONWebToken,RefreshJSONWebToken
from rest_framework.serializers import ValidationError
from apps.WechatApplet.models import WechatApplet
from utils import response_ok, response_error
from apps.tenant.config.serializers import Config,ConfigSerializer
from apps.tenant.option.serializers import OptionSerializer,Option
from apps.tenant.area.serializers import AreaSerializer,Area
from apps.tenant.building.models import Building
from apps.tenant.notices.models import Notices
from apps.tenant.notices.serializers import NoticesWXSerializer
from apps.tenant.notices.filters import NoticesFilter
from utils.permission import isLogin
from utils.wx.WXBizDataCrypt import WXBizDataCrypt
from apps.tenant.poster.serializer import PosterSerializer, Poster
from apps.tenant.device.models import DeviceModel

from .serializers import *

class CustomerRefreshTokenView(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_error(u'登录状态失效，请重新登录[' + e.detail['error'][0] + ']')


class CustomerVerifyTokenView(VerifyJSONWebToken):
    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_error(u'登录状态失效，请重新登录[' + e.detail['error'][0] + ']')


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).first()
        if not customer_wechat:
            raise CustomError(u'未找到相应的微信客户！')

        employee = self.request.user.employee
        if customer_wechat.customer and customer_wechat.customer.id != employee.id:
            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()
            customer_log(employee, BizLog.INSERT, u'客户设置信息，id=%d' % employee.id, result)
        return response_ok()


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 HomeView(generics.ListAPIView):
    '''小程序首页数据'''

    queryset = Config.objects.filter()
    serializer_class = ConfigSerializer

    def filter_queryset(self, queryset):
        appid = self.request.GET.get('appid')
        app = WechatApplet.getByAppid(appid)
        queryset = queryset.filter(tenant=app.tenant)
        return queryset

    def list(self, request, *args, **kwargs):
        try:
            data = super(HomeView, self).list(request)
        except NotFound:
            return response_ok([])
        return data

class PosterView(generics.ListAPIView):
    '''小程序首页数据'''

    queryset = Poster.objects.filter(enable=True)
    serializer_class = PosterSerializer

    def filter_queryset(self, queryset):
        is_auth = False
        if self.request.user and self.request.user.is_authenticated:
            is_auth = True
        queryset = queryset.filter(tenant__isnull=True)
        if is_auth:
            queryset = queryset.filter(Q(tenant__isnull=True) | Q(tenant=self.request.user.employee.tenant))
        return queryset

    def list(self, request, *args, **kwargs):
        try:
            data = super(PosterView, self).list(request)
        except NotFound:
            return response_ok([])
        return data

class DictView(APIView):
    permission_classes = [isLogin, ]
    def get(self, request):
        tenant = request.user.employee.tenant
        ret = {
            'repair_type': OptionSerializer(Option.objects.filter(delete=False,type=Option.REPAIRS_TYPE, enable=True, tenant=tenant), many=True).data,
            'fault_cause': OptionSerializer(Option.objects.filter(delete=False,type=Option.FAULT_CAUSE, enable=True, tenant=tenant), many=True).data,
        }
        return response_ok(ret)


class NoticesView(generics.ListAPIView):
    queryset = Notices.objects.filter()
    serializer_class = NoticesWXSerializer

    def filter_queryset(self, queryset):
        if self.request.user and self.request.user.is_authenticated:
            queryset = queryset.filter(tenant=self.request.user.employee.tenant)
        else:
            queryset = queryset.filter(tenant=0)
        f = NoticesFilter(self.request.GET, queryset=queryset)
        return f.qs


class NoticesDetailView(generics.RetrieveAPIView):
    permission_classes = [isLogin, ]
    queryset = Notices.objects.filter()
    serializer_class = NoticesWXSerializer

    def get_queryset(self):
        queryset = self.queryset.filter(tenant=self.request.user.employee.tenant)
        return queryset

    def retrieve(self, request, *args, **kwargs):
        return response_ok(NoticesWXSerializer(self.get_object()).data)


class BuildingView(APIView):

    def get(self, request):
        area = request.GET.get('area')
        data = []
        rows = Building.objects.filter(area=area).values('building').order_by('building').distinct()
        for build in rows:
            build_dict = {
                'name':build['building'],
                'childern':[]
            }
            floors = Building.objects.filter(area=area,building=build['building']).values('floor').order_by('floor').distinct()
            for floor in floors:
                floor_dict = {
                    'name': floor['floor'],
                    'childern': []
                }
                build_dict['childern'].append(floor_dict)
                locations = Building.objects.filter(area=area, building=build['building'],floor=floor['floor'])
                for location in locations:
                    floor_dict['childern'].append({
                        'id':location.id,
                        'name':location.location,
                    })
            data.append(build_dict)

        return response_ok(data)

class DeviceView(APIView):
    permission_classes = [isLogin, ]
    def get(self, request):
        param = request.GET.get('param')
        data = []
        rows = DeviceModel.objects.filter(tenant=request.user.employee.tenant)
        if param:
            rows = rows.filter(Q(name=param) | Q(device_no=param) | Q(device_model=param))
        else:
            rows = rows[:10]
        for item in rows:
            build_dict = {
                'id': item.id,
                'name':item.name,
                'device_no':item.device_no,
                'device_model':item.device_model,
                'branch':item.branch,
                'address':item.address,
            }
            data.append(build_dict)

        return response_ok(data)
