import re
import time
import json
from datetime import timedelta
from lib.struct import SerialNumber
from utils import FORMAT_TIME,TIME_TO_DATA


class FormatUtils(object):
    def __init__(self) -> None:
        pass

    
    @staticmethod
    def FormatParkingTime(exitTime,entryTime):
        exitDate = TIME_TO_DATA(exitTime,"%Y%m%d%H%M%S")
        entryDate = TIME_TO_DATA(entryTime,"%Y%m%d%H%M%S")
        ingBySecond = exitDate - entryDate #出场时间减去入场时间等于停车时间
        h,s,m = str(timedelta(seconds=ingBySecond)).split(':')
        ingByDate = f"{h}小时{s}分{m}秒"
        entryDateByy_m_d=FORMAT_TIME("%Y%m%d")
        return {"ingBySecond":ingBySecond,
                "ingByDate":ingByDate,
                "exitDate":exitDate,
                "entryDate":entryDate,
                "entryDateByy_m_d":entryDateByy_m_d}

    @staticmethod
    def FormatBookKeepTime(pushTime):
        timeRelated = {
            "pushDate": FORMAT_TIME("%Y-%m-%d"),
            "pushTime": pushTime,
            "pushHour": time.localtime(pushTime).tm_hour
        }
        return timeRelated
    
    @staticmethod
    def FormatAlarmParam(payNo,programStartTime):
        param = {
        "payNo":payNo,
        "pushDate":FORMAT_TIME("%Y-%m-%d %H:%M:%S"),
        "programStartTime":programStartTime}
        return param

    @staticmethod
    def LongToInt(value):
        _value = value - (2 ** 32) if value > 2147483647 else value
        return _value




class FormatManager(object):
    def __init__(self) -> None:
        self.dataContentByOBU = None
        self.dataContentByVehicle = None
        self.dataContentByCard = None
        self.transacTime = ""
        self.preBalance = 0
        self.cardSerialNo = ""
        self.terminalTradeNo = ""
        self.passtypeRand = ""


    def FormatInit(self,cache):
        self.dataContentByOBU = cache.get("dataContentByOBU")
        self.dataContentByVehicle = cache.get("dataContentByVehicle")
        self.dataContentByCard = cache.get("dataContentByCard")
        self.transacTime = cache.get("transacTime")
        self.preBalance = FormatUtils.LongToInt(int(cache.get("preBalance").hex(), base=16))  # 卡前余额
        self.cardSerialNo = cache.get("cardSN").hex()  # 2字节卡内交易序号
        self.terminalTradeNo = cache.get("termNo")
        self.passtypeRand = cache.get("passtypeRand").hex()


    def FormatTransacData(self,PARK_ID,ORDER,workKey,frameDataParam):
        parkIng = FormatUtils.FormatParkingTime(ORDER.get("exitTime"),ORDER.get("entryTime"))

        serial = SerialNumber()
        serialNum = serial.create(PARK_ID)

        parkId = PARK_ID
        vehplateNo = ORDER['plate']
        programStartTime = FORMAT_TIME("%Y-%m-%d %H:%M:%S")
        recordType = 1
        lane = int(ORDER['entryLane'])
        entryTime = parkIng["entryDate"] * 1000
        exitLane = int(ORDER['exitLane'])
        exitTime =parkIng["exitDate"] * 1000
        statisticDate = str(ORDER['statisticDate'])
        exitOperator = "a"
        exitShift = ORDER['shift']
        parkTime = parkIng["ingBySecond"]  # 停车时长
        specialInfo = 1
        receivableTotalAmount = 10
        discountAmount = 0
        actualIncomeAmount = 10
        discountInfo = ""
        payAmount = int(ORDER['fee'])  # 金额动态获取
        payMethod = 2
        paySerialNo = ORDER['payNo']
        passMethod = 2
        cardSn =self.dataContentByCard.cardNumber.hex()
        obuTransId = frameDataParam.obuMac.hex()
        obuId = self.dataContentByOBU.agrNumber.hex()  # 合同序列号
        transactionDate = FORMAT_TIME("%Y-%m-%d")
        Time = re.sub(r"(?<=\w)(?=(?:\w\w)+$)", ":", self.transacTime)
        fee = int(ORDER['fee'])   # 金额动态获取
        serviceType = 2
        transType = "09"
        terminalNo = workKey['termId']
        issuerIdentifier = self.dataContentByOBU.serviceCode.hex()
        cardNetNo = self.dataContentByCard.cardNetworkNumber.hex()  # 卡网络编号
        cardType = str(int(self.dataContentByCard.cardType.hex(), base=16))  # 卡片类型
        preBalance = self.preBalance
        postBalance = FormatUtils.LongToInt(int(frameDataParam.banlance.hex(), base=16))  # 卡后余额
        cardSerialNo = self.cardSerialNo  # 2字节卡内交易序号
        cardRandom = self.passtypeRand  # 卡内随机数
        terminalTradeNo = self.terminalTradeNo
        tac = frameDataParam.tac.hex()
        algorithmIdentifier = 1
        deviceType = 9
        entryDate = int(FORMAT_TIME("%Y%m%d"))
        exitStation = 2010203
        deviceStatus = 0

        body = {
            "programStartTime": programStartTime,
            "recordNo": serial.randint,
            "transSn": serialNum,
            "parkId": parkId,
            "recordType": recordType,
            "vehplateNo": vehplateNo,
            "vehplateColor": int(self.dataContentByVehicle.color.hex(), base=16),
            "vehType": int(self.dataContentByVehicle.type.hex(), base=16),
            "lane": lane,
            "entryTime": entryTime,
            "exitLane": exitLane,
            "exitTime": exitTime,
            "statisticDate": statisticDate,
            "exitOperator": exitOperator,
            "exitShift": exitShift,
            "parkTime": parkTime,
            "specialInfo": specialInfo,
            "seceivableTotalAmount": receivableTotalAmount,
            "discountAmount": discountAmount,
            "actualIncomeAmount": actualIncomeAmount,
            "discountInfo": "",
            "payAmount": payAmount,
            "payMethod": payMethod,
            "paySerialNo": paySerialNo,
            "passMethod": passMethod,
            "cardSn": f"{cardNetNo}{cardSn}",  # 完整卡号 4 + 16
            "obuTransId": obuTransId,
            "obuId": obuId,
            "transactionDate": transactionDate,
            "time": Time,
            "fee": fee,
            "serviceType": serviceType,
            "transType": transType,
            "terminalNo": terminalNo,
            "issuerIdentifier": issuerIdentifier,
            "cardNetNo": cardNetNo,
            "cardType": cardType,
            "preBalance": preBalance,
            "postBalance": postBalance,
            "cardSerialNo": cardSerialNo,
            "cardRandom": cardRandom,
            "terminalTradeNo": terminalTradeNo,
            "TAC": tac,
            "algorithmIdentifier": algorithmIdentifier,
            "deviceType": deviceType,
            "deviceNo": "__",
            "EntryDate": parkIng["entryDateByy_m_d"],
            "ExitStation": exitStation,
            "DeviceStatus": deviceStatus,
            "parkTimeStr": parkIng["ingByDate"],
            "ProgramVer": "1, 0, 0, 1",
        }
        return body
    

