import datetime

from django.conf import settings
from django.db.transaction import atomic
from django.views.decorators.gzip import gzip_page
from django.utils.decorators import method_decorator
from rest_framework import status
from rest_framework.response import Response

from common.utils.exceptions import ValidationError, ServiceHandleException
from common.utils.views import BaseApiView
from common.utils.return_structure import general_message
from common.utils.choices import (MONITOR_MANUFACTURER_METADATA,
                                  MONITOR_NETWORK_METADATA)
from common.third_party_api.qucloud.clients import cos_client
from common.utils.service_code import THIRD_PARTY_API_ERROR
from common.utils.str_utils import make_uuid

from console.monitor.services import monitor_service
from console.monitor.serializers import (
    MonitorDeviceLSerializer, MonitorDeviceCSerializer,
    MonitorDeviceUSerializer, MonitorPointsLSerializer,
    MonitorPointsCSerializer, MonitorPointsUSerializer,
    MonitorTemplateCSerializer, MonitorTemplateUSerializer,
    MonitorDevicesRecordCSerializer, MonitorDevicesRecordUSerializer,
    AlarmUSerializer)
from console.monitor.repositories import MonitorQuerySet, monitor_sql_repo
from console.monitor.filters import MonitorPointsLFilter
from console.monitor.tasks import import_devices

from console.monitor.models import MonitorDevicesRecord, MonitorDevicesImportRecord


class MonitorManufacturerLView(BaseApiView):
    def get(self, request, *args, **kwargs):
        data = general_message(list=MONITOR_MANUFACTURER_METADATA)
        return Response(data, status=status.HTTP_200_OK)


class MonitorNetworkLView(BaseApiView):
    def get(self, request, *args, **kwargs):
        data = general_message(list=MONITOR_NETWORK_METADATA)
        return Response(data, status=status.HTTP_200_OK)


@method_decorator(gzip_page, name='dispatch')
class MonitorDevicesLCView(BaseApiView):
    queryset = MonitorQuerySet.monitor_devices_lc
    serializer_class = MonitorDeviceLSerializer

    def get(self, request, *args, **kwargs):
        query = request.GET.copy()
        page = query.get("page", 1)
        page_size = query.get("page_size", 10)
        query.update({"page": page, "page_size": page_size})
        rst, count = monitor_service.get_monitor_devices(
            self.enterprise_ids, **query)
        data = general_message(list=rst, count=count)
        return Response(data, status=status.HTTP_200_OK)

    def post(self, request, *args, **kwargs):
        serializer = MonitorDeviceCSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        rst = monitor_service.create_monitor_device(self.enterprise.id,
                                                    **serializer.data)
        data = general_message(bean=rst.to_dict())
        return Response(data, status=status.HTTP_200_OK)


class MonitorDevicesUDView(BaseApiView):
    queryset = MonitorQuerySet.monitor_devices_lc
    serializer_class = MonitorDeviceUSerializer

    def get(self, request, device_id, *args, **kwargs):
        # rst = monitor_service.get_monitor_device(device_id)
        query = {"device_id": device_id}
        rst, _ = monitor_service.get_monitor_devices(self.enterprise_ids, **query)
        data = general_message(bean=rst[0])
        return Response(data, status=status.HTTP_200_OK)

    def put(self, request, device_id, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={"device_id": device_id})
        serializer.is_valid()
        monitor_service.update_monitor_device(self.enterprise.id,
                                              **serializer.validated_data)
        data = general_message("修改成功")
        return Response(data, status=status.HTTP_200_OK)

    def delete(self, request, device_id, *args, **kwargs):
        self.queryset.filter(id=device_id).delete()
        data = general_message()
        return Response(data, status=status.HTTP_200_OK)


