#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import boto3
import botocore
import requests
from django.db.models import Q
from django.views.generic.base import View

from Object.IPWeatherObject import IPQuery
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, AppScannedSerial, StsFrequency, DeviceDomainRegionModel, IPAddr, CountryModel, RegionModel, \
    AbnormalEvent, DeviceTypeModel, AbnormalEventCode
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)
            elif operation == 'getScanLog':  # 获取扫码日志
                return self.getScanLog(request_dict, response)
            elif operation == 'getAlarmLog':  # 获取警报日志
                return self.getAlarmLog(request_dict, response)
            elif operation == 'getDomainLog':  # 获取域名日志
                return self.getDomainLog(request_dict, response)
            elif operation == 'getDomainScanLog':  # 获取域名扫码日志
                return self.getDomainScanLog(request_dict, response)
            elif operation == 'getDeviceAbnormalEvent':  # 获取设备异常事件
                return self.getDeviceAbnormalEvent(request_dict, response)
            else:
                return response.json(414)

    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=uid)
                if serial_number:
                    device_log_qs = DeviceLogModel.objects.filter(
                        serial_number=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)))

    def getScanLog(self, request_dict, response):
        serial = request_dict.get('serial', None)
        ip = request_dict.get('ip', 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:
            scan_log_qs = AppScannedSerial.objects.all()
            if serial:
                scan_log_qs = scan_log_qs.filter(serial__contains=serial)
            if ip:
                scan_log_qs = scan_log_qs.filter(ip__contains=ip)
            count = scan_log_qs.count()
            scan_log_qs = scan_log_qs.order_by('-add_time').values(
                'serial', 'ip', 'add_time', 'update_time')[
                          (page - 1) * line:page * line]
            scan_log_list = list(scan_log_qs)
            return response.json(
                0, {'list': scan_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 getAlarmLog(self, request_dict, response):
        page_no = request_dict.get('pageNo', None)
        page_size = request_dict.get('pageSize', None)
        uid = request_dict.get('uid', None)

        if not all([page_no, page_size]):
            return response.json(444)

        page = int(page_no)
        line = int(page_size)

        try:
            alarm_log_qs = StsFrequency.objects.all()
            if uid:
                alarm_log_qs = alarm_log_qs.filter(uid=uid)
            count = alarm_log_qs.count()
            alarm_log_qs = alarm_log_qs.order_by('-updateTime').values('id', 'uid', 'frequency', 'updateTime',
                                                                       'addTime')[(page - 1) * line:page * line]
            return response.json(0, {'list': list(alarm_log_qs), 'total': count})
        except Exception as e:
            print(e)
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    @staticmethod
    def getDomainLog(request_dict, response):
        page_no = request_dict.get('pageNo', None)
        page_size = request_dict.get('pageSize', None)
        serial_number = request_dict.get('serialNumber', None)

        if not all([page_no, page_size]):
            return response.json(444)

        page = int(page_no)
        line = int(page_size)

        try:
            device_domain_qs = DeviceDomainRegionModel.objects.filter(~Q(country_code=''))
            if serial_number:
                device_domain_qs = device_domain_qs.filter(serial_number__contains=serial_number)
            count = device_domain_qs.count()
            device_domain_qs = device_domain_qs.order_by('-update_time').values()[(page - 1) * line:page * line]

            device_domain_list = []
            for device_domain in device_domain_qs:
                ip = device_domain['ip']
                region_id = device_domain['region_id']
                country_code = device_domain['country_code']
                ip_addr_qs = IPAddr.objects.filter(ip=ip, is_geoip2=False).values('region')
                if ip_addr_qs.exists():
                    region = ip_addr_qs[0]['region']
                else:
                    ip_qs = IPQuery(ip)
                    region = ip_qs.region

                # 港澳台返回美洲域名
                if country_code == 'CN' and region in ['香港', '澳门', '台湾']:
                    country_code = region

                # 查询域名数据
                region_qs = RegionModel.objects.filter(id=region_id).values('api', 'name')

                api = 'https://www.dvema.com/'
                region_name = '美洲'
                if region_qs.exists():
                    api = region_qs[0]['api']
                    region_name = region_qs[0]['name']

                api_region = region_name + '域名'

                device_domain_list.append({
                    'id': device_domain['id'],
                    'serial_number': device_domain['serial_number'],
                    'ip': ip,
                    'region_id': region_id,
                    'country_code': country_code,
                    'api': api,
                    'api_region': api_region,
                    'add_time': device_domain['add_time'].strftime("%Y-%m-%d %H:%M:%S"),
                    'update_time': device_domain['update_time'].strftime("%Y-%m-%d %H:%M:%S"),
                })
            return response.json(0, {'list': device_domain_list, 'total': count})
        except Exception as e:
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    @staticmethod
    def getDomainScanLog(request_dict, response):
        serial_number = request_dict.get('serialNumber', None)

        if not all([serial_number]):
            return response.json(444)

        try:
            scan_log_qs = AppScannedSerial.objects.filter(serial__contains=serial_number).values('ip', 'add_time',
                                                                                                 'update_time')
            device_domain_qs = DeviceDomainRegionModel.objects.filter(serial_number__contains=serial_number).values()
            res = {}
            if scan_log_qs.exists() and device_domain_qs.exists():
                device_domain = device_domain_qs[0]
                domain_ip = device_domain['ip']
                region_id = device_domain['region_id']
                country_code = device_domain['country_code']
                ip_addr_qs = IPAddr.objects.filter(ip=domain_ip, is_geoip2=False).values('region')
                if ip_addr_qs.exists():
                    region = ip_addr_qs[0]['region']
                else:
                    ip_qs = IPQuery(domain_ip)
                    region = ip_qs.region

                # 港澳台返回美洲域名
                if country_code == 'CN' and region in ['香港', '澳门', '台湾']:
                    country_code = region

                # 查询域名数据
                region_qs = RegionModel.objects.filter(id=region_id).values('api', 'name')

                api = 'https://www.dvema.com/'
                region_name = '美洲'
                if region_qs.exists():
                    api = region_qs[0]['api']
                    region_name = region_qs[0]['name']

                api_region = region_name + '域名'

                res = {
                    'serial_number': device_domain['serial_number'],
                    'domain_ip': domain_ip,
                    'scan_ip': device_domain_qs[0]['ip'],
                    'region_id': region_id,
                    'country_code': country_code,
                    'api': api,
                    'api_region': api_region,
                    'domain_add_time': device_domain['add_time'].strftime("%Y-%m-%d %H:%M:%S"),
                    'domain_update_time': device_domain['update_time'].strftime("%Y-%m-%d %H:%M:%S"),
                    'scan_add_time': device_domain_qs[0]['add_time'].strftime("%Y-%m-%d %H:%M:%S"),
                    'scan_update_time': device_domain_qs[0]['update_time'].strftime("%Y-%m-%d %H:%M:%S"),
                }
            return response.json(0, res)
        except Exception as e:
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    @staticmethod
    def getDeviceAbnormalEvent(request_dict, response):
        uid = request_dict.get('uid', None)
        device_type = request_dict.get('deviceType', None)
        version = request_dict.get('version', None)
        event_code = request_dict.get('eventCode', None)
        page_no = request_dict.get('pageNo', None)
        page_size = request_dict.get('pageSize', None)

        if not all([page_no, page_size]):
            return response.json(444)

        page = int(page_no)
        line = int(page_size)

        try:
            query = Q()
            if uid:
                query &= Q(uid=uid)
            if device_type:
                # 处理多个deviceType参数
                device_types = [int(t.strip()) for t in device_type.split(',') if t.strip().isdigit()]
                query &= Q(device_type__in=device_types)
            if version:
                query &= Q(version=version)
            if event_code:
                query &= Q(event_code=event_code)

            abnormal_events = AbnormalEvent.objects.filter(query)
            count = abnormal_events.count()
            event_list = abnormal_events.order_by('-created_time').values(
                'id', 'uid', 'device_type', 'version', 'event_code',
                'content', 'event_time', 'created_time'
            )[(page - 1) * line:page * line]
            
            # 查询device_type对应的name,事件编码对应的事件
            for event in event_list:
                device_type = DeviceTypeModel.objects.filter(type=event['device_type']).first()
                if device_type:
                    event['device_type'] = device_type.name
                else:
                    event['device_type'] = ''

                abnormal_event_code = AbnormalEventCode.objects.filter(event_code=event['event_code']).first()
                if abnormal_event_code:
                    event['event'] = abnormal_event_code.event
                else:
                    event['event'] = ''
            
            return response.json(0, {'list': list(event_list), 'total': count})
        except Exception as e:
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