class FormatLocalDataManager(object):
    def __init__(self) -> None:
        pass

    def FormatInit(self,order,devNumber,parkId):
        self.devNumber = devNumber
        self.parkId = parkId
        self.order = order

        self.timeRelated = FormatUtils.FormatBookKeepTime(int(time.time()))

    def FormatQueueData(self,transacBody):
        data = {
        "pay_no": self.order["payNo"],
        "transac_no": transacBody["transSn"],
        "json_str": bytes(json.dumps(transacBody), encoding='gbk').hex(),
        }

        return data

    def FormatQueueErrData(self,transacBody):
        _t = int(time.time())
        body = {
                "item":dict(payNo=self.order["payNo"],
                transNumber=transacBody["transSn"],
                insertDate=FORMAT_TIME("%Y-%m-%d"),
                insertTime=_t,
                insertHour=time.localtime(_t).tm_hour,
                isUpload=0,
                isDelete=0,
                devNumber=self.devNumber),
                "content":transacBody
            }
        return body


    def FormatSummaryData(self,transNumber,parkId):
        requestTime = self.order.get("requestTime",int(time.time()))
        realRequestTime = self.order["realRequestTime"]
        summary = dict(
            payNo=self.order["payNo"],
            transNumber=transNumber,
            insertdate=self.timeRelated["pushDate"],
            insertTime=self.timeRelated["pushTime"],
            inserthour=self.timeRelated["pushHour"],
            isUpload=0,
            isDelete=0,
            serviceId = parkId,
            requestTime = requestTime,
            realRequestTime = realRequestTime,
            devNumber=self.devNumber)
        return summary

    def FormatContentData(self,transacNo,enqueueStatus):
        '''
        2022-09-26
        取消vehicle字段,改为plate
        取消payInfo,不再上传关于OBU内部信息
        '''
        content = {
            "payNo":self.order['payNo'],
            "transNumber":transacNo,
            "fee":self.order['fee'],
            "plate":self.order['plate'],
            "serviceId":self.parkId,
            "devNumber":self.devNumber,
            "hour":self.timeRelated["pushHour"],
            "enqueueStatus":enqueueStatus,
            "shift":2,
            "uploadTime":int(time.time()),
            "uploadDate":FORMAT_TIME("%Y-%m-%d")
        }
        return content