from django.db import transaction
from rest_framework import serializers as serialzier

from console.video_management.models import Device

from console.video_management.models import VideoSystem

from common.third_party_api.surveillance.imou import APIClient
from common.third_party_api.surveillance.ys7 import YSCloudClient

from common.accounts.models import Users

from console.powerstation.models import PowerStation

from console.customer.models import Customer

SYSTEM_MAP = {"1": APIClient, "2": YSCloudClient}


class VideoSystemCreateSerializer(serialzier.ModelSerializer):
    app_key = serialzier.CharField(required=True,
                                   allow_blank=False,
                                   allow_null=False)
    app_secret = serialzier.CharField(required=True,
                                      allow_blank=False,
                                      allow_null=False)
    home_url = serialzier.CharField(required=True,
                                    allow_blank=False,
                                    allow_null=False)
    system = serialzier.CharField(required=True,
                                  allow_blank=False,
                                  allow_null=False)
    customer_id = serialzier.IntegerField(required=False, allow_null=True)
    name = serialzier.CharField(required=False, allow_blank=True, allow_null=True)

    class Meta:
        model = VideoSystem
        fields = "__all__"

    def validate(self, attrs):
        request = self.context.get("request")
        system = VideoSystem.objects.filter(app_key=attrs.get("app_key")).first()
        if system and system.id != request.data.get("id"):
            raise serialzier.ValidationError("app_key已存在")
        return attrs


class DeviceSerializer(serialzier.ModelSerializer):
    deviceSerial = serialzier.CharField(required=True,
                                        allow_null=False,
                                        allow_blank=False)
    channal = serialzier.CharField(required=False,
                                   allow_null=True,
                                   allow_blank=True)
    deviceName = serialzier.CharField(required=False,
                                      allow_null=True,
                                      allow_blank=True)
    deviceType = serialzier.CharField(required=False,
                                      allow_null=True,
                                      allow_blank=True)
    customer_id = serialzier.IntegerField(required=False, allow_null=True)
    validateCode = serialzier.CharField(required=False,
                                        allow_blank=True,
                                        allow_null=True)
    system = serialzier.CharField(required=False,
                                  allow_null=True,
                                  allow_blank=True)
    status = serialzier.BooleanField(required=False, allow_null=True)
    name = serialzier.CharField(required=False, allow_blank=True, allow_null=True)
    type = serialzier.CharField(required=False, allow_null=True, allow_blank=True)
    user = serialzier.SerializerMethodField(read_only=True)
    video_system = serialzier.SerializerMethodField()
    station = serialzier.SerializerMethodField()
    customer = serialzier.SerializerMethodField()
    video_token = serialzier.SerializerMethodField()
    system_name = serialzier.SerializerMethodField()

    def get_system_name(self, obj):
        return obj.system.name if obj.system else None

    def get_video_token(self, obj):
        return obj.system.access_token if obj.system else None

    def get_customer(self, obj):
        return {
            "id": obj.customer.id,
            "name": obj.customer.name
        } if obj.customer else None

    def get_station(self, obj):
        return {
            "id": obj.station.id,
            "name": obj.station.name
        } if obj.station else None

    def get_video_system(self, obj):
        return obj.system.system

    def get_user(self, obj):
        return {
            "id": obj.user.id,
            "name": obj.user.nickname
        } if obj.user else None

    class Meta:
        model = Device
        fields = ("id", "deviceSerial", "channal", "deviceName", "deviceType", "station", "customer",
                  "customer_id", "validateCode", "video_system", "status", "name", "type", "user", "system",
                  "system_id", "video_token", "system_name")

    def validate(self, attrs):
        system = VideoSystem.objects.filter(id=attrs.get("system")).first()
        if not system:
            raise serialzier.ValidationError("平台{}不存在".format(attrs.get("system")))
        return attrs

    @transaction.atomic()
    def create(self, validated_data):
        point = transaction.savepoint()
        try:
            instance = Device.objects.create(**validated_data)
            request = self.context.get("request")
            system = VideoSystem.objects.filter(account=request.user).first()
            client = SYSTEM_MAP.get(validated_data.get("system"))(system)
            param = {
                "deviceSerial": validated_data.get("deviceSerial"),
                "validateCode": validated_data.get("validateCode")
            }
            client.create_device(**param)
            transaction.savepoint_commit(point)
            return instance
        except Exception as e:
            transaction.savepoint_rollback(point)
            raise serialzier.ValidationError(e)