class MonitorDevicesImportCView(BaseApiView):
    def post(self, request, *args, **kwargs):
        url = request.data.get("url")
        record = MonitorDevicesImportRecord.objects.create(order_id=make_uuid(), url=url)
        import_devices.apply_async(kwargs={'record_id': record.id,
                                           'url': url,
                                           "enterprise_id": self.enterprise.id})
        dt = general_message(bean={"record_id": record.id})
        return Response(dt, status=status.HTTP_200_OK)


class MonitorDevicesImportRecordLView(BaseApiView):
    def get(self, request, record_id, *args, **kwargs):
        record = MonitorDevicesImportRecord.objects.get(id=record_id)
        dt = general_message(bean=record.to_dict())
        return Response(dt, status=status.HTTP_200_OK)


@method_decorator(gzip_page, name='dispatch')
class MonitorPointsLCView(BaseApiView):
    queryset = MonitorQuerySet.monitor_pointers_l
    serializer_class = MonitorPointsLSerializer
    filter_class = MonitorPointsLFilter

    def get(self, request, *args, **kwargs):
        query = request.GET.copy()
        page = query.get("page", 1)
        page_size = query.get("page_size", 10)
        query.update({"page": page, "page_size": page_size})
        if self.is_manager:
            rst, count = monitor_service.get_monitor_points(
                self.enterprise_ids, **query)
        else:
            rst, count = monitor_service.get_monitor_points(
                [str(self.service_ent_id)], **query)

        data = general_message(list=rst, count=count)
        return Response(data, status=status.HTTP_200_OK)

    def post(self, request, *args, **kwargs):
        monitor_record = MonitorDevicesRecord.objects.filter(id=request.data.get("id")).first()
        # if not monitor_record:
        #     return Response(error_message(code=400, msg_show="审批单{}不存在".format(request.data.get("id"))))
        serializer = MonitorPointsCSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        rst = monitor_service.create_monitor_points(**serializer.data)
        if monitor_record:
            monitor_record.status = 1
            monitor_record.approver_id=self.user.id
            monitor_record.online_time=datetime.datetime.now()
            monitor_record.save()
        dt = rst.to_dict()
        dt.update({"imei": rst.imei, "device_id": rst.device_id})
        data = general_message(bean=dt)
        return Response(data, status=status.HTTP_200_OK)


class MonitorPointsUDView(BaseApiView):
    queryset = MonitorQuerySet.monitor_pointers_l
    serializer_class = MonitorPointsUSerializer

    def get(self, request, point_id, *args, **kwargs):
        rst = monitor_service.get_monitor_point(self.enterprise_ids, point_id)
        data = general_message(bean=rst)
        return Response(data, status=status.HTTP_200_OK)

    def put(self, request, point_id, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={"point_id": point_id})
        serializer.is_valid()
        monitor_service.update_monitor_points(**serializer.data)
        rst = monitor_service.get_monitor_point(self.enterprise_ids, point_id)
        data = general_message(bean=rst)
        return Response(data, status=status.HTTP_200_OK)

    def delete(self, request, point_id, *args, **kwargs):
        self.queryset.filter(id=point_id).delete()
        data = general_message()
        return Response(data, status=status.HTTP_200_OK)


class MonitorTemplateLCView(BaseApiView):
    queryset = MonitorQuerySet.monitor_templates_l
    serializer_class = MonitorTemplateCSerializer

    def get(self, request, *args, **kwargs):
        query = request.GET.copy()
        page = query.get("page", 1)
        page_size = query.get("page_size", 10)
        query.update({"page": page, "page_size": page_size})
        rst, count = monitor_service.get_templates(**query)
        data = general_message(list=rst, count=count)
        return Response(data, status=status.HTTP_200_OK)

    def post(self, request, *args, **kwargs):
        serializer = MonitorTemplateCSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        rst = monitor_service.create_templates(**serializer.data)
        dt = rst.to_dict()
        data = general_message(bean=dt)
        return Response(data, status=status.HTTP_200_OK)


