package com.jsowell.thirdparty.platform.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
import com.jsowell.common.enums.lianlian.StationPaymentEnum;
import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum;
import com.jsowell.common.enums.ykc.BillingTimeTypeEnum;
import com.jsowell.common.enums.ykc.OrderStatusEnum;
import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.JWTUtils;
import com.jsowell.common.util.PageUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.dto.PushRealTimeInfoDTO;
import com.jsowell.pile.dto.QueryOperatorInfoDTO;
import com.jsowell.pile.dto.QueryStationInfoDTO;
import com.jsowell.pile.service.*;
import com.jsowell.pile.thirdparty.CommonParamsDTO;
import com.jsowell.pile.thirdparty.EquipmentInfo;
import com.jsowell.pile.util.MerchantUtils;
import com.jsowell.pile.vo.SupStationStatsVO;
import com.jsowell.pile.vo.ThirdPartySecretInfoVO;
import com.jsowell.pile.vo.base.ConnectorInfoVO;
import com.jsowell.pile.vo.base.MerchantInfoVO;
import com.jsowell.pile.vo.base.ThirdPartyStationInfoVO;
import com.jsowell.pile.vo.uniapp.customer.BillingPriceVO;
import com.jsowell.pile.vo.web.PileConnectorInfoVO;
import com.jsowell.pile.vo.web.PileStationVO;
import com.jsowell.thirdparty.lianlian.domain.ConnectorChargeStatusInfo;
import com.jsowell.thirdparty.lianlian.domain.ConnectorStatusInfo;
import com.jsowell.thirdparty.lianlian.domain.StationStatusInfo;
import com.jsowell.thirdparty.lianlian.vo.AccessTokenVO;
import com.jsowell.thirdparty.platform.common.StationInfo;
import com.jsowell.thirdparty.platform.domain.*;
import com.jsowell.thirdparty.platform.service.ThirdPartyPlatformService;
import com.jsowell.thirdparty.platform.factory.ThirdPartyPlatformFactory;
import com.jsowell.thirdparty.platform.util.Cryptos;
import com.jsowell.thirdparty.platform.util.HttpRequestUtil;
import com.jsowell.thirdparty.platform.util.ThirdPartyPlatformUtils;
import com.jsowell.thirdparty.service.ThirdpartySecretInfoService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class NinaXiaPlatformServiceImpl implements ThirdPartyPlatformService {
    // 平台类型
    private final String thirdPlatformType = ThirdPlatformTypeEnum.NING_XIA_PLATFORM.getTypeCode();

    @Override
    public void afterPropertiesSet() throws Exception {
        ThirdPartyPlatformFactory.register(thirdPlatformType, this);
    }

    @Autowired
    private ThirdPartyPlatformConfigService thirdPartyPlatformConfigService;

    @Autowired
    private ThirdPartyStationRelationService thirdPartyStationRelationService;

    @Autowired
    private ThirdpartySecretInfoService thirdpartySecretInfoService;

    @Autowired
    private PileBasicInfoService pileBasicInfoService;

    @Autowired
    private PileStationInfoService pileStationInfoService;

    @Autowired
    private PileMerchantInfoService pileMerchantInfoService;

    @Autowired
    private PileConnectorInfoService pileConnectorInfoService;

    @Autowired
    private OrderBasicInfoService orderBasicInfoService;

    @Autowired
    private PileBillingTemplateService pileBillingTemplateService;

    /**
     * @return
     */
    @Override
    public void printServiceName() {
        System.out.println("当前类名：" + this.getClass().getSimpleName());
    }

    /**
     * query_token 获取token，提供给第三方平台使用
     *
     * @param dto
     * @return
     */
    @Override
    public Map<String, String> queryToken(CommonParamsDTO dto) {
        AccessTokenVO vo = new AccessTokenVO();
        // 0:成功；1:失败
        int succStat = 0;
        // 0:无；1:无此对接平台；2:密钥错误； 3～99:自定义
        int failReason = 0;

        String operatorId = dto.getOperatorID();
        // 通过operatorId 查出 operatorSecret
        ThirdPartySecretInfoVO thirdPartySecretInfoVO = thirdpartySecretInfoService.queryByOperatorId(operatorId);
        if (thirdPartySecretInfoVO == null) {
            failReason = 1;
            succStat = 1;
        } else {
            String ourOperatorSecret = thirdPartySecretInfoVO.getOurOperatorSecret();
            String dataSecret = thirdPartySecretInfoVO.getOurDataSecret();
            String dataSecretIv = thirdPartySecretInfoVO.getOurDataSecretIv();
            // 解密data 获取参数中的OperatorSecret
            String decrypt = Cryptos.decrypt(dto.getData(), dataSecret, dataSecretIv);
            String inputOperatorSecret = null;
            if (StringUtils.isNotBlank(decrypt)) {
                inputOperatorSecret = JSON.parseObject(decrypt).getString("OperatorSecret");
            }
            // 对比密钥
            if (!StringUtils.equals(ourOperatorSecret, inputOperatorSecret)) {
                failReason = 1;
                succStat = 1;
            } else {
                // 生成token
                String token = JWTUtils.createToken(operatorId, ourOperatorSecret, JWTUtils.ttlMillis);
                vo.setAccessToken(token);
                vo.setTokenAvailableTime((int) (JWTUtils.ttlMillis / 1000));
            }
        }
        // 组装返回参数
        vo.setOperatorID(operatorId);
        vo.setFailReason(failReason);
        vo.setSuccStat(succStat);

        Map<String, String> resultMap = ThirdPartyPlatformUtils.generateResultMap(vo, thirdPartySecretInfoVO);
        return resultMap;
    }

    /**
     * 查询运营商信息 query_operator_info
     * supervise_query_operator_info
     *
     * @param dto 查询运营商信息DTO
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public Map<String, String> queryOperatorInfo(QueryOperatorInfoDTO dto) {
        PageHelper.startPage(dto.getPageNo(), dto.getPageSize());
        List<MerchantInfoVO> merchantList = thirdPartyStationRelationService.selectMerchantList(thirdPlatformType);
        PageInfo<MerchantInfoVO> pageInfo = new PageInfo<>(merchantList);
        List<SupOperatorInfo> operatorInfos = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(pageInfo.getList())) {
            SupOperatorInfo supOperatorInfo;
            for (MerchantInfoVO merchantInfoVO : pageInfo.getList()) {
                supOperatorInfo = new SupOperatorInfo();
                supOperatorInfo.setOperatorID(MerchantUtils.getOperatorID(merchantInfoVO.getOrganizationCode()));
                supOperatorInfo.setOperatorUSCID(merchantInfoVO.getOrganizationCode());
                supOperatorInfo.setOperatorName(merchantInfoVO.getMerchantName());
                supOperatorInfo.setOperatorTel1(merchantInfoVO.getMerchantTel());
                supOperatorInfo.setOperatorRegAddress(merchantInfoVO.getMerchantAddress());
                operatorInfos.add(supOperatorInfo);
            }
        }
        ThirdPartySecretInfoVO thirdPartySecretInfoVO = thirdpartySecretInfoService.queryByThirdPlatformType(thirdPlatformType);

        // 组装结果集
        Map<String, Object> map = Maps.newHashMap();
        map.put("PageNo", pageInfo.getPageNum());
        map.put("PageCount", pageInfo.getPages());
        map.put("ItemSize", pageInfo.getTotal());
        map.put("OperatorInfos", operatorInfos);

        Map<String, String> resultMap = ThirdPartyPlatformUtils.generateResultMap(map, thirdPartySecretInfoVO);
        return resultMap;
    }

    /**
     * 查询充电站信息 query_stations_info
     * 此接口用于查询对接平台的充电站的信息
     *
     * @param dto 查询站点信息dto
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public Map<String, String> queryStationsInfo(QueryStationInfoDTO dto) {
        int pageNo = dto.getPageNo() == null ? 1 : dto.getPageNo();
        int pageSize = dto.getPageSize() == null ? 10 : dto.getPageSize();

        PageUtils.startPage(pageNo, pageSize);
        List<ThirdPartyStationInfoVO> stationInfos = pileStationInfoService.getStationInfosByThirdParty(dto);
        if (CollectionUtils.isEmpty(stationInfos)) {
            // 未查到数据
            return null;
        }
        // ThirdPartyPlatformConfig configInfo = thirdPartyPlatformConfigService.getInfoByOperatorId(dto.getOperatorId());
        ThirdPartySecretInfoVO thirdPartySecretInfoVO = thirdpartySecretInfoService.queryByThirdPlatformType(thirdPlatformType);
        if (thirdPartySecretInfoVO == null) {
            return null;
        }
        PageInfo<ThirdPartyStationInfoVO> pageInfo = new PageInfo<>(stationInfos);
        List<SupStationInfo> resultList = new ArrayList<>();
        for (ThirdPartyStationInfoVO pileStationInfo : pageInfo.getList()) {
            SupStationInfo stationInfo = new SupStationInfo();
            String stationId = String.valueOf(pileStationInfo.getId());
            stationInfo.setStationID(stationId);
            // MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(String.valueOf(pileStationInfo.getMerchantId()));
            stationInfo.setOperatorID(Constants.OPERATORID_LIANLIAN); // 组织机构代码
            stationInfo.setEquipmentOwnerID(String.valueOf(pileStationInfo.getMerchantId()));
            stationInfo.setStationName(pileStationInfo.getStationName());
            stationInfo.setIsAloneApply(Integer.valueOf(pileStationInfo.getAloneApply()));
            stationInfo.setIsPublicParkingLot(Integer.valueOf(pileStationInfo.getPublicParking()));
            stationInfo.setCountryCode(pileStationInfo.getCountryCode());
            stationInfo.setAreaCode(pileStationInfo.getAreaCode());
            stationInfo.setAddress(pileStationInfo.getAddress());
            stationInfo.setServiceTel(pileStationInfo.getStationTel());
            stationInfo.setStationType(Integer.valueOf(pileStationInfo.getStationType()));
            stationInfo.setParkNums(Integer.valueOf(pileStationInfo.getParkNums()));
            stationInfo.setStationLng(new BigDecimal(pileStationInfo.getStationLng()));
            stationInfo.setStationLat(new BigDecimal(pileStationInfo.getStationLat()));
            stationInfo.setConstruction(Integer.valueOf(pileStationInfo.getConstruction()));
            stationInfo.setOpenAllDay(Integer.valueOf(pileStationInfo.getOpenAllDay()));
            // stationInfo.setMinElectricityPrice(pileStationInfo); // 最低充电电费率
            // stationInfo.setElectricityFee(); // 电费 xx元/度
            // stationInfo.setServiceFee(); // 服务费 xx元/度
            stationInfo.setParkFree(Integer.valueOf(pileStationInfo.getParkFree()));
            stationInfo.setPayment(pileStationInfo.getPayment());
            stationInfo.setSupportOrder(Integer.valueOf(pileStationInfo.getSupportOrder()));
            // stationInfo.setParkFeeType(pileStationInfo); // 停车收费类型
            stationInfo.setToiletFlag(Integer.valueOf(pileStationInfo.getToiletFlag()));
            stationInfo.setStoreFlag(Integer.valueOf(pileStationInfo.getStoreFlag()));
            stationInfo.setRestaurantFlag(Integer.valueOf(pileStationInfo.getRestaurantFlag()));
            stationInfo.setLoungeFlag(Integer.valueOf(pileStationInfo.getLoungeFlag()));
            stationInfo.setCanopyFlag(Integer.valueOf(pileStationInfo.getCanopyFlag()));
            stationInfo.setPrinterFlag(Integer.valueOf(pileStationInfo.getPrinterFlag()));
            stationInfo.setBarrierFlag(Integer.valueOf(pileStationInfo.getBarrierFlag()));
            stationInfo.setParkingLockFlag(Integer.valueOf(pileStationInfo.getParkingLockFlag()));
            List<EquipmentInfo> pileList = pileBasicInfoService.getPileListForLianLian(stationId);
            if (CollectionUtils.isNotEmpty(pileList)) {
                stationInfo.setEquipmentInfos(pileList); // 充电设备信息列表
            }
            resultList.add(stationInfo);
        }
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("PageNo", pageInfo.getPageNum());
        map.put("PageCount", pageInfo.getPages());
        map.put("ItemSize", pageInfo.getTotal());
        map.put("StationInfos", resultList);
        Map<String, String> resultMap = ThirdPartyPlatformUtils.generateResultMap(map, thirdPartySecretInfoVO);
        return resultMap;
    }

    /**
     * 设备接口状态查询 query_station_status
     *
     * @param dto 查询站点信息dto
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public Map<String, String> queryStationStatus(QueryStationInfoDTO dto) {
        List<String> stationIds = dto.getStationIds();
        List<StationStatusInfo> StationStatusInfos = new ArrayList<>();
        List<Object> connectorStatusInfos = new ArrayList<>();
        // ThirdPartyPlatformConfig configInfo = thirdPartyPlatformConfigService.getInfoByOperatorId(dto.getOperatorId());
        ThirdPartySecretInfoVO thirdPartySecretInfoVO = thirdpartySecretInfoService.queryByThirdPlatformType(thirdPlatformType);
        if (thirdPartySecretInfoVO == null) {
            return null;
        }
        ConnectorStatusInfo connectorStatusInfo;
        for (String stationId : stationIds) {
            StationStatusInfo stationStatusInfo = new StationStatusInfo();
            stationStatusInfo.setStationId(stationId);
            // 根据站点id查询
            List<ConnectorInfoVO> list = pileConnectorInfoService.getConnectorListForLianLian(Long.parseLong(stationId));
            for (ConnectorInfoVO connectorInfoVO : list) {

                String connectorStatus = connectorInfoVO.getConnectorStatus();
                if (StringUtils.equals(connectorStatus, PileConnectorDataBaseStatusEnum.OCCUPIED_CHARGING.getValue())) {
                    // 充电中
                    ConnectorChargeStatusInfo info = new ConnectorChargeStatusInfo();
                    OrderBasicInfo orderBasicInfo = orderBasicInfoService.queryChargingByPileConnectorCode(connectorInfoVO.getPileConnectorCode());
                    if (orderBasicInfo == null) {
                        continue;
                    }
                    List<RealTimeMonitorData> chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderBasicInfo.getTransactionCode());
                    if (CollectionUtils.isNotEmpty(chargingRealTimeData)) {
                        RealTimeMonitorData realTimeMonitorData = chargingRealTimeData.get(0);
                        info.setStartChargeSeq(orderBasicInfo.getOrderCode());
                        info.setConnectorID(orderBasicInfo.getPileConnectorCode());
                        info.setConnectorStatus(Integer.valueOf(connectorInfoVO.getConnectorStatus()));
                        info.setCurrentA(new BigDecimal(realTimeMonitorData.getOutputCurrent()));
                        info.setVoltageA(new BigDecimal(realTimeMonitorData.getOutputVoltage()));
                        info.setSoc(new BigDecimal(realTimeMonitorData.getSOC()));
                        info.setStartTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderBasicInfo.getChargeStartTime()));
                        info.setEndTime(DateUtils.getDateTime()); // 本次采样时间
                        info.setTotalPower(new BigDecimal(realTimeMonitorData.getChargingDegree())); // 累计充电量
                        // info.setElecMoney(); // 累计电费
                        // info.setSeviceMoney(); // 累计服务费
                        info.setTotalMoney(new BigDecimal(realTimeMonitorData.getChargingAmount()));
                        connectorStatusInfos.add(info);
                    }
                } else {
                    // 其他
                    connectorStatusInfo = new ConnectorStatusInfo();
                    connectorStatusInfo.setConnectorID(connectorInfoVO.getPileConnectorCode());
                    connectorStatusInfo.setStatus(Integer.parseInt(connectorInfoVO.getConnectorStatus()));
                    connectorStatusInfos.add(connectorStatusInfo);
                }
            }
            stationStatusInfo.setConnectorStatusInfos(connectorStatusInfos);
            StationStatusInfos.add(stationStatusInfo);
        }
        // 将 StationStatusInfos 分页
        int pageNum = 1;
        int pageSize = 10;
        List<StationStatusInfo> collect = StationStatusInfos.stream()
                .skip((pageNum - 1) * pageSize)
                .limit(pageSize)
                .collect(Collectors.toList());

        // int total = StationStatusInfos.size();
        // int pages = PageUtil.totalPage(total, pageSize);

        Map<String, Object> map = new LinkedHashMap<>();
        // map.put("Total", total);
        map.put("StationStatusInfos", collect);

        Map<String, String> resultMap = ThirdPartyPlatformUtils.generateResultMap(map, thirdPartySecretInfoVO);
        return resultMap;
    }

    /**
     * 设备状态变化推送  notification_stationStatus
     * 推送充电设备接口状态信息 supervise_notification_station_status
     *
     * @param dto
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public String notificationStationStatus(PushRealTimeInfoDTO dto) {
        String pileConnectorCode = dto.getPileConnectorCode();
        String status = dto.getStatus();
        ThirdPartySecretInfoVO xiaPlatformSecretInfo = getNingXiaPlatformSecretInfo();
        // 查询充电枪口状态
        PileConnectorInfoVO connectorInfo = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorCode);
        if (Objects.isNull(connectorInfo)) {
            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
        }

        String merchantId = connectorInfo.getMerchantId();
        MerchantInfoVO merchantInfoVO = pileMerchantInfoService.getMerchantInfoVO(merchantId);
        if (Objects.isNull(merchantInfoVO)) {
            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
        }

        SupConnectorStatusInfo info = SupConnectorStatusInfo.builder()
                .operatorID(Constants.JSOWELL_OPERATORID)
                .equipmentOwnerID(MerchantUtils.getOperatorID(merchantInfoVO.getOrganizationCode()))
                .stationID(connectorInfo.getStationId())
                .equipmentID(connectorInfo.getPileSn())
                .connectorID(pileConnectorCode)
                .equipmentClassification(Constants.ONE)
                .status(Integer.parseInt(status))
                .statusDesc(PileConnectorDataBaseStatusEnum.getStatusDescription(status))
                .parkStatus(Constants.ZERO)
                .lockStatus(Constants.ZERO)
                .batteryStatus(Constants.ZERO)
                .batteryPackID("")
                .lastChangeTime(DateUtils.getDateTime())
                .build();

        // 调用联联平台接口
        String operatorId = xiaPlatformSecretInfo.getOurOperatorId();
        String operatorSecret = xiaPlatformSecretInfo.getTheirOperatorSecret();
        String signSecret = xiaPlatformSecretInfo.getTheirSigSecret();
        String dataSecret = xiaPlatformSecretInfo.getTheirDataSecret();
        String dataSecretIv = xiaPlatformSecretInfo.getTheirDataSecretIv();
        String urlAddress = xiaPlatformSecretInfo.getTheirUrlPrefix();
        String url = urlAddress + "supervise_notification_station_status";

        // JSONObject json = new JSONObject();
        // json.put("ConnectorStatusInfo", info);
        String jsonString = JSON.toJSONString(info);
        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;
    }

    @Override
    public String notificationStationStatus(String stationId, String pileConnectorCode, String status, ThirdPartySecretInfoVO secretInfoVO) {
        // 查询充电枪口状态
        PileConnectorInfoVO connectorInfo = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorCode);
        if (Objects.isNull(connectorInfo)) {
            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
        }

        String merchantId = connectorInfo.getMerchantId();
        MerchantInfoVO merchantInfoVO = pileMerchantInfoService.getMerchantInfoVO(merchantId);
        if (Objects.isNull(merchantInfoVO)) {
            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
        }

        SupConnectorStatusInfo info = SupConnectorStatusInfo.builder()
                .operatorID(Constants.JSOWELL_OPERATORID)
                .equipmentOwnerID(MerchantUtils.getOperatorID(merchantInfoVO.getOrganizationCode()))
                .stationID(connectorInfo.getStationId())
                .equipmentID(connectorInfo.getPileSn())
                .connectorID(pileConnectorCode)
                .equipmentClassification(Constants.ONE)
                .status(Integer.parseInt(status))
                .statusDesc(PileConnectorDataBaseStatusEnum.getStatusDescription(status))
                .parkStatus(Constants.ZERO)
                .lockStatus(Constants.ZERO)
                .batteryStatus(Constants.ZERO)
                .batteryPackID("")
                .lastChangeTime(DateUtils.getDateTime())
                .build();

        // 调用联联平台接口
        String operatorId = secretInfoVO.getOurOperatorId();
        String operatorSecret = secretInfoVO.getTheirOperatorSecret();
        String signSecret = secretInfoVO.getTheirSigSecret();
        String dataSecret = secretInfoVO.getTheirDataSecret();
        String dataSecretIv = secretInfoVO.getTheirDataSecretIv();
        String urlAddress = secretInfoVO.getTheirUrlPrefix();
        String url = urlAddress + "supervise_notification_station_status";

        // JSONObject json = new JSONObject();
        // json.put("ConnectorStatusInfo", info);
        String jsonString = JSON.toJSONString(info);
        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;
    }

    /**
     * 充电订单推送 notification_charge_order_info
     *
     * @param orderCode 订单编号
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public String notificationChargeOrderInfo(String orderCode) {
        // 根据订单号查询出信息
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        if (orderBasicInfo == null) {
            return null;
        }

        ThirdPartySecretInfoVO ningXiaSecretInfo = getNingXiaPlatformSecretInfo();

        String operatorId = ningXiaSecretInfo.getOurOperatorId();
        String operatorSecret = ningXiaSecretInfo.getTheirOperatorSecret();
        String signSecret = ningXiaSecretInfo.getTheirSigSecret();
        String dataSecret = ningXiaSecretInfo.getTheirDataSecret();
        String dataSecretIv = ningXiaSecretInfo.getTheirDataSecretIv();
        String urlAddress = ningXiaSecretInfo.getTheirUrlPrefix();

        // 根据订单号查询订单详情
        OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode);
        if (orderDetail == null) {
            return null;
        }

        // 推送地址
        String url = urlAddress + "supervise_notification_charge_order_info";

        // 拼装成内蒙古平台所需格式对象
        ChargeOrderInfo orderInfo = transformChargeOrderInfo(orderBasicInfo, orderDetail);
        orderInfo.setOperatorID(operatorId);
        String equipmentOwnerID;
        if (MerchantUtils.isXiXiaoMerchant(orderBasicInfo.getMerchantId())) {
            equipmentOwnerID = Constants.OPERATORID_XI_XIAO;
        } else {
            equipmentOwnerID = Constants.OPERATORID_LIANLIAN;
        }
        orderInfo.setEquipmentOwnerID(equipmentOwnerID);

        List<BillingPriceVO> billingList = pileBillingTemplateService.queryBillingPrice(orderBasicInfo.getStationId());
        // 先将list按照 尖、峰、平、谷 时段排序
        // List<BillingPriceVO> collect = billingList.stream().sorted(Comparator.comparing(BillingPriceVO::getTimeType)).collect(Collectors.toList());
        // 再循环该list，拼装对应的充电价格、费率
        List<SupChargeDetails> chargeDetails = transformSupChargeDetails(orderDetail, billingList);
        orderInfo.setChargeDetails(chargeDetails);

        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        if (StringUtils.isBlank(token)) {
            return null;
        }
        // 调用联联平台接口
        JSONObject json = new JSONObject();
        json.put("ChargeOrderInfo", orderInfo);
        String jsonString = JSON.toJSONString(json);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;
    }

    @Override
    public String notificationChargeOrderInfo(String orderCode, ThirdPartySecretInfoVO secretInfoVO) {
        // 根据订单号查询出信息
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        if (orderBasicInfo == null) {
            return null;
        }

        // 通过站点id查询相关配置信息
        // ThirdPartyStationRelationVO relationInfo = thirdPartyStationRelationService.selectRelationInfo(orderBasicInfo.getStationId());
        // if (relationInfo == null) {
        //     return null;
        // }

        String operatorId = secretInfoVO.getOurOperatorId();
        String operatorSecret = secretInfoVO.getTheirOperatorSecret();
        String signSecret = secretInfoVO.getTheirSigSecret();
        String dataSecret = secretInfoVO.getTheirDataSecret();
        String dataSecretIv = secretInfoVO.getTheirDataSecretIv();
        String urlAddress = secretInfoVO.getTheirUrlPrefix();

        // 根据订单号查询订单详情
        OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode);
        if (orderDetail == null) {
            return null;
        }

        // 推送地址
        String url = urlAddress + "notification_orderInfo";

        // 拼装成宁夏平台所需格式对象
        ChargeOrderInfo orderInfo = transformChargeOrderInfo(orderBasicInfo, orderDetail);
        orderInfo.setOperatorID(operatorId);
        String equipmentOwnerID;
        if (MerchantUtils.isXiXiaoMerchant(orderBasicInfo.getMerchantId())) {
            equipmentOwnerID = Constants.OPERATORID_XI_XIAO;
        } else {
            equipmentOwnerID = Constants.OPERATORID_LIANLIAN;
        }
        orderInfo.setEquipmentOwnerID(equipmentOwnerID);

        List<BillingPriceVO> billingList = pileBillingTemplateService.queryBillingPrice(orderBasicInfo.getStationId());
        // 先将list按照 尖、峰、平、谷 时段排序
        // List<BillingPriceVO> collect = billingList.stream().sorted(Comparator.comparing(BillingPriceVO::getTimeType)).collect(Collectors.toList());
        // 再循环该list，拼装对应的充电价格、费率
        List<SupChargeDetails> chargeDetails = transformSupChargeDetails(orderDetail, billingList);
        orderInfo.setChargeDetails(chargeDetails);

        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        if (StringUtils.isBlank(token)) {
            return null;
        }
        // 调用联联平台接口
        JSONObject json = new JSONObject();
        json.put("ChargeOrderInfo", orderInfo);
        String jsonString = JSON.toJSONString(json);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;
    }

    /**
     * 推送充电状态 notification_equip_charge_status
     * 推送充电状态信息 supervise_notification_equip_charge_status
     *
     * @param orderCode 订单编号
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public String notificationEquipChargeStatus(String orderCode) {
        // 根据订单号查询订单信息
        OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        ThirdPartySecretInfoVO ningXiaSecretInfo = getNingXiaPlatformSecretInfo();

        String operatorId = ningXiaSecretInfo.getOurOperatorId();
        String operatorSecret = ningXiaSecretInfo.getTheirOperatorSecret();
        String signSecret = ningXiaSecretInfo.getTheirSigSecret();
        String dataSecret = ningXiaSecretInfo.getTheirDataSecret();
        String dataSecretIv = ningXiaSecretInfo.getTheirDataSecretIv();
        String urlAddress = ningXiaSecretInfo.getTheirUrlPrefix();

        // 查询充电枪口状态
        PileConnectorInfoVO connectorInfo = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(orderInfo.getPileConnectorCode());
        if (Objects.isNull(connectorInfo)) {
            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
        }

        String merchantId = connectorInfo.getMerchantId();
        MerchantInfoVO merchantInfoVO = pileMerchantInfoService.getMerchantInfoVO(merchantId);
        if (Objects.isNull(merchantInfoVO)) {
            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
        }
        String orderStatus = orderInfo.getOrderStatus();
        if (StringUtils.equals(OrderStatusEnum.IN_THE_CHARGING.getValue(), orderStatus)) {
            // 充电中
            orderStatus = "2";
        }else if (StringUtils.equals(OrderStatusEnum.ORDER_COMPLETE.getValue(), orderStatus)) {
            // 充电完成
            orderStatus = "4";
        }
        String dateTimeNow = DateUtils.getDateTime();

        SupEquipChargeStatusInfo supEquipChargeStatusInfo = SupEquipChargeStatusInfo.builder()
                .operatorID(Constants.JSOWELL_OPERATORID)
                .equipmentOwnerID(MerchantUtils.getOperatorID(merchantInfoVO.getOrganizationCode()))
                .stationID(orderInfo.getStationId())
                .equipmentID(orderInfo.getPileSn())
                .orderNo(orderCode)
                .orderStatus(Integer.parseInt(orderStatus))
                .connectorID(orderInfo.getPileConnectorCode())
                .equipmentClassification(1)
                .pushTimeStamp(dateTimeNow)
                .connectorStatus(connectorInfo.getStatus())
                .currentA(connectorInfo.getCurrent())
                .soc(new BigDecimal(Constants.ZERO))
                .startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderInfo.getChargeStartTime()))
                .endTime(dateTimeNow)
                .totalPower(connectorInfo.getInstantPower())

                .build();
        if (StringUtils.isNotBlank(connectorInfo.getSOC())) {
            supEquipChargeStatusInfo.setSoc(new BigDecimal(connectorInfo.getSOC()));
        }


        String url = urlAddress + "supervise_notification_equip_charge_status";
        // 调用联联平台接口
        String jsonString = JSON.toJSONString(supEquipChargeStatusInfo);

        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;
    }

    /**
     * 推送充换电站用能统计信息 supervise_notification_operation_stats_info
     *
     * @param stationId
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public String notificationOperationStatsInfo(String stationId) {
        SupStationStatsInfo.
                EquipmentStatsInfo equipmentStatsInfo = new SupStationStatsInfo.EquipmentStatsInfo();
        List<SupStationStatsInfo.
                EquipmentStatsInfo> equipmentStatsInfoList = new ArrayList<>();

        SupStationStatsInfo.
                EquipmentStatsInfo.
                ConnectorStatsInfo connectorStatsInfo = null;
        List<SupStationStatsInfo.
                EquipmentStatsInfo.
                ConnectorStatsInfo> connectorStatsInfoList = new ArrayList<>();

        // 根据站点id查询订单记录 (新建Service方法)
        List<SupStationStatsVO> orderVOS = orderBasicInfoService.queryOrderListByStationId(stationId);
        // 根据订单信息汇总出站点充电数据
        BigDecimal stationTotalElectricity = BigDecimal.ZERO; // 充电站累计用电量
        int stationChargeTime = Constants.zero; // 充电站累计充电次数
        for (SupStationStatsVO orderVO : orderVOS) {
            // 充电站累计用电量
            BigDecimal totalPower = orderVO.getTotalPower();
            if (totalPower == null || orderVO.getChargingTime() == null) {
                continue;
            }
            stationTotalElectricity = stationTotalElectricity.add(totalPower);
            // 充电站累计充电时长(分钟)
            stationChargeTime += orderVO.getChargingTime();
        }

        // 根据枪口排序，分组，将充电时长和充电量累加
        Map<String, SupStationStatsVO> collect = orderVOS.stream()
                .sorted(Comparator.comparing(SupStationStatsVO::getPileConnectorCode))
                .filter(vo -> vo.getChargingTime() != null && vo.getTotalPower() != null)
                .collect(Collectors.toMap(SupStationStatsVO::getPileConnectorCode, Function.identity(),
                (a, b) -> {
                    a.setChargingTime(a.getChargingTime() + b.getChargingTime());
                    a.setTotalPower(a.getTotalPower().add(b.getTotalPower()));
                    return a;
                }));
        TreeMap<String, SupStationStatsVO> sortedMap = new TreeMap<>(collect);

        // 初始化相关数据
        String pileSn = "";
        BigDecimal pileTotalPower = BigDecimal.ZERO;
        int pileChargeTime = Constants.zero;
        // key : pileConnectorCode
        // value: SupStationStatsVO
        for (Map.Entry<String, SupStationStatsVO> entry: sortedMap.entrySet()) {

            String pileConnectorCode = entry.getKey();
            SupStationStatsVO vo = entry.getValue();

            connectorStatsInfo = new SupStationStatsInfo.EquipmentStatsInfo.ConnectorStatsInfo();

            // 先封装枪口数据
            connectorStatsInfo.setConnectorId(pileConnectorCode);

            connectorStatsInfo.setEquipmentClassification(1);
            connectorStatsInfo.setConnectorElectricity(vo.getTotalPower());
            connectorStatsInfo.setConnectorTotalChargeTime(vo.getChargingTime());
            // TODO connectorStatsInfo.setConnectorTotalChargeNum();
            connectorStatsInfo.setConnectorTotalWarningNum(0);

            // 对比这次循环到的桩编号和上次的桩编号，如果是同一台桩，将数据进行汇总，如果不是，新建桩数据，并将之前的累计数据清0
            String newPileSn = vo.getPileSn();
            if (!StringUtils.equals(pileSn, newPileSn)) {
                pileSn = newPileSn;
                pileTotalPower = BigDecimal.ZERO;
                pileChargeTime = Constants.zero;

                equipmentStatsInfo = new SupStationStatsInfo.EquipmentStatsInfo();
                connectorStatsInfoList = new ArrayList<>();

                equipmentStatsInfo.setEquipmentId(pileSn);
                equipmentStatsInfo.setEquipmentClassification(1);
                equipmentStatsInfo.setEquipmentElectricity(vo.getTotalPower());
                equipmentStatsInfo.setEquipmentTotalChargeTime(vo.getChargingTime());
                // TODO equipmentStatsInfo.setEquipmentTotalChargeNum();

                pileTotalPower = pileTotalPower.add(vo.getTotalPower());
                pileChargeTime += vo.getChargingTime();

                connectorStatsInfoList.add(connectorStatsInfo);
                equipmentStatsInfo.setConnectorStatsInfos(connectorStatsInfoList);
                equipmentStatsInfoList.add(equipmentStatsInfo);
            }else {
                // 同一台桩，枪口号不同，累加桩数据，将枪口数据新建

                pileTotalPower = pileTotalPower.add(vo.getTotalPower());
                pileChargeTime += vo.getChargingTime();

                equipmentStatsInfo.setEquipmentElectricity(pileTotalPower); // 第一次判断时一定不会进入到这里，所以不用判断 equipmentStatsInfo 是否为 null
                equipmentStatsInfo.setEquipmentTotalChargeTime(pileChargeTime);

                connectorStatsInfoList.add(connectorStatsInfo);
                equipmentStatsInfo.setConnectorStatsInfos(connectorStatsInfoList);
                equipmentStatsInfoList.add(equipmentStatsInfo);
            }

        }

        // 创建对象
        String startTime = DateUtils.getYesterdayStr() + " 00:00:00";
        String endTime = DateUtils.getYesterdayStr() + " 23:59:59";
        SupStationStatsInfo supStationStatsInfo = SupStationStatsInfo.builder()
                .stationId(stationId)
                .operatorId(Constants.OPERATORID_JIANG_SU)
                // .equipmentOwnerId(orderVOS.get(0).getOrganizationCode())
                .stationClassification(1)
                .startTime(startTime)
                .endTime(endTime)
                .stationElectricity(stationTotalElectricity)
                .stationTotalChargeEnergy(stationTotalElectricity)
                .stationTotalChargeNum(orderVOS.size())
                .stationTotalChargeTime(stationChargeTime)
                .stationTotalWarningNum(0)
                .equipmentStatsInfos(equipmentStatsInfoList)

                .build();
        JSONObject json = new JSONObject();
        json.put("StationStatsInfos", supStationStatsInfo);
        String jsonString = JSON.toJSONString(json);
        // 发送推送请求
        ThirdPartySecretInfoVO ningXiaSecretInfo = getNingXiaPlatformSecretInfo();

        String operatorId = ningXiaSecretInfo.getOurOperatorId();
        String operatorSecret = ningXiaSecretInfo.getTheirOperatorSecret();
        String signSecret = ningXiaSecretInfo.getTheirSigSecret();
        String dataSecret = ningXiaSecretInfo.getTheirDataSecret();
        String dataSecretIv = ningXiaSecretInfo.getTheirDataSecretIv();
        String urlAddress = ningXiaSecretInfo.getTheirUrlPrefix();
        String url = urlAddress + "supervise_notification_operation_stats_info";
        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        if (StringUtils.isBlank(token)) {
            return null;
        }
        // 调用平台接口
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;

    }

    /**
     * 推送充电站实时功率
     * @param stationIds
     * @return
     */
    @Override
    public String notificationPowerInfo(List<String> stationIds) {
        List<SupStationPowerInfo> supStationPowerInfoList = new ArrayList<>();
        stationIds.forEach(stationId -> {
            PileStationVO stationInfo = pileStationInfoService.getStationInfo(stationId);
            String dateTimeNow = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS);
            SupStationPowerInfo supStationPowerInfo = new SupStationPowerInfo();
            // 根据站点id查询桩列表
            List<PileBasicInfo> pileList = pileBasicInfoService.getPileListByStationId(stationId);
            SupStationPowerInfo.
                    EquipmentPowerInfo equipmentPowerInfo = null;
            List<SupStationPowerInfo.
                    EquipmentPowerInfo> equipmentPowerInfoList = new ArrayList<>();
            BigDecimal stationInstantPower = BigDecimal.ZERO;
            supStationPowerInfo.setOperatorId(Constants.OPERATORID_LIANLIAN);
            supStationPowerInfo.setEquipmentOwnerID(stationInfo.getMerchantId());
            supStationPowerInfo.setStationId(stationId);
            supStationPowerInfo.setStationClassification(1);
            supStationPowerInfo.setDataTime(dateTimeNow);

            for (PileBasicInfo pileBasicInfo : pileList) {
                equipmentPowerInfo = new SupStationPowerInfo.EquipmentPowerInfo();
                equipmentPowerInfo.setEquipmentID(pileBasicInfo.getSn());
                equipmentPowerInfo.setEquipmentClassification(1);
                equipmentPowerInfo.setDataTime(dateTimeNow);

                // 根据桩sn查询枪口列表
                List<PileConnectorInfo> pileConnectorInfos = pileConnectorInfoService.selectPileConnectorInfoList(pileBasicInfo.getSn());
                // 如果枪口状态为充电中，则查询枪口功率等信息
                SupStationPowerInfo.
                        EquipmentPowerInfo.
                        ConnectorPowerInfo connectorPowerInfo = null;
                List<SupStationPowerInfo.
                        EquipmentPowerInfo.
                        ConnectorPowerInfo> connectorPowerInfoList = new ArrayList<>();
                // 初始化桩功率
                BigDecimal pileInstantPower = BigDecimal.ZERO;
                for (PileConnectorInfo pileConnectorInfo : pileConnectorInfos) {
                    if (StringUtils.equals(PileConnectorDataBaseStatusEnum.OCCUPIED_CHARGING.getValue(), pileConnectorInfo.getStatus())) {
                        // 查询充电枪口状态
                        PileConnectorInfoVO connectorInfo = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorInfo.getPileConnectorCode());
                        if (Objects.isNull(connectorInfo)) {
                            throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR);
                        }
                        BigDecimal instantPower = connectorInfo.getInstantPower();
                        pileInstantPower = pileInstantPower.add(instantPower);

                        connectorPowerInfo = new SupStationPowerInfo.EquipmentPowerInfo.ConnectorPowerInfo();
                        connectorPowerInfo.setConnectorID(connectorInfo.getPileConnectorCode());
                        connectorPowerInfo.setEquipmentClassification(1);
                        connectorPowerInfo.setDataTime(dateTimeNow);
                        connectorPowerInfo.setConnectorRealTimePower(instantPower);

                        connectorPowerInfoList.add(connectorPowerInfo);
                    }
                    // 计算桩的功率（枪口功率之和）
                    equipmentPowerInfo.setEquipRealTimePower(pileInstantPower);
                    // 汇总站点功率
                    stationInstantPower = stationInstantPower.add(pileInstantPower);

                    equipmentPowerInfo.setConnectorPowerInfos(connectorPowerInfoList);
                    equipmentPowerInfoList.add(equipmentPowerInfo);
                }
            }
            supStationPowerInfo.setStationRealTimePower(stationInstantPower);
            supStationPowerInfo.setEquipmentPowerInfos(equipmentPowerInfoList);
            supStationPowerInfoList.add(supStationPowerInfo);
        });
        // 发送请求
        ThirdPartySecretInfoVO ningXiaSecretInfo = getNingXiaPlatformSecretInfo();

        String operatorId = ningXiaSecretInfo.getOurOperatorId();
        String operatorSecret = ningXiaSecretInfo.getTheirOperatorSecret();
        String signSecret = ningXiaSecretInfo.getTheirSigSecret();
        String dataSecret = ningXiaSecretInfo.getTheirDataSecret();
        String dataSecretIv = ningXiaSecretInfo.getTheirDataSecretIv();
        String urlAddress = ningXiaSecretInfo.getTheirUrlPrefix();
        String url = urlAddress + "supervise_notification_realtime_power_info";
        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        if (StringUtils.isBlank(token)) {
            return null;
        }
        // 调用平台接口
        JSONObject json = new JSONObject();
        json.put("SupStationPowerInfos", supStationPowerInfoList);
        String jsonString = JSON.toJSONString(json);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;

    }

    /**
     * 推送充电站历史充电订单信息 supervise_notification_charge_order_info_history
     *
     * @param orderCode
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public String notificationChargeOrderInfoHistory(String orderCode) {
        // 根据订单号查询出信息
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);

        ThirdPartySecretInfoVO ningXiaSecretInfo = getNingXiaPlatformSecretInfo();

        String operatorId = ningXiaSecretInfo.getOurOperatorId();
        String operatorSecret = ningXiaSecretInfo.getTheirOperatorSecret();
        String signSecret = ningXiaSecretInfo.getTheirSigSecret();
        String dataSecret = ningXiaSecretInfo.getTheirDataSecret();
        String dataSecretIv = ningXiaSecretInfo.getTheirDataSecretIv();
        String urlAddress = ningXiaSecretInfo.getTheirUrlPrefix();


        OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode);
        String url = urlAddress + "supervise_notification_charge_order_info_history";

        // 拼装成内蒙古平台所需格式对象
        ChargeOrderInfo orderInfo = transformChargeOrderInfo(orderBasicInfo, orderDetail);
        orderInfo.setOperatorID(operatorId);
        String equipmentOwnerID;
        if (MerchantUtils.isXiXiaoMerchant(orderBasicInfo.getMerchantId())) {
            equipmentOwnerID = Constants.OPERATORID_XI_XIAO;
        } else {
            equipmentOwnerID = Constants.OPERATORID_LIANLIAN;
        }
        orderInfo.setEquipmentOwnerID(equipmentOwnerID);

        List<BillingPriceVO> billingList = pileBillingTemplateService.queryBillingPrice(orderBasicInfo.getStationId());
        // 先将list按照 尖、峰、平、谷 时段排序
        // List<BillingPriceVO> collect = billingList.stream().sorted(Comparator.comparing(BillingPriceVO::getTimeType)).collect(Collectors.toList());
        // 再循环该list，拼装对应的充电价格、费率
        List<SupChargeDetails> chargeDetails = transformSupChargeDetails(orderDetail, billingList);
        orderInfo.setChargeDetails(chargeDetails);

        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        if (StringUtils.isBlank(token)) {
            return null;
        }
        // 调用联联平台接口
        JSONObject json = new JSONObject();
        json.put("ChargeOrderInfo", orderInfo);
        String jsonString = JSON.toJSONString(json);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret);
        return result;
    }

    /**
     * 转换充电站充电订单信息
     * @param orderBasicInfo
     * @param orderDetail
     * @return
     */
    private ChargeOrderInfo transformChargeOrderInfo(OrderBasicInfo orderBasicInfo, OrderDetail orderDetail) {
        ChargeOrderInfo chargeOrderInfo = ChargeOrderInfo.builder()
                .stationID(orderBasicInfo.getStationId())
                .equipmentID(orderBasicInfo.getPileSn())
                .orderNo(orderBasicInfo.getOrderCode())
                .connectorID(orderBasicInfo.getPileConnectorCode())
                .licensePlate(orderBasicInfo.getPlateNumber())
                .vin(orderBasicInfo.getVinCode())
                .startSOC(orderBasicInfo.getStartSoc())
                .endSOC(orderBasicInfo.getEndSoc())
                .startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderBasicInfo.getChargeStartTime()))
                .endTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderBasicInfo.getChargeEndTime()))
                .totalPower(orderDetail.getTotalUsedElectricity())
                .cuspElect(orderDetail.getSharpUsedElectricity())
                .peakElect(orderDetail.getSharpUsedElectricity())
                .flatElect(orderDetail.getFlatUsedElectricity())
                .valleyElect(orderDetail.getValleyUsedElectricity())
                .pushTimeStamp(DateUtils.getDateTime())
                .totalElecMoney(orderDetail.getTotalElectricityAmount())
                .totalSeviceMoney(orderDetail.getTotalServiceAmount())
                .totalMoney(orderDetail.getTotalOrderAmount())
                .stopReason(0)
                .stopDesc(orderBasicInfo.getReason()) // TODO 停止原因
                .sumPeriod(0)
                .build();
        return chargeOrderInfo;
    }

    /**
     * 转换时段充电明细
     * @param orderDetail
     * @param billingList
     * @return
     */
    private List<SupChargeDetails> transformSupChargeDetails(OrderDetail orderDetail, List<BillingPriceVO> billingList) {
        List<SupChargeDetails> resultList = Lists.newArrayList();
        SupChargeDetails detail;
        for (BillingPriceVO billingPriceVO : billingList) {
            detail = new SupChargeDetails();
            if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.SHARP.getValue())) {
                // 尖时段
                detail.setDetailStartTime(billingPriceVO.getStartTime());
                detail.setDetailEndTime(billingPriceVO.getEndTime());
                detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setDetailPower(orderDetail.getSharpUsedElectricity());
                detail.setDetailElecMoney(orderDetail.getSharpElectricityPrice());
                detail.setDetailSeviceMoney(orderDetail.getSharpServicePrice());
            } else if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.PEAK.getValue())) {
                // 峰时段
                detail.setDetailStartTime(billingPriceVO.getStartTime());
                detail.setDetailEndTime(billingPriceVO.getEndTime());
                detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setDetailPower(orderDetail.getPeakUsedElectricity());
                detail.setDetailElecMoney(orderDetail.getPeakElectricityPrice());
                detail.setDetailSeviceMoney(orderDetail.getPeakServicePrice());
            } else if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.FLAT.getValue())) {
                // 平时段
                detail.setDetailStartTime(billingPriceVO.getStartTime());
                detail.setDetailEndTime(billingPriceVO.getEndTime());
                detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setDetailPower(orderDetail.getFlatUsedElectricity());
                detail.setDetailElecMoney(orderDetail.getFlatElectricityPrice());
                detail.setDetailSeviceMoney(orderDetail.getFlatServicePrice());
            } else if (StringUtils.equals(billingPriceVO.getTimeType(), BillingTimeTypeEnum.VALLEY.getValue())) {
                // 谷时段
                detail.setDetailStartTime(billingPriceVO.getStartTime());
                detail.setDetailEndTime(billingPriceVO.getEndTime());
                detail.setElecPrice(new BigDecimal(billingPriceVO.getElectricityPrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setSevicePrice(new BigDecimal(billingPriceVO.getServicePrice()).setScale(4, BigDecimal.ROUND_HALF_UP));
                detail.setDetailPower(orderDetail.getValleyUsedElectricity());
                detail.setDetailElecMoney(orderDetail.getValleyElectricityPrice());
                detail.setDetailSeviceMoney(orderDetail.getValleyServicePrice());
            }
            resultList.add(detail);
        }
        return resultList;
    }


    /**
     * 充电站信息变化推送 notification_stationInfo
     * 新站需要推送。当站点信息发生变化时，推送新的信息通知到市级平台
     *
     * @param stationId 充电站id
     * @throws UnsupportedOperationException 未实现异常
     */
    @Override
    public String notificationStationInfo(String stationId) {
        // 通过id查询站点相关信息
        PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(Long.parseLong(stationId));

        // 查询第三方平台配置信息
        ThirdPartySecretInfoVO thirdPartySecretInfoVO = thirdpartySecretInfoService.queryByThirdPlatformType(thirdPlatformType);
        if (thirdPartySecretInfoVO == null) {
            throw new BusinessException("", "无此平台配置信息");
        }
        String operatorId = thirdPartySecretInfoVO.getOurOperatorId();
        String operatorSecret = thirdPartySecretInfoVO.getTheirOperatorSecret();
        String signSecret = thirdPartySecretInfoVO.getTheirSigSecret();
        String dataSecret = thirdPartySecretInfoVO.getTheirDataSecret();
        String dataSecretIv = thirdPartySecretInfoVO.getTheirDataSecretIv();
        String urlAddress = thirdPartySecretInfoVO.getTheirUrlPrefix();

        // 组装联联平台所需要的数据格式
        StationInfo info = StationInfo.builder()
                .stationID(stationId)
                .operatorID(operatorId)
                .stationName(pileStationInfo.getStationName())
                .isAloneApply(Integer.valueOf(pileStationInfo.getAloneApply()))
                .isPublicParkingLot(Integer.valueOf(pileStationInfo.getPublicParking()))
                .countryCode(pileStationInfo.getCountryCode())
                .address(pileStationInfo.getAddress())
                .serviceTel(pileStationInfo.getStationTel())
                .stationType(Integer.valueOf(pileStationInfo.getStationType()))
                .stationStatus(Integer.valueOf(pileStationInfo.getStationStatus()))
                .parkNums(Integer.valueOf(pileStationInfo.getParkNums()))
                .stationLng(new BigDecimal(pileStationInfo.getStationLng()))
                .stationLat(new BigDecimal(pileStationInfo.getStationLat()))
                .construction(Integer.valueOf(pileStationInfo.getConstruction()))
                .openAllDay(Integer.valueOf(pileStationInfo.getOpenAllDay()))
                .minElectricityPrice(new BigDecimal(Constants.ZERO))
                .electricityFee(Constants.ZERO)
                .serviceFee(Constants.ZERO)
                .parkFree(Integer.valueOf(pileStationInfo.getParkFree()))
                .supportOrder(Integer.valueOf(pileStationInfo.getSupportOrder()))
                .parkFeeType(0)
                .toiletFlag(Integer.valueOf(pileStationInfo.getToiletFlag()))
                .storeFlag(Integer.valueOf(pileStationInfo.getStoreFlag()))
                .restaurantFlag(Integer.valueOf(pileStationInfo.getRestaurantFlag()))
                .loungeFlag(Integer.valueOf(pileStationInfo.getLoungeFlag()))
                .canopyFlag(Integer.valueOf(pileStationInfo.getCanopyFlag()))
                .printerFlag(Integer.valueOf(pileStationInfo.getPrinterFlag()))
                .barrierFlag(Integer.valueOf(pileStationInfo.getBarrierFlag()))
                .parkingLockFlag(Integer.valueOf(pileStationInfo.getParkingLockFlag()))
                .build();
        String areaCode = pileStationInfo.getAreaCode();  // 330000,330200,330213
        // 根据逗号分组
        String[] split = StringUtils.split(areaCode, ",");
        // 只取最后一部分  330213
        String subAreaCode = split[split.length - 1];
        info.setAreaCode(subAreaCode);
        // 截取运营商组织机构代码(去除最后一位后的最后九位)
        String organizationCode = "";
        if (StringUtils.equals(ThirdPlatformTypeEnum.LIAN_LIAN_PLATFORM.getTypeCode(), thirdPlatformType)) {
            // 联联平台先使用自己运营商的组织机构代码
            organizationCode = Constants.OPERATORID_LIANLIAN;
            info.setEquipmentOwnerID(organizationCode);
        } else {
            MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfoVO(String.valueOf(pileStationInfo.getMerchantId()));
            organizationCode = merchantInfo.getOrganizationCode();
            if (StringUtils.isNotBlank(organizationCode) && organizationCode.length() == 18) {
                String equipmentOwnerId = StringUtils.substring(organizationCode, organizationCode.length() - 10, organizationCode.length() - 1);
                info.setEquipmentOwnerID(equipmentOwnerId);
            }
        }
        if (StringUtils.equals("36", String.valueOf(pileStationInfo.getMerchantId()))) {
            // 远大
            info.setEquipmentOwnerID(Constants.OPERATORID_YUAN_DA);
        }
        if (MerchantUtils.isXiXiaoMerchant(String.valueOf(pileStationInfo.getMerchantId()))) {
            // 如果是希晓运营商，则把equipmentOwnerID换成希晓
            info.setEquipmentOwnerID(Constants.OPERATORID_XI_XIAO);
        }
        String payment = StationPaymentEnum.getPaymentByCode(pileStationInfo.getPayment());
        info.setPayment(payment);
        if (StringUtils.isNotBlank(pileStationInfo.getParkingNumber())) {
            info.setIsPublicParkingLot(1);
            info.setParkingLotNumber(pileStationInfo.getParkingNumber());
        }
        // 户号
        if (StringUtils.isNotBlank(pileStationInfo.getAccountNumber())) {
            info.setAccountNumber(pileStationInfo.getAccountNumber());
        }

        // 容量
        if (StringUtils.isNotBlank(String.valueOf(pileStationInfo.getCapacity()))) {
            info.setCapacity(pileStationInfo.getCapacity().setScale(4, BigDecimal.ROUND_HALF_UP));
        }
        List<EquipmentInfo> pileList = pileBasicInfoService.getPileListForLianLian(stationId);
        if (CollectionUtils.isNotEmpty(pileList)) {
            info.setEquipmentInfos(pileList); // 充电设备信息列表
        }

        // 调用联联平台接口
        String url = urlAddress + "supervise_notification_station_info";

        String jsonStr = JSON.toJSONString(info);
        JSONObject data = new JSONObject();
        data.put("StationInfo", jsonStr);

        String jsonString = JSON.toJSONString(data);

        // 获取令牌
        String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret);
        String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret
                , dataSecretIv, operatorId, signSecret);

        return result;
    }

    // 获取青海平台配置密钥信息
    private ThirdPartySecretInfoVO getNingXiaPlatformSecretInfo() {
        // 通过第三方平台类型查询相关配置信息
        ThirdPartySecretInfoVO thirdPartySecretInfoVO = thirdpartySecretInfoService.queryByThirdPlatformType(ThirdPlatformTypeEnum.NING_XIA_PLATFORM.getTypeCode());
        if (thirdPartySecretInfoVO == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_SELECT_INFO_IS_NULL);
        }
        thirdPartySecretInfoVO.setOurOperatorId(Constants.OPERATORID_JIANG_SU);
        return thirdPartySecretInfoVO;
    }
}