class DeviceBindSerializer(serialzier.Serializer):
    deviceSerial = serialzier.CharField(required=True, allow_null=False, allow_blank=False)
    deviceName = serialzier.CharField(required=False, allow_blank=True, allow_null=True)
    name = serialzier.CharField(required=False, allow_null=True, allow_blank=True)
    type = serialzier.CharField(required=True, allow_blank=False, allow_null=False)
    system = serialzier.CharField(required=True, allow_null=False, allow_blank=False)
    station_id = serialzier.IntegerField(required=False, allow_null=True)
    customer_id = serialzier.CharField(required=False, allow_null=True, allow_blank=True)

    def validate(self, attrs):
        device = Device.objects.filter(deviceSerial=attrs.get("deviceSerial")).first()
        if device:
            raise serialzier.ValidationError("设备已被绑定")
        if attrs.get("type") not in ["1", "2"]:
            raise serialzier.ValidationError("设备类型参数不正确")
        # if attrs.get("system") not in ["1", "2"]:
        #     raise serialzier.ValidationError("视频云平台参数不正确")
        system = VideoSystem.objects.filter(id=attrs.get("system")).first()
        if not system:
            raise serialzier.ValidationError("视频管理后台不存在")
        if attrs.get("station_id"):
            power_station = PowerStation.objects.filter(id=attrs.get("station_id")).first()
            if not power_station:
                raise serialzier.ValidationError("电站%s不存在" % attrs.get("station_id"))
        if attrs.get("customer_id"):
            power_station = Customer.objects.filter(id=attrs.get("customer_id")).first()
            if not power_station:
                raise serialzier.ValidationError("客户%s不存在" % attrs.get("customer_id"))
        attrs["system"] = system
        return attrs

    def create(self, validated_data):
        instance = Device.objects.create(
            deviceSerial=validated_data.get("deviceSerial"),
            deviceName=validated_data.get("deviceName"),
            name=validated_data.get("name"),
            type=validated_data.get("type"),
            system=validated_data.get("system"),
            customer_id=validated_data.get("customer_id"),
            station_id=validated_data.get("station_id"),
            channal=0 if validated_data.get("system").system == "1" else 1
        )
        return instance


class DeviceBindUserSerializer(serialzier.Serializer):
    user_id = serialzier.CharField(required=True, allow_blank=False, allow_null=False)

    def validate(self, attrs):
        user = Users.objects.filter(id=attrs.get("user_id")).first()
        if not user:
            raise serialzier.ValidationError("用户{}不存在".format(attrs.get("user_id")))
        attrs["user"] = user
        return attrs

    def update(self, instance, validated_data):
        instance.user = validated_data.get("user")
        instance.save()
        return instance


class VideoSystemSerializer(serialzier.ModelSerializer):
    class Meta:
        model = VideoSystem
        fields = ("id", "name", "customer_id", "system", "app_key", "app_secret",
                  "home_url")


class DeviceUpdateSerializer(serialzier.Serializer):
    deviceSerial = serialzier.CharField(required=False, allow_blank=True, allow_null=True)
    deviceName = serialzier.CharField(required=False, allow_null=True, allow_blank=True)
    name = serialzier.CharField(required=False, allow_blank=True, allow_null=True)
    system = serialzier.IntegerField(required=False, allow_null=True)
    type = serialzier.IntegerField(required=False, allow_null=True)
    customer_id = serialzier.IntegerField(required=False, allow_null=True)
    station_id = serialzier.IntegerField(required=False, allow_null=True)

    def validate(self, attrs):
        request = self.context.get("request")
        if attrs.get("deviceSerial"):
            device = Device.objects.filter(deviceSerial=attrs.get("deviceSerial")).first()
            if device and device.id != request.data.get("id"):
                raise serialzier.ValidationError("设备{}已经被绑定".format(attrs.get("deviceSerial")))
        return attrs

    def update(self, instance, validated_data):
        instance.deviceSerial = validated_data.get("deviceSerial")
        instance.deviceName = validated_data.get("deviceName")
        instance.name = validated_data.get("name")
        instance.system_id = validated_data.get("system")
        instance.type = validated_data.get("type")
        instance.customer_id = validated_data.get("customer_id")
        instance.station_id = validated_data.get("station_id")
        instance.save()
        instance.system.save()
        return instance
