
import { ReqChargingApiData, DeductionResponse } from "./ChargingDeduction"
import { AppService, TyExternalApiClient, axiosInstance, ApiResponse, throwIfResCodeNoSuccess } from "../refs/nslib"
import { ChargingBusDeal } from "./ChargingBusDeal"
import { logger } from "mslib";
/**
 * 抵扣方式判断和抵扣处理
 * @date 2022-08-16 13:56:23
 * @author 侯洪莉
 */
class ChargingApi {

    /**
     * 抵扣方式限制判断
     * @param {*}  ReqChargingApiData 
     * @tyConfig {*}  tyConfig 车场配置文件
     * @返回值 resData：{PileRule,FreeData} PileRule：使用规则 FreeData:可免费金额和时长
     */
    async getChargingLimit(param: ReqChargingApiData, tyConfig): Promise<DeductionResponse> {
        let resData = {}
        const { plateNo, parkId, pileId, startTime, endTime, chargingTime } = param
        // 获取停车信息
        const carplateDataRst = await new TyExternalApiClient().getParkingPaymentInfo({ parkId: parkId, plateNo: plateNo });
        if (carplateDataRst.resCode != '0') {
            // 获取停车信息失败
            return await DeductionResponse.failWithMsg(carplateDataRst.resMsg);
        }

        const { entryTime, elapsedTime, payable, } = carplateDataRst.data;

        const parkCarInfo = {
            inTime: entryTime,  // 入场时间
            parkTime: elapsedTime * 60, // 停车时长 （秒）
            payMoney: payable, // 待支付金额（分）
        }

        //获取全局配置规则
        const configRule = await new ChargingBusDeal().getPileConfig(parkId)
        let timeCanUse_c = Infinity //全局限制判断本次可用抵扣时间
        let moneyCanUse_c = Infinity //全局限制判断本次可用抵扣金额 默认不限制全局
        //存在全局配置 判断全局配置的抵扣限制
        if (configRule) {
            let { timeCanUse, moneyCanUse } = await new ChargingBusDeal().getConfigRuleLimit(param, configRule, parkCarInfo)
            if (timeCanUse === 0 || moneyCanUse === 0) {
                return await DeductionResponse.failWithMsg("全局限制未通过，无法抵扣")
            }
            timeCanUse_c = timeCanUse
            moneyCanUse_c = moneyCanUse
        }

        logger.info(`全局配置限制本次可使用 timeCanUse_c-----:${timeCanUse_c},moneyCanUse_c:${moneyCanUse_c}`)


        // 获取某充电桩品牌的使用规则配置
        const pileRule = await new ChargingBusDeal().getPileRule(parkId, pileId);
        if (!pileRule) {
            return await DeductionResponse.failWithMsg(`未配置或未启用该充电桩-${pileId}-使用规则`);
        }
        // let chargingTime = dayjs(endTime).diff(startTime, 'm')
        if (pileRule.chargeTime != 0 && chargingTime < pileRule.chargeTime) {
            return await DeductionResponse.failWithMsg("充电时长未达到最小充电时长要求");
        }
        //抵扣来源为第三方
        if (pileRule.discountSource == 1) {
            if ((!param?.discountNumber && param?.discountNumber != 0) || (!param?.discountType && param?.discountType != 0)) {
                return await DeductionResponse.failRes("当抵扣来源为第三方时，抵扣类型和抵扣数量为必填值", param);
            }
            pileRule.discountNumber = param.discountNumber
            pileRule.discountType = param.discountType
        }
        //返回参数添加当前抵扣规则
        Object.assign(resData, {
            PileRule: pileRule
        })

        //判断该充电桩使用规则的限制
        let { timeCanUse: timeCanUse_p, moneyCanUse: moneyCanUse_p } = await new ChargingBusDeal().getPileRuleLimit(param, pileRule, parkCarInfo)
        logger.info(`使用规则限制本次可使用 timeCanUse_p-----:${timeCanUse_p}秒,moneyCanUse_p:${moneyCanUse_p}分`)



        let timeCanUse, moneyCanUse //本次抵扣可使用时间和金额

        //Number.isFinite(Infinity);  => false 当全局和单个使用规则都不限制时 赋值Infinity 无限大不能相减
        if (!Number.isFinite(timeCanUse_p) && !Number.isFinite(timeCanUse_c)) {
            timeCanUse = Infinity
        }
        else {
            timeCanUse = timeCanUse_c - timeCanUse_p >= 0 ? timeCanUse_p : timeCanUse_c //全局可使用和单个可使用 取最小
        }
        if (!Number.isFinite(moneyCanUse_p) && !Number.isFinite(moneyCanUse_c)) {
            moneyCanUse = Infinity
        }
        else {
            moneyCanUse = moneyCanUse_c - moneyCanUse_p >= 0 ? moneyCanUse_p : moneyCanUse_c
        }
        logger.info(`本次可使用 timeCanUse-----:${timeCanUse}秒,moneyCanUse:${moneyCanUse}分`)


        //抵扣时间
        if (pileRule.discountType === 0 && timeCanUse > 0) {
            let time = pileRule.discountMethod === 0 ? pileRule.discountNumber : chargingTime
            let freeTime
            if (pileRule.discountMethod === 0) {
                freeTime = timeCanUse - time >= 0 ? time : 0

            } else {
                freeTime = timeCanUse - time >= 0 ? time : timeCanUse
            }
            if (freeTime <= 0) {
                return await DeductionResponse.failRes(`抵扣失败，配置的可抵扣值${time}秒>本次可使用值${timeCanUse}秒`, resData);
            }
            Object.assign(resData, {
                FreeData: {
                    freeTime: freeTime, //单位秒
                    freeMoney: 0 //单位分
                }
            })
            return await DeductionResponse.successRes(`可抵扣时间${freeTime}秒`, resData);
        }

        //抵扣金额
        if (pileRule.discountType === 1 && moneyCanUse > 0) {
            let money = moneyCanUse >= pileRule.discountNumber ? pileRule.discountNumber : 0
            if (money <= 0) {
                return await DeductionResponse.failRes(`抵扣失败，配置的可抵扣值${pileRule.discountNumber}分>本次可使用值${moneyCanUse}分`, resData);
            }
            Object.assign(resData, {
                FreeData: {
                    freeTime: 0, //单位秒
                    freeMoney: money //单位分
                }
            })
            return await DeductionResponse.successRes(`可抵扣时间${money}分`, resData);
        }
        Object.assign(resData, {
            timeCanUse: timeCanUse,
            moneyCanUse: moneyCanUse
        })

        return await DeductionResponse.failRes(`抵扣失败`, resData);

    }