class MonitorDevicesRecordLCView(BaseApiView):
    queryset = MonitorQuerySet.monitor_devices_lc
    serializer_class = MonitorDevicesRecordCSerializer

    def get(self, request, *args, **kwargs):
        query = request.GET.copy()
        page = query.get("page", 1)
        page_size = query.get("page_size", 10)
        # query.update({"page": page, "page_size": page_size})
        query["page"] = int(page)
        query["page_size"] = int(page_size)
        rst, count = monitor_service.get_monitor_device_records(self.enterprise_ids, **query)
        data = general_message(list=rst, count=count)
        return Response(data, status=status.HTTP_200_OK)

    def post(self, request, *args, **kwargs):
        serializer = MonitorDevicesRecordCSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        monitor_service.create_or_update_monitor_device_record(worker_id=self.user.id,
                                                               enterprise_id=self.enterprise.id,
                                                               **serializer.data)
        data = general_message(bean=serializer.data)
        return Response(data, status=status.HTTP_200_OK)


class MonitorDevicesRecordRUDView(BaseApiView):
    def get(self, request, record_id, *args, **kwargs):
        rst, _ = monitor_service.get_monitor_device_records(self.enterprise_ids,
                                                            **{"record_id": str(record_id)})
        data = general_message(bean=rst[0] if rst else None)
        return Response(data, status=status.HTTP_200_OK)

    @atomic()
    def put(self, request, record_id, *args, **kwargs):
        serializer = MonitorDevicesRecordUSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        rst, _ = monitor_service.update_monitor_device_record(self.enterprise_ids,
                                                              enterprise_id=self.enterprise.id,
                                                              approver_id=self.user.id,
                                                              **serializer.data)

        # point_data = serializer.data.get("point_data", {})
        # if point_data:
        #     # 创建监控点
        #     point = monitor_service.create_monitor_points(**point_data)
        #     # 移动monitor库mo_test数据到对应的户号表里面
        #     monitor_service.move_data_to_number(
        #         point.electricity_user.number, serializer.data.get("imei"), point.id)
        data = general_message(bean=rst[0] if rst else None)
        return Response(data, status=status.HTTP_200_OK)

    def delete(self, request, record_id, *args, **kwargs):
        monitor_service.delete_monitor_device_record(record_id)
        data = general_message(msg_show="删除成功")
        return Response(data, status=status.HTTP_200_OK)


class MonitorDevicesRecordUploadView(BaseApiView):
    def post(self, request, *args, **kwargs):
        bucket = settings.CLOUD_COS.MONITOR_RECORD_BUCKET
        file_id = request.GET.get("file_id")
        imei = request.GET.get("imei")
        if not file_id or not imei:
            raise ValidationError("缺少file_id或imei参数")
        if not request.FILES or not request.FILES.get('file'):
            raise ValidationError("请指定需要上传的文件")
        file = request.FILES.get('file')
        suffix = file.name.split(".")[-1]
        if suffix.lower() not in ["png", "jpg", "jpeg"]:
            raise ValidationError("文件类型仅支持png、jpg、jpeg")
        key = imei + "/" + file_id + "." + file.name.split(".")[-1]
        response = cos_client.put_object(Bucket=bucket,
                                         Body=file,
                                         Key=key,
                                         EnableMD5=False)
        url = cos_client._conf.uri(bucket=bucket, path=key)
        if response.get("ETag"):
            return Response({"url": url}, status=status.HTTP_200_OK)
        else:
            raise ServiceHandleException(msg_show="上传失败",
                                         msg="upload error",
                                         code=THIRD_PARTY_API_ERROR)


