import datetime

from django.db import models
from django.db import connections
from django.db.models.fields import AutoField
from django.db.models.fields import BooleanField
from django.db.models.fields import CharField
from django.db.models.fields import DateTimeField
from django.db.models.fields import DecimalField
from django.db.models.fields import IntegerField
from django.db.models.fields.files import FileField

from common.utils import choices


class BaseConnection(object):
    def __init__(self, db_alias='default', *args, **kwargs):
        self.db_alias = db_alias

    def _dict_fetch_all(self, cursor):
        desc = cursor.description
        return [
            dict(zip([col[0] for col in desc], row))
            for row in cursor.fetchall()
        ]

    def query(self, sql):
        cursor = connections[self.db_alias].cursor()
        cursor.execute(sql)
        return self._dict_fetch_all(cursor)


class ConsoleConnection(object):

    def __init__(self, db_alias="console", *args, **kwargs):
        self.db_alias = db_alias

    def _dict_fetch_all(self, cursor):
        desc = cursor.description
        return [
            dict(zip([col[0] for col in desc], row))
            for row in cursor.fetchall()
        ]

    def query(self, sql):
        cursor = connections[self.db_alias].cursor()
        cursor.execute(sql)
        return self._dict_fetch_all(cursor)

    def paginator(cls, page, page_size):
        if page and page_size:
            pre_page = int(page)
            pre_page_size = int(page_size)
            page = (pre_page - 1) * pre_page_size
            page_size = pre_page * pre_page_size
            return "{page}, {page_size}".format(page=page, page_size=page_size)
        return ""

class BaseModel(models.Model):
    id = models.AutoField(primary_key=True, max_length=10)
    deleted = models.BooleanField(default=False)
    created_time = models.DateTimeField(auto_now_add=True, null=True)
    updated_time = models.DateTimeField(auto_now=True, null=True)
    deleted_time = models.DateTimeField(null=True)

    class Meta:
        abstract = True

    # model转字典
    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields:
            value = f.value_from_object(self)
            if isinstance(value, type(datetime)):
                value = value.strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(f, FileField):
                value = value.url if value else None
            data[f.attname] = value
        return data

    # model转字典格式的数据库设计描述
    def to_json(self):
        opts = self._meta
        data = []
        for f in opts.concrete_fields:
            parameter = {}
            parameter["table"] = opts.db_table
            parameter["name"] = f.name
            parameter["kind"] = self.parse_kind(f)
            parameter["default"] = self.parse_default(f.default)
            parameter["desc"] = f.help_text
            data.append(parameter)
        return data

    def parse_default(self, a):
        # if type(a) == NOT_PROVIDED:
        return ""

    def parse_kind(self, a):
        # print(a.name, type(a))
        if type(a) == CharField:
            return "string"
        if type(a) == AutoField:
            return "int"
        if type(a) == BooleanField:
            return "boolean"
        if type(a) == DecimalField:
            return "decimal"
        if type(a) == DateTimeField:
            return "datetime"
        if type(a) == IntegerField:
            return "int"
        return "string"


def model_to_dict(self):
    opts = self._meta
    data = {}
    for f in opts.concrete_fields:
        value = f.value_from_object(self)
        if isinstance(value, type(datetime)):
            value = value.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(f, FileField):
            value = value.url if value else None
        data[f.attname] = value
    return data


class ElectricityUser(BaseModel):
    """ElectricityUser Model """

    id = models.AutoField(primary_key=True, help_text="自增ID")
    number = models.CharField(max_length=64,
                              unique=True,
                              null=False,
                              blank=False,
                              help_text='户号')
    customer_id = models.IntegerField(help_text='所属客户')
    ad_code = models.CharField(max_length=32,
                               null=True,
                               blank=True,
                               help_text="区域编码")
    city_code = models.CharField(max_length=32,
                                 null=True,
                                 blank=True,
                                 help_text="城市编码")
    addr = models.CharField(max_length=256,
                            null=True,
                            blank=True,
                            help_text='用电地址')
    postcode = models.CharField(max_length=32,
                                null=True,
                                blank=True,
                                help_text="邮编")
    transformer_capacity = models.FloatField(default=0, help_text='变压器容量')
    real_capacity = models.FloatField(default=0, help_text='实际容量')
    voltage_level = models.CharField(max_length=16,
                                     null=True,
                                     blank=True,
                                     help_text='电压等级')
    type = models.CharField(max_length=32,
                            null=True,
                            blank=True,
                            help_text='用电类型')
    trusteeship_num = models.FloatField(default=0, help_text='托管电站数')
    ep_factor = models.FloatField(default=0, help_text='电功率考核因素')
    billing_method = models.CharField(max_length=16,
                                      null=True,
                                      blank=True,
                                      help_text='计费方式')
    longitude = models.CharField(max_length=32,
                                 null=True,
                                 blank=True,
                                 help_text='经度')
    latitude = models.CharField(max_length=32,
                                null=True,
                                blank=True,
                                help_text='纬度')
    householder = models.CharField(max_length=64,
                                   null=True,
                                   blank=True,
                                   help_text='户主')
    phone = models.CharField(max_length=16,
                             null=True,
                             blank=True,
                             help_text='户主联系方式')
    is_md = models.BooleanField(default=False, help_text="是否需量申报")

    class Meta:
        db_table = 'electricity_user'

    def __str__(self):
        return self.number



