import redis
import json
import time
import random
from typing import Any
from enum import Enum

from utils import FORMAT_TIME

class Tag(Enum):
    PAY = "#####"
    PAY_RES = "*****"

class Mac2(object):
    def __init__(self,res) -> None:
        self.termNo = res[0:8]
        self.mac2 = res[8:16]


class SerialNumber(object):
    def __init__(self):
        self.time = time.strftime("%Y%m%d%H%M%S", time.localtime(int(time.time())))
        self.randint = random.randint(10, 99)

    def create(self, parkId):
        '''生成交易编号'''
        return f"{parkId}{self.time}{self.randint}"

class PaySignal(object):
    tag = Tag.PAY.value
    def __init__(self,address:dict,parkId:str) -> None:
        self.middleware = redis.Redis(
            host=address["host"],
            port=address["port"],
            password=address["password"],
            decode_responses=True
        )
        self.parkId = parkId
    
    def GetPaySignal(self,lane:int):
        return self.middleware.get(f"{self.tag}{self.parkId}{lane}")

    def SetPaySignal(self,orderItem:dict,lane:int):
        orderItemSrt = json.dumps(orderItem)
        self.middleware.set(f"{self.tag}{self.parkId}{lane}", orderItemSrt)

    def ClearPaySignal(self,lane:int):
        self.middleware.set(f"{self.tag}{self.parkId}{lane}", "")

class PayResSignal(object):
    tag = Tag.PAY_RES.value
    def __init__(self,address:dict,parkId:str) -> None:
        self.middleware = redis.Redis(
            host=address["host"],
            port=address["port"],
            password=address["password"],
            decode_responses=True
        )
        self.parkId = parkId

    def GetPayRes(self,lane:int)->Any:
        startTime = int(time.time())
        while True:
            endTime = int(time.time())
            if endTime - startTime > 3:
                res = "E12-交易超时"
                break
            res = self.middleware.get(f"{self.tag}{self.parkId}{lane}")
            if res:
                break
        return res

    def SetPayResSignal(self,res:str,lane:int):
        self.middleware.set(f"{self.tag}{self.parkId}{lane}", res)

    def ClearResSignal(self,lane:int):
        self.middleware.set(f"{self.tag}{self.parkId}{lane}", "")