class MonitorRealDataLView(BaseApiView):
    def get(self, request, *args, **kwargs):
        imei = request.GET.get("imei")
        if not imei:
            raise ValidationError("参数imei不能为空")
        dt, current_ratio, voltage_ratio, is_calculated = monitor_service.get_real_data(
            imei=imei)
        excess = {
            "current_ratio": 1,
            "voltage_ratio": 1,
            "is_calculated": is_calculated
        }
        if dt:
            dt.update(excess)
        data = general_message(bean=dt)
        return Response(data, status=status.HTTP_200_OK)

    def put(self, request, *args, **kwargs):
        imei = request.GET.get("imei")
        dt = request.data
        if not imei:
            raise ValidationError("参数imei不能为空")
        monitor_service.update_real_data_parameter(imei, dt)
        dt, current_ratio, voltage_ratio, is_calculated = monitor_service.get_real_data(
            imei=imei)
        excess = {
            "current_ratio": current_ratio,
            "voltage_ratio": voltage_ratio,
            "is_calculated": is_calculated
        }
        dt.update(excess)
        data = general_message(bean=dt)
        return Response(data, status=status.HTTP_200_OK)


@method_decorator(gzip_page, name='dispatch')
class MonitorRangeDataLView(BaseApiView):
    def get(self, request, *args, **kwargs):
        query = request.GET.copy()
        rst = monitor_service.get_range_data(**query)
        if isinstance(rst, dict):
            data = general_message(bean=rst)
        else:
            data = general_message(list=rst)
        return Response(data, status=status.HTTP_200_OK)


class MonitorAlarmLView(BaseApiView):
    def get(self, request, *args, **kwargs):
        query = request.GET.copy()
        if self.is_customer:
            query.update({"customer_id": self.customer.id})
        else:
            query.update({"enterprise_ids": self.enterprise_ids})
        rst, count, page, page_size = monitor_service.get_alarm(**query)
        data = general_message(list=rst, count=count, page=page, page_size=page_size)
        return Response(data, status=status.HTTP_200_OK)


class MonitorAlarmRUDView(BaseApiView):
    def get(self, request, alarm_id, *args, **kwargs):
        query = request.GET.copy()
        query.update({"alarm_id": alarm_id})
        rt = {}
        rst, _, _, _ = monitor_service.get_alarm(**query)
        if rst:
            rt = rst[0]
        data = general_message(bean=rt)
        return Response(data, status=status.HTTP_200_OK)

    def put(self, request, alarm_id, *args, **kwargs):
        serializer = AlarmUSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        monitor_service.update_alarm(**serializer.data)
        rst, _, _, _ = monitor_service.get_alarm(**{"alarm_id": alarm_id})
        data = general_message(bean=rst[0] if rst else {})
        return Response(data, status=status.HTTP_200_OK)

    def delete(self, request, alarm_id, *args, **kwargs):
        monitor_service.delete_alarm(alarm_id)
        data = general_message(msg_show="删除成功")
        return Response(data, status=status.HTTP_200_OK)


class MonitorTemplateRUDView(BaseApiView):
    queryset = MonitorQuerySet.monitor_templates_l
    serializer_class = MonitorTemplateUSerializer

    def get(self, request, template_id, *args, **kwargs):
        rst = monitor_service.get_template(template_id)
        data = general_message(bean=rst.to_dict())
        return Response(data, status=status.HTTP_200_OK)

    def put(self, request, template_id, *args, **kwargs):
        serializer = MonitorTemplateUSerializer(
            data=request.data, context={"template_id": template_id})
        serializer.is_valid(raise_exception=True)
        rst = monitor_service.update_template(**serializer.data)
        dt = rst.to_dict()
        data = general_message(bean=dt)
        return Response(data, status=status.HTTP_200_OK)

    def delete(self, request, template_id, *args, **kwargs):
        monitor_service.delete_template(template_id)
        return Response(general_message(), status=status.HTTP_200_OK)


@method_decorator(gzip_page, name='dispatch')
class MonitorPointDataLView(BaseApiView):
    def get(self, request, number, point_id, *args, **kwargs):
        rst = monitor_service.get_monitor_data(number, point_id)
        data = general_message(list=rst.values())
        return Response(data, status=status.HTTP_200_OK)


class StationMonitorPoints(BaseApiView):
    def get(self, request, number, station_id, *args, **kwargs):
        points = monitor_service.get_old_station_points(number)
        data = general_message(list=points)
        return Response(data, status=status.HTTP_200_OK)