class MonitorPoints(BaseModel):
    name = models.CharField(max_length=64, help_text="监控点名称")
    customer = models.IntegerField(null=True,
                                   help_text="客户")
    electricity_user = models.IntegerField(null=True,
                                           help_text="户号")
    station = models.IntegerField(null=True,
                                  help_text="电站")
    equipment = models.IntegerField(null=True,
                                    help_text="设备")
    frequency = models.IntegerField(null=True, help_text="上传频率, 单位秒")
    template = models.IntegerField(null=True,
                                   help_text="模板")
    current_ratio = models.FloatField(default=1.00, help_text="流变")
    voltage_ratio = models.FloatField(default=1.00, help_text="压变")
    comments = models.CharField(max_length=1024, null=True, help_text="备注")
    # 0异常、1正常、2断电
    status = models.IntegerField(default=1,
                                 help_text="电站状态")

    class Meta:
        db_table = "monitor_points"


class MonitorDevice(BaseModel):
    manufacturer = models.IntegerField(null=True, help_text="制造商")
    model = models.IntegerField(null=True,
                                help_text="监控设备型号")
    imei = models.CharField(max_length=32, null=True, help_text="IMEI号（设备序列号")
    network_type = models.IntegerField(choices=choices.MONITOR_NETWORK_TP,
                                       null=True,
                                       help_text="网络类型")
    sim = models.CharField(max_length=32, null=True, help_text="sim卡号")
    iccid = models.CharField(max_length=32, null=True, help_text="物联网卡号")
    # 1正常、2断电
    status = models.IntegerField(default=1,
                                 help_text="状态")
    current_ratio = models.FloatField(default=1.00, help_text="流变")
    voltage_ratio = models.FloatField(default=1.00, help_text="压变")
    monitor_point = models.ForeignKey(to=MonitorPoints,
                                      on_delete=models.SET_NULL,
                                      null=True,
                                      related_name="ptdv",
                                      help_text="监控点")
    enterprise = models.IntegerField(null=True, help_text="所属管理者公司")
    from_oa = models.BooleanField(default=False, help_text="继承oa")

    class Meta:
        db_table = "monitor_device"


class MonitorMetaDataForTest(BaseModel):
    imei = models.CharField(max_length=32, null=True, help_text="imei号")
    ua = models.FloatField(null=True, help_text="A相电流")
    ub = models.FloatField(null=True, help_text="B相电流")
    uc = models.FloatField(null=True, help_text="C相电流")

    uab = models.FloatField(null=True, help_text="AB线电压")
    ubc = models.FloatField(null=True, help_text="BC线电压")
    uca = models.FloatField(null=True, help_text="CA线电压")

    ia = models.FloatField(null=True, help_text="A相电流")
    ib = models.FloatField(null=True, help_text="B相电流")
    ic = models.FloatField(null=True, help_text="C相电流")
    ir = models.FloatField(null=True, help_text="剩余电流")

    pa = models.FloatField(null=True, help_text="A相有功功率")
    pb = models.FloatField(null=True, help_text="B相有功功率")
    pc = models.FloatField(null=True, help_text="C相有功功率")
    p = models.FloatField(null=True, help_text="总有功功率")

    qa = models.FloatField(null=True, help_text="A相无功功率")
    qb = models.FloatField(null=True, help_text="B相无功功率")
    qc = models.FloatField(null=True, help_text="C相无功功率")
    q = models.FloatField(null=True, help_text="总无功功率")

    sa = models.FloatField(null=True, help_text="A相视在功率")
    sb = models.FloatField(null=True, help_text="A相视在功率")
    sc = models.FloatField(null=True, help_text="A相视在功率")
    s = models.FloatField(null=True, help_text="A相视在功率")

    pfa = models.FloatField(null=True, help_text="A相功率因数")
    pfb = models.FloatField(null=True, help_text="B相功率因数")
    pfc = models.FloatField(null=True, help_text="C相功率因数")
    pf = models.FloatField(null=True, help_text="总功率因数")

    f = models.FloatField(null=True, help_text="电源频率")

    ept = models.FloatField(null=True, help_text="总有功电能")
    eqi = models.FloatField(null=True, help_text="正向无功电能")
    eqe = models.FloatField(null=True, help_text="反向无功电能")

    p_d = models.FloatField(null=True, help_text="总有功功率实时需量")

    lvur = models.FloatField(null=True, help_text="三相电压不平衡度")
    iur = models.FloatField(null=True, help_text="三相电流不平衡度")

    ua_thd = models.FloatField(null=True, help_text="A相电压总谐波畸变率")
    ub_thd = models.FloatField(null=True, help_text="B相电压总谐波畸变率")
    uc_thd = models.FloatField(null=True, help_text="C相电压总谐波畸变率")

    ia_thd = models.FloatField(null=True, help_text="A相电流总谐波畸变率")
    ib_thd = models.FloatField(null=True, help_text="B相电流总谐波畸变率")
    ic_thd = models.FloatField(null=True, help_text="C相电流总谐波畸变率")

    t1 = models.FloatField(null=True, help_text="温度1")
    t2 = models.FloatField(null=True, help_text="温度2")
    t3 = models.FloatField(null=True, help_text="温度3")
    t4 = models.FloatField(null=True, help_text="温度4")
    tm = models.DateTimeField(null=True, help_text="上传时间")

    segment1 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment2 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment3 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment4 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment5 = models.CharField(max_length=32, default="NA", null=True, help_text="冗余字段")
    segment6 = models.CharField(max_length=32, default="NA", null=True, help_text="冗余字段")

    class Meta:
        db_table = "mo_test"