class SwitchOrder(object):
    def __init__(self) -> None:
        self._plate = ""
        self._plateColor = ""
        self._entryLane = ""
        self._exitLane = ""
        self._entryTime = ""
        self._exitTime = ""
        self._statisticDate = ""
        self._shift = 0
        self._fee = ""
        self._payNo = ""
        self.realRequestTime = 0

    @property
    def plate(self):
        return self._plate

    @plate.setter
    def plate(self,v):
        assert v,"车牌不能为空"
        self._plate = v

    @property
    def entryLane(self):
        return self._entryLane

    @entryLane.setter
    def entryLane(self,v):
        try:
            v = int(v)
        except Exception as e:
            raise TypeError(f"入口车道号转换异常:{e}")
        assert isinstance(v,int),f"入口车道号类型不正确:需要一个int值,此处获取到:{type(v)}"
        self._entryLane = v

    @property
    def exitLane(self):
        return self._exitLane
    
    @exitLane.setter
    def  exitLane(self,v):
        try:
            v = int(v)
        except Exception as e:
            raise TypeError(f"出口车道号转换异常:{e}")
        assert isinstance(v,int),f"出口车道号类型不正确:需要一个int值,此处获取到{type(v)}"
        self._exitLane = v

    
    @property
    def entryTime(self):
        return self._entryTime

    @entryTime.setter
    def  entryTime(self,v):
        '''设置入场时间'''
        assert v,"入场时间不能为空"
        assert isinstance(v,str),f"入场时间类型不正确:需要一个string值,此处获取到{type(v)}"
        self._entryTime = v

    
    @property
    def exitTime(self):
        return self._exitTime

    @exitTime.setter
    def  exitTime(self,v):
        '''设置出场时间'''
        assert v,"出场时间不能为空"
        assert isinstance(v,str),f"出场时间类型不正确:需要一个string值,此处获取到{type(v)}"
        self._exitTime = v

    @property
    def statisticDate(self):
        return self._statisticDate

    @statisticDate.setter
    def  statisticDate(self,v):
        '''设置对账统计时间'''
        assert v,"对账统计时间不能为空"
        assert isinstance(v,int),f"对账统计时间类型不正确:需要一个int值,此处获取到{type(v)}"
        self._statisticDate = v


    @property
    def shift(self):
        return self._statisticDate

    @shift.setter
    def  shift(self,v):
        '''设置班次'''
        assert v,"班次不能为空"
        assert isinstance(v,int),f"班次类型不正确:需要一个int值,此处获取到{type(v)}"
        self._shift = v
    
    @property
    def fee(self):
        return self._fee

    @fee.setter
    def fee(self,v):
        '''设置扣费金额'''
        assert v,f"扣费金额不能为空:{v}"
        assert v > 0 ,f"扣费金额不合法:{v}"
        assert isinstance(v,int),f"扣费金额类型不正确:需要一个int值,此处获取到{type(v)}"
        self._fee = v

    @property
    def payNo(self):
        return self._payNo

    @payNo.setter
    def payNo(self,v):
        '''设置订单号'''
        assert v,f"订单号不能为空:{v}"
        assert isinstance(v,str),f"订单号类型不正确:需要一个string值,此处获取到{type(v)}"
        self._payNo = v

    @property
    def plateColor(self):
        return self._plateColor

    @plateColor.setter
    def plateColor(self,v):
        '''设置车牌颜色'''
        assert str(v),f"车牌颜色不能为空:{v}"
        assert isinstance(v,int),f"车牌颜色类型不正确:需要一个int值,此处获取到{type(v)}"
        self._plateColor = v
    
    @staticmethod
    def FakedStatisticDate():
        '''
        业务场景需要伪造对账统计日期
        '''
        _date = FORMAT_TIME("%Y%m%d")
        return int(_date)

    @staticmethod
    def FakedTimeInfo():
        '''
        业务场景需要伪造入场,出场时间
        '''
        exitTime = int(time.time())
        entryTime = exitTime - random.randint(3600,14400)
        
        return  time.strftime("%Y%m%d%H%M%S",time.localtime(exitTime)),time.strftime("%Y%m%d%H%M%S",time.localtime(entryTime))

    def OtherOrderBodyToOrder(self,otherCode,orderBody):
        if otherCode == 1: #海康
            exitTime,entryTime = SwitchOrder.FakedTimeInfo()
            self._plate = orderBody["plateNo"]
            self._plateColor = orderBody["plateColor"]
            self._entryLane = 1
            self._exitLane = 2
            self._entryTime = entryTime
            self._exitTime = exitTime
            self._statisticDate = SwitchOrder.FakedStatisticDate()
            self._shift = 2
            self._fee = orderBody["arrearsFee"]
            self._payNo = orderBody["billCode"]
            self.realRequestTime = 0

        elif otherCode == 2:#冠宇
            exitTime,entryTime = SwitchOrder.FakedTimeInfo()
            self._plate = orderBody["plateNo"]
            self._plateColor = 2
            self._entryLane = 1
            self._exitLane = 2
            self._entryTime = entryTime
            self._exitTime = exitTime
            self._statisticDate = SwitchOrder.FakedStatisticDate()
            self._shift = 2
            self._fee = orderBody["amt"]
            self._payNo = orderBody["orderId"]

        elif otherCode == 3:#冠宇
            exitTime,entryTime = SwitchOrder.FakedTimeInfo()
            self._plate = orderBody["plateNum"]
            self._plateColor = 2
            self._entryLane = 1
            self._exitLane = 2
            self._entryTime = entryTime
            self._exitTime = exitTime
            self._statisticDate = SwitchOrder.FakedStatisticDate()
            self._shift = 2
            self._fee = orderBody["unPaidPrice"]
            self._payNo = orderBody["orderNum"]
        
    def format(self):
        return dict(
            plate=self._plate,
            plateColor = self._plateColor,
            entryLane = self._entryLane,
            exitLane = self._exitLane,
            entryTime = self._entryTime,
            exitTime = self._exitTime,
            statisticDate = self._statisticDate,
            shift = self._shift,
            fee = self._fee,
            payNo = self._payNo,
            realRequestTime = self.realRequestTime
        )