    /**
     * 车辆类型修改和 充电桩抵扣
     * @param {Object} param  ReqChargingApiData
     * @param {FreeData,PileRule} freeData 可抵扣信息
     * @param {Object} tyConfig 配置信息
     */
    async discount(param, discountData, tyConfig) {
        let { FreeData, PileRule } = discountData
        try {
            //若执行特殊计费规则 修改车牌
            if (PileRule.isSpecialFeeRule == 1) {
                let modifyData = {
                    parkId: param.parkId,
                    plateNo: param.plateNo,
                    carStyle: PileRule.carStyle,
                }

                let modifyRes = await new TyExternalApiClient().modifyCarInfo(modifyData)
                if (modifyRes.data.resCode != 0) {
                    return await DeductionResponse.failRes(`车辆类型修改失败--${modifyRes.resMsg}`, { param, discountData });

                }
            }

            //调用充电桩接口进行抵扣
            let reqData = {
                parkId: param.parkId,
                plateNo: param.plateNo,
                startTime: param.startTime,  //充电开始时间
                endTime: param.endTime, //充电结束时间
                orderNo: param.orderNo,  //订单号
                stationId: param.stationId || '11111',
                stationName: param.stationName || 'xxxx',    //电站名称
                deviceId: param.deviceId || param.pileId,     //设备Id
                deviceName: param.deviceName || '无',  // 设备名称
                spaceNo: '无',    //车位号
                power: param.power || 0,  //充电量 单位：度，小数点后2位
                elecMoney: param.elecMoney || 0,  //电费 单位 分
                seviceMoney: param.seviceMoney || 0,   //服务费 单位：分
                totalMoney: param.totalMoney || 0, //总费用 单位：分
                freeType: 0,    // 固定为0   0或1    0：根据freemoeny、freeTime减免1：本地车场配置减免规则，根据充电时长换算，freemoney、freetime可以为0
                freeMoney: FreeData.freeMoney,
                freeTime: FreeData.freeTime
            }


            const axiosResponse = await axiosInstance.post<ApiResponse>('/api/wec/SyncChargePilePay', reqData)
            throwIfResCodeNoSuccess(axiosResponse.data)
            let discountRes = axiosResponse.data
            //抵扣成功 且规则配置执行特殊计费规则 则修改车辆类型
            if (discountRes.data.resCode == 0) {
                return await DeductionResponse.successRes(`抵扣成功`, { param, discountData });
            } else {
                return await DeductionResponse.failRes( `车辆信息修改成功，抵扣失败-${discountRes.resMsg}`, { param, discountData });
            }
        } catch (error) {
            logger.error(`抵扣异常`, error.message)
        }

    }

}

export { ChargingApi }