#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import boto3
import botocore
import requests
from django.views.generic.base import View
from Object.ResponseObject import ResponseObject
from Object.TokenObject import TokenObject
from Service.CommonService import CommonService
from Model.models import Device_Info, RequestRecordModel, iotdeviceInfoModel, Access_Log, DeviceLogModel, LogModel, \
    AppLogModel
from Ansjer.config import REGION_NAME, ACCESS_KEY_ID, SECRET_ACCESS_KEY, LOG_BUCKET


class LogManagementView(View):
    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        operation = kwargs.get('operation')
        return self.validation(request.GET, request, operation)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        operation = kwargs.get('operation')
        return self.validation(request.POST, request, operation)

    def validation(self, request_dict, request, operation):
        language = request_dict.get('language', 'en')
        response = ResponseObject(language, 'pc')
        if operation == '??':
            return 0
        else:
            tko = TokenObject(
                request.META.get('HTTP_AUTHORIZATION'),
                returntpye='pc')
            # if tko.code != 0:
            #     return response.json(tko.code)
            response.lang = tko.lang
            userID = tko.userID
            if operation == 'getRequestList':
                return self.getRequestList(request_dict, response)
            elif operation == 'getDeviceIotInfoList':
                return self.getDeviceIotInfoList(request_dict, response)
            elif operation == 'requestPublishMqtt':
                return self.requestPublishMqtt(request_dict, response)
            elif operation == 'getAccessLogList':
                return self.getAccessLogList(request_dict, response)
            elif operation == 'getDeviceLogList':
                return self.getDeviceLogList(request_dict, response)
            # 操作日志
            elif operation == 'getOperationLogList':
                return self.getOperationLogList(request_dict, response)
            elif operation == 'getAppLogList':  # 获取app日志
                return self.getAppLogList(request_dict, response)
            else:
                return response.json(404)

    def getRequestList(self, request_dict, response):
        pageNo = request_dict.get('pageNo', None)
        pageSize = request_dict.get('pageSize', None)
        method = request_dict.get('method', None)
        url = request_dict.get('url', None)
        parameter = request_dict.get('parameter', None)
        status_code = request_dict.get('status_code', None)
        reason_phrase = request_dict.get('reason_phrase', None)
        if not all([pageNo, pageSize]):
            return response.json(444)

        page = int(pageNo)
        line = int(pageSize)
        try:
            request_qs = RequestRecordModel.objects.all()
            if method:
                request_qs = request_qs.filter(method=method)
            if url:
                request_qs = request_qs.filter(url__contains=url)
            if parameter:
                request_qs = request_qs.filter(parameter__contains=parameter)
            if status_code:
                request_qs = request_qs.filter(status_code=status_code)
            if reason_phrase:
                request_qs = request_qs.filter(reason_phrase=reason_phrase)

            count = request_qs.count()

            request_qs = request_qs[(page - 1) * line:page * line]
            qs_list = []
            for requsetobj in request_qs:
                qs_list.append({
                    'id': requsetobj.id,
                    'method': requsetobj.method,
                    'url': requsetobj.url,
                    'parameter': requsetobj.parameter,
                    # 时间保留小数点后两位
                    'execute_time': round(requsetobj.execute_time, 2),
                    'status_code': requsetobj.status_code,
                    'reason_phrase': requsetobj.reason_phrase,
                    'add_time': requsetobj.add_time.strftime("%Y-%m-%d %H:%M:%S"),
                })
            return response.json(
                0, {'list': qs_list, 'total': count})
        except Exception as e:
            print(e)
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    def getDeviceIotInfoList(self, request_dict, response):
        serial_number = request_dict.get('serial_number', None)
        uid = request_dict.get('uid', None)
        pageNo = request_dict.get('pageNo', None)
        pageSize = request_dict.get('pageSize', None)

        if not all([pageNo, pageSize]):
            return response.json(444)

        page = int(pageNo)
        line = int(pageSize)
        try:
            if serial_number or uid:
                if serial_number:
                    iot_device_info_qs = iotdeviceInfoModel.objects.filter(
                        serial_number__contains=serial_number)
                if uid:
                    iot_device_info_qs = iotdeviceInfoModel.objects.filter(
                        uid__contains=uid)
                if not iot_device_info_qs.exists():
                    return response.json(0)
                total = len(iot_device_info_qs)
                iot_device_info_qs = iot_device_info_qs.values(
                    'serial_number',
                    'uid',
                    'thing_name',
                    'thing_groups',
                    'add_time',
                    'update_time')[(page - 1) * line:page * line]
            else:
                total = iotdeviceInfoModel.objects.filter().count()
                iot_device_info_qs = iotdeviceInfoModel.objects.filter().values(
                    'serial_number',
                    'uid',
                    'thing_name',
                    'thing_groups',
                    'add_time',
                    'update_time')[(page - 1) * line:page * line]

            iot_device_info_list = CommonService.qs_to_list(iot_device_info_qs)
            # 获取序列号的uid
            for iot_device_info in iot_device_info_list:
                if not iot_device_info['uid']:
                    device_info_qs = Device_Info.objects.filter(
                        serial_number__contains=iot_device_info['serial_number']).values('UID')
                    if device_info_qs.exists():
                        iot_device_info['uid'] = device_info_qs[0]['UID']
            return response.json(
                0, {'list': iot_device_info_list, 'total': total})
        except Exception as e:
            print(e)
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    # 通用发布MQTT通知
    @staticmethod
    def requestPublishMqtt(request_dict, response):
        msg = request_dict.get('msg', None)
        thing_name = request_dict.get('thing_name', None)
        topic_name = request_dict.get('topic_name', None)
        if not all([msg, thing_name, topic_name]):
            return response.json(444)

        try:
            msg = eval(msg)
            identification_code = thing_name[thing_name.rindex('_') + 1:]
            if not CommonService.req_publish_mqtt_msg(identification_code, topic_name, msg):
                return response.json(10044)
            return response.json(0)
        except Exception as e:
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    def getAccessLogList(self, request_dict, response):
        user = request_dict.get('user', None)
        operation = request_dict.get('operation', None)
        status = request_dict.get('status', None)
        pageNo = request_dict.get('pageNo', None)
        pageSize = request_dict.get('pageSize', None)

        if not all([pageNo, pageSize]):
            return response.json(444)

        page = int(pageNo)
        line = int(pageSize)
        try:
            if user or operation or status:
                if user:
                    access_log_qs = Access_Log.objects.filter(
                        user__contains=user)
                if operation:
                    access_log_qs = Access_Log.objects.filter(
                        operation__contains=operation)
                if status:
                    access_log_qs = Access_Log.objects.filter(status=status)
                if not access_log_qs.exists():
                    return response.json(0)
                total = access_log_qs.count()
                access_log_qs = access_log_qs.order_by('-time').values(
                    'user', 'operation', 'ip', 'status', 'content', 'time')[(page - 1) * line:page * line]
            else:
                total = Access_Log.objects.count()
                access_log_qs = Access_Log.objects.filter().order_by('-time').values('user',
                                                                                     'operation', 'ip', 'status',
                                                                                     'content', 'time')[
                                (page - 1) * line:page * line]
            access_log_list = CommonService.qs_to_list(access_log_qs)
            return response.json(0, {'list': access_log_list, 'total': total})
        except Exception as e:
            print(e)
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    def getDeviceLogList(self, request_dict, response):
        uid = request_dict.get('uid', None)
        serial_number = request_dict.get('serial_number', None)
        pageNo = request_dict.get('pageNo', None)
        pageSize = request_dict.get('pageSize', None)

        if not all([pageNo, pageSize]):
            return response.json(444)

        page = int(pageNo)
        line = int(pageSize)
        try:
            if uid or serial_number:
                if uid:
                    device_log_qs = DeviceLogModel.objects.filter(
                        uid__contains=uid)
                if serial_number:
                    device_log_qs = DeviceLogModel.objects.filter(
                        serial_number__contains=serial_number)
                if not device_log_qs.exists():
                    return response.json(0)
                total = device_log_qs.count()
                device_log_qs = device_log_qs.order_by(
                    '-add_time').values()[(page - 1) * line:page * line]
            else:
                total = DeviceLogModel.objects.count()
                device_log_qs = DeviceLogModel.objects.filter().order_by(
                    '-add_time').values()[(page - 1) * line:page * line]
            device_log_list = CommonService.qs_to_list(device_log_qs)

            # 添加下载链接
            aws_s3_client = boto3.client(
                's3',
                region_name=REGION_NAME,
                aws_access_key_id=ACCESS_KEY_ID,
                aws_secret_access_key=SECRET_ACCESS_KEY,
                config=botocore.client.Config(signature_version='s3v4'),
            )
            for device_log in device_log_list:
                obj = device_log['serial_number'] if device_log['serial_number'] else device_log['uid']
                obj = 'device_log/' + obj + \
                      '/{}'.format(device_log['filename'])
                download_url = aws_s3_client.generate_presigned_url(
                    ClientMethod='get_object',
                    Params={
                        'Bucket': LOG_BUCKET,
                        'Key': obj
                    },
                    ExpiresIn=3600
                )
                device_log['download_url'] = download_url
            return response.json(0, {'list': device_log_list, 'total': total})
        except Exception as e:
            print(e)
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    def getOperationLogList(self, request_dict, response):
        operation = request_dict.get('operation', None)
        url = request_dict.get('url', None)
        pageNo = request_dict.get('pageNo', None)
        pageSize = request_dict.get('pageSize', None)

        if not all([pageNo, pageSize]):
            return response.json(444)

        page = int(pageNo)
        line = int(pageSize)

        try:
            log_qs = LogModel.objects.all()
            if operation:
                log_qs = log_qs.filter(operation__contains=operation)
            if url:
                log_qs = log_qs.filter(url__contains=url)
            count = log_qs.count()
            log_qs = log_qs.values(
                'operation', 'url', 'content', 'ip', 'time')[
                     (page - 1) * line:page * line]
            log_list = list(log_qs)
            return response.json(
                0, {'list': log_list, 'total': count})
        except Exception as e:
            print(e)
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    def getAppLogList(self, request_dict, response):
        """
        获取App日志信息
        @param request_dict:请求参数
        @param response:响应对象
        @request_dict userID:用户ID
        @request_dict uid:uid
        @return:
        """
        userName = request_dict.get('userName', None)
        uid = request_dict.get('uid', None)
        pageNo = request_dict.get('pageNo', None)
        pageSize = request_dict.get('pageSize', None)

        if not all([pageNo, pageSize]):
            return response.json(444)
        page = int(pageNo)
        line = int(pageSize)
        try:
            app_log_qs = AppLogModel.objects.all()
            if userName:
                app_log_qs = app_log_qs.filter(user__username=userName)
            elif uid:
                app_log_qs = app_log_qs.filter(uid=uid)
            count = app_log_qs.count()
            log_qs = app_log_qs.values(
                'user__username', 'uid', 'average_delay', 'status', 'filename', 'add_time', 'user_id').order_by(
                '-add_time')[(page - 1) * line:page * line]
            app_log_list = CommonService.qs_to_list(log_qs)
            # 添加下载链接
            aws_s3_client = boto3.client(
                's3',
                region_name=REGION_NAME,
                aws_access_key_id=ACCESS_KEY_ID,
                aws_secret_access_key=SECRET_ACCESS_KEY,
                config=botocore.client.Config(signature_version='s3v4'),
            )
            for app_log in app_log_list:
                filename = app_log['filename']
                if not filename.endswith('.txt'):
                    filename += ".txt"
                obj = 'app_log/' + app_log['user_id'] + '/{}'.format(filename)
                appLog_url = aws_s3_client.generate_presigned_url(
                    ClientMethod='get_object',
                    Params={
                        'Bucket': LOG_BUCKET,
                        'Key': obj
                    },
                    ExpiresIn=3600
                )
                app_log['appLog_url'] = appLog_url
            return response.json(0, {'list': app_log_list, 'total': count})
        except Exception as e:
            print(e)
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
