import time
import json
import traceback
import collections
import sys

from django.db import transaction
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.models import User
from django.contrib.sessions.models import Session
from django.utils import timezone


from kedong.utils import PrAes
from smartfarming.models.user import DeviceUser


JsonResponse = lambda x: HttpResponse(json.dumps(x, indent=True,ensure_ascii=False),content_type="application/json")

class PortError(Exception):
    def __init__(self, field_name, message,data=1):
        Exception.__init__(self)
        self.message = message
        self.field_name = field_name
        self.data = data
    def __str__(self):
        return str("$fielderror" + json.dumps({"field_name": self.field_name, "message": self.message,"data": self.data}))
    def __unicode__(self):
        return str("$fielderror" + json.dumps({"field_name": self.field_name, "message": self.message,"data": self.data}))


class ReturnValue(Exception):
    def __init__(self, data, message=""):
        self.data = data
        self.message = message

def session_check(session_key):
    try:
        sessions = Session.objects.get(session_key=session_key)
    except:
        return False
    else:
        expired_time = sessions.expire_date
        if timezone.now() < expired_time:
            sessions = sessions.get_decoded()
            return sessions
        else:
            return False


def kedong_deco(login_required=False,inteam_required=False,inproject_required=False):
    def _kedong_deco(views):
        @csrf_exempt
        def _(request, *args, **kwargs):
            start_time = time.time()
            params = {}
            for i in request.POST:
                params[str(i)] = request.POST[i]
            session_key = request.POST.get("token", "")
            if '%2B' in session_key or " " in session_key:
                session_key = str(session_key).replace("%2B","+").replace(" ","+")
            try:
                session_key = PrAes.aesdecrypt(session_key)
            except:
                pass
            try:
                if session_key:
                    sessions = session_check(session_key)
                    assert sessions
            except Exception as e:
                _result = (
                        {"errorCode": 403, "message": "session 校验失败！无权访问！",
                            "formError": {}, "data": None})
            else:
                try:
                    value = sessions.get('user_id')
                    try:
                        ip = request.META['HTTP_X_FORWARDED_FOR']
                    except:
                        ip = request.META['REMOTE_ADDR']
                    uid = int(value)
                    state = 1
                    try:
                        auto_login_uid = int(sessions.get('auto_login_uid'))
                        temp_state = auto_login_uid - uid
                        if temp_state in [1, 4]:
                            state = temp_state
                    except Exception as e:
                        pass
                    device_user = DeviceUser.objects.get(uid=uid, state=state)
                    request.myuser = device_user
                    request.ip = ip
                    try:
                        perm = device_user.perm(uid)
                        request.user_perm = perm
                        request.role_id = device_user.role_id
                        request.user_type = device_user.user_type
                    except:
                        request.user_perm = None
                        request.role_id = None
                        pass
                except:
                    request.myuser = None
                    request.user_perm = None
                    request.role_id = None
                if request.method == "OPTIONS":
                    _result = {}
                else:
                    if login_required and not request.myuser:
                        _result = (
                            {"errorCode": 403, "message": "当前设备尚未登陆，不允许操作",
                                "formError": {}, "data": None})
                    else:
                        _result = None
                        if login_required:
                            perm = request.user_perm
                            port_name = views.__name__
                            if port_name == 'logout_user':
                                del sessions['user_id']
                            if port_name in ["lamp_list"]:
                                try:
                                    device_type_id = request.POST["device_type_id"]
                                    port_name = port_name + device_type_id
                                except:
                                    _result = (
                                    {"errorCode": 500, "message": "device_type_id 必传", "formError": {},
                                        "data": None})
                            if not _result:
                                if ("logout" not in port_name) and perm != 'all' \
                                        and ('user_login_info' not in port_name) \
                                        and ('user_theme' not in port_name) \
                                        and ('changepwd' not in port_name):
                                    if port_name == 'check_suyuan_user':
                                        pass
                        if not _result:
                            try:
                                try:
                                    result = views(request, *args, **kwargs)
                                except AssertionError as _re:
                                    if str(_re).startswith("$fielderror"):
                                        _re_info = str(_re).strip("$fielderror")
                                        _re_info = json.loads(_re_info)
                                        raise PortError(_re_info["field_name"], _re_info["message"])
                                    else:
                                        raise Exception(traceback.format_exc())
                            except PortError as e:
                                _result = ({"errorCode": 0, "message": e.message, "formError":
                                    {"name": e.field_name, "message": e.message}, "data": None})
                            else:
                                message = ""
                                http_origin = request.META.get('HTTP_ORIGIN', None)
                                origin = "https://web.hnyfwlw.com"
                                if http_origin == origin:
                                    try:
                                        temp_result = json.dumps(result)
                                        temp_result = temp_result.replace("http://8.136.98.49:8002", f"{origin}:58002")
                                        temp_result = temp_result.replace("http://8.136.98.49:8003", f"{origin}:58003")
                                        temp_result = temp_result.replace("http://120.27.222.26:8002", f"{origin}:58002/siqing")
                                        temp_result = temp_result.replace("http://static.yfpyx.com",
                                                                          f"{origin}:58002/static.yfpyx.com")
                                        temp_result = temp_result.replace("https://bkimg.cdn.bcebos.com",
                                                                          f"{origin}:58002/bkimg.cdn.bcebos.com")
                                        temp_result = temp_result.replace("http://47.99.110.100",
                                                                          f"{origin}:58002/47.99.110.100")
                                        result = json.loads(temp_result)
                                    except Exception as e:
                                        print('转换https异常: ', e)

                                if isinstance(result, ReturnValue):
                                    message = result.message
                                    result = result.data
                                _result = ({"errorCode": 0, "message": message, "formError": {}, "data": result})
            _result["params"] = params
            end_time = time.time()
            delta_time = int((end_time - start_time) * 1000)
            result = JsonResponse(_result)
            result["Access-Control-Allow-Origin"] = "*"
            if request.META.get("HTTP_ORIGIN"):
                result["Access-Control-Allow-Origin"] = request.META.get("HTTP_ORIGIN")
            result["Access-Control-Allow-Method"] = "OPTIONS, GET, POST"
            result["X-Requested-With"] = "XMLHttpRequest"
            result["Access-Control-Allow-Headers"] = "x-requested-with,session,Session,Content-Type,Accept,Origin"
            result["Access-Control-Max-Age"] = "86400"
            result["Access-Control-Allow-Credentials"] = "true"
            return result
        _.__doc__ = views.__doc__
        _.login_required = login_required
        _.inteam_required = login_required and inteam_required
        _.inproject_required = login_required and inproject_required
        _.api_factory = "bigdata_deco"
        if not getattr(sys, "api_config", None):
            sys.api_config = collections.OrderedDict()
        module_name = views.__module__.replace('smartfarming.api.views.', '')
        sys.api_config[module_name + "." + views.__name__] = _
        return _
    return _kedong_deco