class StationMonitorPointsRealData(BaseApiView):
    def get(self, request, number, station_id, point_id, *args, **kwargs):
        if number == "3107593345":
            number = "0060349055"
            if point_id == "5377":
                point_id = "1"
            else:
                point_id = "2"
        rst = monitor_service.get_real_old_station_point_realdata(
            number, point_id)
        if rst:
            rst = rst[0]
        else:
            rst = {}
        data = general_message(bean=rst)
        return Response(data, status=status.HTTP_200_OK)


@method_decorator(gzip_page, name='dispatch')
class StationMonitorPointsData(BaseApiView):
    def get(self, request, number, station_id, point_id, *args, **kwargs):
        td = datetime.datetime.now()
        today = td.strftime("%Y-%m-%d")
        query = request.GET.copy()
        tomorrow = (td + datetime.timedelta(days=1)).strftime("%Y-%m-%d")
        start_time = request.GET.get("start_time", today)
        end_time = request.GET.get("end_time", tomorrow)
        query.update({"start_time": start_time, "end_time": end_time})
        if number == "3107593345":
            number = "0060349055"
            if point_id == "5377":
                point_id = "1"
            else:
                point_id = "2"
        capacity = monitor_service.get_point_transformer_capacity(
            number, point_id)
        rst = monitor_service.get_real_old_station_point_data(
            number, point_id, capacity, **query)
        count = len(rst)
        data = general_message(list=rst, count=count)
        return Response(data, status=status.HTTP_200_OK)


@method_decorator(gzip_page, name='dispatch')
class StationMonitorPointsStatisticsData(BaseApiView):
    def get(self, request, number, station_id, point_id, *args, **kwargs):
        td = datetime.datetime.now()
        today = td.strftime("%Y-%m-%d")
        tomorrow = (td + datetime.timedelta(days=1)).strftime("%Y-%m-%d")
        start_time = request.GET.get("start_time", today)
        end_time = request.GET.get("end_time", tomorrow)
        if number == "3107593345":
            number = "0060349055"
            if point_id == "5377":
                point_id = "1"
            elif point_id == "5411":
                point_id = "2"
            else:
                point_id = "3"
        rst = monitor_service.get_real_old_station_point_statistic_data(
            number, point_id, start_time, end_time)
        data = general_message(bean=rst)
        return Response(data, status=status.HTTP_200_OK)


class TestMonitorView(BaseApiView):
    def get(self, request, *args, **kwargs):
        # monitor_sql_repo.check_monitor_over_tm()
        # monitor_sql_repo.insert_oa_real_data()
        # monitor_sql_repo.check_monitor_data_density()
        # monitor_sql_repo.insert_changsha_mo_dt_sync()
        # monitor_sql_repo.sync_monitor_points_and_devices_from_oa()
        # monitor_sql_repo.sync_monitor_points_from_oa()
        return Response(status=status.HTTP_200_OK)


@method_decorator(gzip_page, name='dispatch')
class MonitorHTPointsLCView(BaseApiView):
    def get(self, request, *args, **kwargs):
        query = request.GET.copy()
        page = query.get("page", 1)
        page_size = query.get("page_size", 10)
        query.update({"page": page, "page_size": page_size})
        if self.is_manager:
            rst, count = monitor_service.get_monitor_ht_points(
                self.enterprise_ids, **query)
        else:
            rst, count = monitor_service.get_monitor_ht_points(
                [str(self.service_ent_id)], **query)

        data = general_message(list=rst, count=count)
        return Response(data, status=status.HTTP_200_OK)


class MonitorHTRealDataLView(BaseApiView):
    def get(self, request, *args, **kwargs):
        imei = request.GET.get("imei")
        if not imei:
            data = general_message()
        else:
            dt= monitor_service.get_ht_real_data(imei=imei)
            data = general_message(bean=dt)
        return Response(data, status=status.HTTP_200_OK)