class MonitorMetaData(BaseModel):
    point_id = models.IntegerField(null=True, help_text="监控点")
    ua = models.FloatField(null=True, help_text="A相电流")
    ub = models.FloatField(null=True, help_text="B相电流")
    uc = models.FloatField(null=True, help_text="C相电流")

    uab = models.FloatField(null=True, help_text="AB线电压")
    ubc = models.FloatField(null=True, help_text="BC线电压")
    uca = models.FloatField(null=True, help_text="CA线电压")

    ia = models.FloatField(null=True, help_text="A相电流")
    ib = models.FloatField(null=True, help_text="B相电流")
    ic = models.FloatField(null=True, help_text="C相电流")
    ir = models.FloatField(null=True, help_text="剩余电流")

    pa = models.FloatField(null=True, help_text="A相有功功率")
    pb = models.FloatField(null=True, help_text="B相有功功率")
    pc = models.FloatField(null=True, help_text="C相有功功率")
    p = models.FloatField(null=True, help_text="总有功功率")

    qa = models.FloatField(null=True, help_text="A相无功功率")
    qb = models.FloatField(null=True, help_text="B相无功功率")
    qc = models.FloatField(null=True, help_text="C相无功功率")
    q = models.FloatField(null=True, help_text="总无功功率")

    sa = models.FloatField(null=True, help_text="A相视在功率")
    sb = models.FloatField(null=True, help_text="A相视在功率")
    sc = models.FloatField(null=True, help_text="A相视在功率")
    s = models.FloatField(null=True, help_text="A相视在功率")

    pfa = models.FloatField(null=True, help_text="A相功率因数")
    pfb = models.FloatField(null=True, help_text="B相功率因数")
    pfc = models.FloatField(null=True, help_text="C相功率因数")
    pf = models.FloatField(null=True, help_text="总功率因数")

    f = models.FloatField(null=True, help_text="电源频率")

    ept = models.FloatField(null=True, help_text="总有功电能")
    eqi = models.FloatField(null=True, help_text="正向无功电能")
    eqe = models.FloatField(null=True, help_text="反向无功电能")

    p_d = models.FloatField(null=True, help_text="总有功功率实时需量")

    lvur = models.FloatField(null=True, help_text="三相电压不平衡度")
    iur = models.FloatField(null=True, help_text="三相电流不平衡度")

    ua_thd = models.FloatField(null=True, help_text="A相电压总谐波畸变率")
    ub_thd = models.FloatField(null=True, help_text="B相电压总谐波畸变率")
    uc_thd = models.FloatField(null=True, help_text="C相电压总谐波畸变率")

    ia_thd = models.FloatField(null=True, help_text="A相电流总谐波畸变率")
    ib_thd = models.FloatField(null=True, help_text="B相电流总谐波畸变率")
    ic_thd = models.FloatField(null=True, help_text="C相电流总谐波畸变率")

    t1 = models.FloatField(null=True, help_text="温度1")
    t2 = models.FloatField(null=True, help_text="温度2")
    t3 = models.FloatField(null=True, help_text="温度3")
    t4 = models.FloatField(null=True, help_text="温度4")
    tm = models.DateTimeField(null=True, help_text="上传时间")

    segment1 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment2 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment3 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment4 = models.FloatField(default=0, null=True, help_text="冗余字段")
    segment5 = models.CharField(max_length=32, default="NA", null=True, help_text="冗余字段")
    segment6 = models.CharField(max_length=32, default="NA", null=True, help_text="冗余字段")

    class Meta:
        abstract = True


class MonitorAlarm(BaseModel):
    name = models.CharField(max_length=64, help_text="告警内容")
    type = models.SmallIntegerField(choices=choices.MONITOR_ALARM_TYPE,
                                    help_text="告警类型")
    level = models.SmallIntegerField(choices=choices.MONITOR_ALARM_LEVEL,
                                     help_text="告警等级")
    duration = models.IntegerField(help_text="持续时间(分钟)")
    status = models.SmallIntegerField(choices=choices.MONITOR_ALARM_STATUS,
                                      help_text="处理状态")
    monitor_point = models.ForeignKey(to=MonitorPoints,
                                      on_delete=models.SET_NULL,
                                      null=True,
                                      help_text="监控点")
    is_end = models.BooleanField(default=False, help_text="告警结束")
    comments = models.CharField(max_length=1024, help_text="备注")

    class Meta:
        db_table = "monitor_alarm"
