package com.xhpc.charging.station.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import com.xhpc.charging.station.mapper.XhpcChargingPileMapper;
import com.xhpc.charging.station.mapper.XhpcImgMapper;
import com.xhpc.charging.station.mapper.XhpcTerminalMapper;
import com.xhpc.charging.station.pojo.XhpcImg;
import com.xhpc.charging.station.utils.img.QrImgUtils;
import com.xhpc.common.api.PowerPileService;
import com.xhpc.common.api.TenantService;
import com.xhpc.common.core.constant.HttpStatus;
import com.xhpc.common.core.domain.R;
import com.xhpc.common.core.exception.CustomException;
import com.xhpc.common.core.utils.SecurityUtils;
import com.xhpc.common.core.utils.StringUtils;
import com.xhpc.common.core.web.domain.AjaxResult;
import com.xhpc.common.core.web.service.BaseService;
import com.xhpc.common.domain.XhpcChargingPile;
import com.xhpc.common.domain.XhpcChargingStation;
import com.xhpc.common.domain.XhpcTerminal;
import com.xhpc.common.enums.ConnectorTypeEnum;
import com.xhpc.common.enums.PileEquipmentTypeEnum;
import com.xhpc.common.enums.PowerTypeEnum;
import com.xhpc.common.redis.service.RedisService;
import com.xhpc.common.security.service.TokenService;
import com.xhpc.common.util.LogUserUtils;
import com.xhpc.system.api.domain.SysUser;
import com.xhpc.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.*;

import static com.aliyun.oss.internal.OSSConstants.URL_ENCODING;

/**
 * @author yuyang
 * @date 2021/7/27 14:36
 */
@Service
public class XhpcChargingPileServiceImpl extends BaseService implements IXhpcChargingPileService{

    @Autowired
    private XhpcChargingPileMapper xhpcChargingPileMapper;
    @Autowired
    private XhpcTerminalMapper xhpcTerminalMapper;
    @Autowired
    private PowerPileService powerPileService;
    @Autowired
    private Environment environment;
    @Autowired
    private XhpcImgMapper xhpcImgMapper;
    @Autowired
    private IXhpcChargingStationService xhpcChargingStationService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private TenantService tenantService;
    @Autowired
    RedisService redisService;

    private final ExecutorService executorService = Executors.newFixedThreadPool(20);
    //字母集合
    private static Map letterMap;

    static {
        Character letter = 'A';
        letterMap = new HashMap<Integer, Character>();
        for (int i = 1; i <= 26; i++) {
            letterMap.put(i, letter);
            letter++;
        }
    }



    /**
     * 桩列表
     *
     * @param serialNumber 桩编号
     * @param type         桩类型
     * @param name         桩名称
     * @return
     */
    @Override
    public List<Map<String, Object>> selectXhpcChargingPileList(HttpServletRequest request,String tenantId,Long operatorId, String name, Integer type, String serialNumber, Long chargingStationId) {

        LoginUser loginUser = tokenService.getLoginUser();
        //获取登陆用户
        Long userId = loginUser.getUserid();
        //桩的统计、该时段金额
        List<Map<String, Object>> list =new ArrayList<>();

        if(userId !=1) {
            Map<String, Object> landUser = xhpcChargingStationService.getLandUser(userId);
            if(landUser !=null){
                if(landUser.get("userType") !=null){
                    startPage();
                    if("01".equals(landUser.get("userType").toString())){
                        Long logOperatorId = Long.valueOf(landUser.get("operatorId").toString());
                        list= xhpcChargingPileMapper.selectXhpcChargingPileList(operatorId,name, type, serialNumber, chargingStationId,logOperatorId,1,tenantId);
                    }else{
                        list= xhpcChargingPileMapper.selectXhpcChargingPileList(operatorId,name, type, serialNumber, chargingStationId,userId,2,tenantId);
                    }
                }
            }
        }else{
            startPage();
            list= xhpcChargingPileMapper.selectXhpcChargingPileList(operatorId,name, type, serialNumber, chargingStationId,userId,0,tenantId);
        }

        if(list !=null && list.size()>0){
            for (Map<String, Object> map: list ) {
                if(map.get("serialNumber") !=null){
                    String serialNumberMap =map.get("serialNumber").toString();
                    String configRateReply = redisService.getCacheObject("pile:" + serialNumberMap + ".configRateReply");
                    if(configRateReply==null || "".equals(configRateReply)){
                        map.put("configRmReply","未下发");
                    }else{
                        map.put("configRmReply",configRateReply);
                    }
                }
            }
        }
        return list;
    }

    @Override
    @Transactional
    public AjaxResult addXhpcChargingPile(XhpcChargingPile xhpcChargingPile) {
        Long chargingStationId = xhpcChargingPile.getChargingStationId();
        LoginUser loginUser = tokenService.getLoginUser();
        String tenantId = loginUser.getTenantId();
        R r1 = tenantService.gettenantIdTime(loginUser.getTenantId());
        if(r1.getCode()!=200){
            return AjaxResult.error(1001, "请重新登录");
        }else{
            Map<String, Object> map = (Map<String, Object>)r1.getData();
            if(map !=null){
                if(!map.get("stationPileQuote").toString().equals("-1")){
                    int count = xhpcChargingPileMapper.getCountXhpcChargingPile(chargingStationId,loginUser.getTenantId());
                    if(Integer.parseInt(map.get("stationPileQuote").toString())<count){
                        return AjaxResult.error(1001, "桩已达到限额，如要在创建桩请联系管理员");
                    }
                }
            }else{
                return AjaxResult.error(1001, "无法创建桩请联系管理员");
            }
        }

        if(xhpcChargingPile.getGunNumber() ==null || xhpcChargingPile.getGunNumber()>26){
            return AjaxResult.error("终端数量不能大于26");
        }
        if(xhpcChargingPile.getSerialNumber() ==null || xhpcChargingPile.getSerialNumber().length()!=14){
            return AjaxResult.error("桩编号14位");
        }

        //获取计费模型id
        Map<String, Object> stringObjectMap = xhpcChargingPileMapper.selectXhpcChargingStationById(chargingStationId);
        Long rateModelId = Long.parseLong(StringUtils.valueOf(stringObjectMap.get("rateModelId")));
        xhpcChargingPile.setRateModelId(rateModelId);
        String serialNumber = xhpcChargingPile.getSerialNumber();
        xhpcChargingPile.setCreateTime(new Date());
        xhpcChargingPile.setTenantId(tenantId);
        //判断桩编号是否重复
        int count = xhpcChargingPileMapper.getXhpcChargingPileSerialNumberCount(serialNumber);
        if (count > 0) {
            return AjaxResult.error("桩编号重复");
        }
        //桩
        xhpcChargingPileMapper.insertXhpcChargingPile(xhpcChargingPile);
        //终端
        Long chargingPileId = xhpcChargingPile.getChargingPileId();

        if (xhpcChargingPile.getGunNumber() > 0) {
            int number = xhpcChargingPileMapper.countXhpcTerminal(chargingStationId);
            for (int i = 1; i <= xhpcChargingPile.getGunNumber(); i++) {
                addXhpcTerminal(xhpcChargingPile.getName(), chargingStationId, rateModelId, serialNumber, chargingPileId, i, number + 1, xhpcChargingPile.getConnectorType(),tenantId);
            }
        }
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    //插入redis 桩的编号
                    HashSet<String> noSet = new HashSet<>();
                    noSet.add(serialNumber);
                    R r = powerPileService.addPileWhitelist(chargingStationId, xhpcChargingPile.getCommunicationProtocolVersion(), noSet);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        return AjaxResult.success();
    }

    /**
     * @param name           桩名称
     * @param chargingPileId 场站id
     * @param rateModelId    费率模型id
     * @param i              枪号，索引，map映射
     * @pa
     * @author Yu yang
     * @date 2022/2/17 15:31
     * @since version-1.0
     */
    private void addXhpcTerminal(String name, Long chargingStationId, Long rateModelId, String serialNumber, Long chargingPileId, int i, int number, int conType,String tenantId) {

        XhpcTerminal xhpcTerminal = new XhpcTerminal();
        xhpcTerminal.setChargingStationId(chargingStationId);
        xhpcTerminal.setChargingPileId(chargingPileId);
        xhpcTerminal.setName(name + "号桩" + "-" + letterMap.get(i) + "枪");
        if (i > 9) {
            xhpcTerminal.setSerialNumber(serialNumber + i);
        } else {
            xhpcTerminal.setSerialNumber(serialNumber + "0" + i);
        }
        xhpcTerminal.setPileSerialNumber(serialNumber);
        xhpcTerminal.setWorkStatus(2);
        xhpcTerminal.setStatus(0);
        xhpcTerminal.setRateModelId(rateModelId);
        xhpcTerminal.setNumber(number);
        xhpcTerminal.setConnectorType(conType);
        xhpcTerminal.setTenantId(tenantId);
        xhpcTerminalMapper.insertXhpcTerminal(xhpcTerminal);

        //获取场站名称：
        String chargingStationName = xhpcChargingStationService.selectXhpcChargingStationById(xhpcTerminal.getChargingStationId()).getName();
        //生成最终的完整图片，并上传
        QrImgUtils.uploadImg(xhpcTerminal, xhpcTerminal.getSerialNumber(),environment,xhpcImgMapper,chargingStationName,i,letterMap,name);

    }

    @Override
    @Transactional
    public AjaxResult updateXhpcChargingPile(XhpcChargingPile xhpcChargingPile) {

        Long chargingPileId = xhpcChargingPile.getChargingPileId();
        XhpcChargingPile xhpc = xhpcChargingPileMapper.selectXhpcChargingPileById(chargingPileId);

        if (xhpcChargingPile.getSerialNumber() == null) {
            return AjaxResult.error("桩编号不能为空");
        }
        if (!xhpc.getSerialNumber().equals(xhpc.getSerialNumber())) {
            //删除桩
            HashSet<String> set = new HashSet<>();
            set.add(xhpc.getSerialNumber());
            R r = powerPileService.deletePileWhitelist(xhpc.getChargingStationId(), set);
            if(r.getCode() !=200){
                //数据回滚-手动回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return  AjaxResult.error("删除之前桩号缓存失败，请稍后在试");
            }
        }
        if (xhpcChargingPile.getGunNumber() == null || xhpcChargingPile.getGunNumber() > 26) {
            return AjaxResult.error("终端数量不能大于26");
        }
        if (!xhpcChargingPile.getGunNumber().equals(xhpc.getGunNumber()) || !xhpcChargingPile.getSerialNumber().equals(xhpc.getSerialNumber())) {
            //删除之前的终端
            xhpcChargingPileMapper.updateXhpcTerminal(chargingPileId);
            int number = xhpcChargingPileMapper.countXhpcTerminal(xhpcChargingPile.getChargingStationId());
            String serialNumber = xhpcChargingPile.getSerialNumber();
            Long rateModelId = xhpcChargingPile.getRateModelId();
            Long chargingStationId = xhpcChargingPile.getChargingStationId();
            if (xhpcChargingPile.getGunNumber() > 0) {
                // 删除阿里云上面之前可能存在的桩图片文件夹
                // clearRepetition(environment, serialNumber);
                for (int i = 1; i <= xhpcChargingPile.getGunNumber(); i++) {
                    addXhpcTerminal(xhpcChargingPile.getName(), chargingStationId, rateModelId, serialNumber, chargingPileId, i, number + 1, xhpcChargingPile.getConnectorType(),xhpc.getTenantId());
                }
            }
            //插入redis 桩的编号
            HashSet<String> noSet = new HashSet<>();
            noSet.add(serialNumber);
            R r = powerPileService.addPileWhitelist(chargingStationId, xhpcChargingPile.getCommunicationProtocolVersion(), noSet);
            if (r.getCode() != 200) {
                //数据回滚-手动回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return  AjaxResult.error("添加桩入缓存失败，请稍后在试");
            }
        }else{
            Long chargingStationId = xhpcChargingPile.getChargingStationId();
            String serialNumber = xhpcChargingPile.getSerialNumber();

            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(3000);
                        HashSet<String> noSet = new HashSet<>();
                        noSet.add(serialNumber);
                        R r = powerPileService.addPileWhitelist(chargingStationId, xhpcChargingPile.getCommunicationProtocolVersion(), noSet);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });

        }
        xhpcChargingPileMapper.updaeXhpcChargingPile(xhpcChargingPile);

        return AjaxResult.success();
    }

    @Override
    public AjaxResult selectXhpcChargingPile(Long chargingPileId) {

        XhpcChargingPile xhpc = xhpcChargingPileMapper.selectXhpcChargingPileById(chargingPileId);
        //终端信息
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> list = xhpcChargingPileMapper.selectXhpcTerminalList(chargingPileId);
        if(list !=null && list.size()>0){
            for (int i = 0; i < list.size(); i++) {
                Map<String, Object> listMap =list.get(i);
                int pileSerialNumber = xhpcChargingStationService.getTerminalStatus(listMap.get("serialNumber").toString());
                listMap.put("workStatus",pileSerialNumber);
            }
        }
        map.put("chargingPile", xhpc);
        map.put("terminal", list);
        return AjaxResult.success(map);
    }


    @Override
    @Transactional
    public AjaxResult updateStatus(Long chargingPileId, Integer status,String prompt) {
        if(status ==0 || status ==1){
            XhpcChargingPile xhpc = xhpcChargingPileMapper.selectXhpcChargingPileById(chargingPileId);
            xhpc.setStatus(status);
            xhpcChargingPileMapper.updaeXhpcChargingPile(xhpc);
            //修改枪状态 0正常 1停用
            xhpcChargingPileMapper.xhpcTerminalSataus(chargingPileId,status,prompt);
            return AjaxResult.success();
        }
        return AjaxResult.error("修改状态不对请重新编辑");
    }

    @Override
    @Transactional
    public int updateXhpcChargingPileById(Long chargingPileId) {

        XhpcChargingPile xhpc = xhpcChargingPileMapper.selectXhpcChargingPileById(chargingPileId);
        int i = xhpcChargingPileMapper.updateXhpcChargingPileById(chargingPileId);
        if (i > 0) {
            //删除桩
            Set<String> set = new HashSet<>();
            set.add(xhpc.getSerialNumber());
            powerPileService.deletePileWhitelist(xhpc.getChargingStationId(), set);
            return 1;
        }
        return 0;
    }

    /**
     * 下载对应终端的二维码图片
     *
     * @param terminalIds
     * @return
     */
    @Override
    public List<Map<String, Object>> downloadsTerminalImgs(List<Integer> terminalIds) {

        return xhpcImgMapper.selectImgUrlByTerminal_id(terminalIds);
    }

    /**
     * 清理阿里云中冗余的二维码图片数据
     * <p>
     * 该方法会根据传入的桩名称<param>prefix<param>,
     * 到阿里云上去删除指定的桩下面的所有终端二维码（包括其本身）
     *
     * @param environment nacos环境对象
     * @param prefix      桩的名称
     */
    public static void clearRepetition(Environment environment, String prefix) {

        OSSClient ossClient = new OSSClient(environment.getProperty("oss.endpoint"), environment.getProperty("oss.access-key"), environment.getProperty("oss.secret-key"));
        String bucketName = environment.getProperty("oss.bucket-name");
        System.out.println("==》桩：" + prefix + "图片冗余正在清理");
        prefix = prefix + "/";
        String nextMarker = null;
        ObjectListing objectListing = null;
        do {
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName)
                    .withPrefix(prefix)
                    .withMarker(nextMarker);
            objectListing = ossClient.listObjects(listObjectsRequest);
            if (objectListing.getObjectSummaries().size() > 0) {
                List<String> keys = new ArrayList<String>();
                for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
                    keys.add(s.getKey());
                }
                DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName).withKeys(keys).withEncodingType(URL_ENCODING);
                DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(deleteObjectsRequest);
                List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
                try {
                    for (String obj : deletedObjects) {
                        String deleteObj = URLDecoder.decode(obj, "UTF-8");
                        System.out.println(deleteObj);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            nextMarker = objectListing.getNextMarker();
        } while (objectListing.isTruncated());
        System.out.println(DateUtil.now() + "==》图片冗余清理执行成功");
    }


    @Override
    public String importPile(List<XhpcChargingPile> pileList, Boolean isUpdateSupport, String operName){

        if (pileList == null || pileList.size() == 0) {
            throw new CustomException("导入电桩数据不能为空！");
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (XhpcChargingPile pile : pileList) {
            try {
                // 所有表格字段数据必须非空且有效
                if(StrUtil.hasBlank(pile.getChargingStationName()) || StrUtil.hasBlank(pile.getName())
                        || StrUtil.hasBlank(pile.getBrandModel()) || StrUtil.hasBlank(pile.getNationalStandard())
                        || pile.getPower() == null || pile.getPower() < 0
                        || pile.getAuxiliaryPowerSupply() == null || pile.getAuxiliaryPowerSupply() < 0
                        || pile.getInputVoltage() ==null || pile.getInputVoltage() < 0
                        || pile.getMaxVoltage() ==null || pile.getMaxVoltage() < 0
                        || pile.getMinVoltage() == null || pile.getMinVoltage() < 0
                        || pile.getMaxElectricCurrent() == null || pile.getMaxElectricCurrent() < 0
                        || pile.getMinElectriCurrent() == null || pile.getMinElectriCurrent() < 0
                        || StrUtil.hasBlank(pile.getSerialNumber())
                        || StrUtil.hasBlank(pile.getTypeName())
                        || pile.getGunNumber() == null || pile.getGunNumber() < 0
                        || StrUtil.hasBlank(pile.getCommunicationProtocolVersion()) || StrUtil.hasBlank(pile.getNetworkLinkType())
                        || StrUtil.hasBlank(pile.getProductionDate()) || StrUtil.hasBlank(pile.getManufactureName())
                        || StrUtil.hasBlank(pile.getConnectorTypeName())|| StrUtil.hasBlank(pile.getEquipmentTypeName())){
                    failureNum ++;
                    failureMsg.append("<br/>电站名称: ").append(pile.getChargingStationName()).append(" ,电桩名称: ").append(pile.getName()).append(" 导入失败; 失败原因: 必填字段为空。");
                    continue;
                }

                pile.setType(PowerTypeEnum.getCodeByName(pile.getTypeName()));
                pile.setConnectorType(ConnectorTypeEnum.getCodeByName(pile.getConnectorTypeName()));
                pile.setEquipmentType(PileEquipmentTypeEnum.getCodeByName(pile.getEquipmentTypeName()));
                if("否".equals(pile.getNewNationalStandardName())){
                    pile.setNewNationalStandard(0);
                }else{
                    pile.setNewNationalStandard(1);
                }
                if("否".equals(pile.getVinFlagName())){
                    pile.setVinFlag(0);
                }else{
                    pile.setVinFlag(1);
                }

                if("未知".equals(pile.getEquipmentStatusName())){
                    pile.setEquipmentStatus(0);
                }else if("建设中".equals(pile.getEquipmentStatusName())){
                    pile.setEquipmentStatus(1);
                }else if("关闭下线".equals(pile.getEquipmentStatusName())){
                    pile.setEquipmentStatus(5);
                }else if("维护中".equals(pile.getEquipmentStatusName())){
                    pile.setEquipmentStatus(6);
                }else {
                    pile.setVinFlag(50);
                }

                if("公共".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(0);
                }else if("个人".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(50);
                }else if("公交(专用)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(100);
                }else if("环卫(专用)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(101);
                }else if("物流(专用)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(102);
                }else if("出租车(专用)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(103);
                }else if("分时租赁(专用)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(104);
                }else if("单位(专用)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(106);
                }else if("移动站点(移动储能设备)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(107);
                }else if("居民小区(公共)".equals(pile.getEquipmentPurposeName())){
                    pile.setEquipmentStatus(108);
                }else {
                    pile.setVinFlag(109);
                }

                if("车辆充电设备".equals(pile.getEquipmentClassificatlonName())){
                    pile.setEquipmentClassificatlon(1);
                }else{
                    pile.setEquipmentClassificatlon(2);
                }



                XhpcChargingStation station = xhpcChargingStationService.selectXhpcChargingStationByName(pile.getChargingStationName());
                if(station == null){
                    failureNum ++;
                    failureMsg.append("<br/>电站名称: ").append(pile.getChargingStationName()).append(" ,电桩名称: ").append(pile.getName()).append(" 导入失败; 失败原因: 电站不存在。");
                    continue;
                }
                pile.setChargingStationId(station.getChargingStationId());

                String serialNumber = pile.getSerialNumber();
                XhpcChargingPile chargingPile = xhpcChargingPileMapper.getXhpcChargingPileBySerialNumber(serialNumber);
                AjaxResult result = null;

                if(isUpdateSupport){
                    if(chargingPile != null){
                        pile.setChargingPileId(chargingPile.getChargingPileId());
                        result = updateXhpcChargingPile(pile);
                    }else {
                        result = addXhpcChargingPile(pile);
                    }
                } else {
                    if(chargingPile != null) {
                        result = AjaxResult.error("桩编号重复");
                    } else {
                        result = addXhpcChargingPile(pile);
                    }
                }

                if(!result.get(AjaxResult.CODE_TAG).equals(HttpStatus.SUCCESS)){
                    failureNum ++;
                    failureMsg.append("<br/>电站名称: ").append(pile.getChargingStationName()).append(" ,电桩名称: ").append(pile.getName()).append(" 导入失败; 失败原因: ").append(result.get(AjaxResult.MSG_TAG));
                } else {
                    successNum++;
                }
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>电站名称: ").append(pile.getChargingStationName()).append(" ,电桩名称: ").append(pile.getName()).append(" 导入失败; 失败原因: ").append(e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new CustomException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult generateQrCode(Long chargingStationId, Long pileId) {
        //get tenant id
        LoginUser loginUser = tokenService.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        String tenantId = sysUser.getTenantId();
        //query effective pile
        List<XhpcChargingPile> xhpcChargingPile = xhpcChargingPileMapper.selectXhpcChargingPilesBy(chargingStationId, pileId, tenantId);
        if (xhpcChargingPile.isEmpty()) {
            return AjaxResult.success();
        }
        ArrayList<Long> pileIds = new ArrayList<>();
        for (XhpcChargingPile chargingPile : xhpcChargingPile) {
            Long chargingPileId = chargingPile.getChargingPileId();
            pileIds.add(chargingPileId);
        }
        //get effective terminal
        List<XhpcTerminal> xhpcTerminalList = xhpcTerminalMapper.selectXhpcTerminalIdByPileIds(pileIds);
        if (xhpcTerminalList.isEmpty()) {
            return AjaxResult.success();
        }
        ArrayList<Long> terminalIds = new ArrayList<>();
        for (XhpcTerminal xhpcTerminal : xhpcTerminalList) {
            Long terminalId = xhpcTerminal.getTerminalId();
            terminalIds.add(terminalId);
        }
        //delete old qrcode img url data in the database
        List<XhpcImg> xhpcImgList = xhpcImgMapper.selectByTerminalId(terminalIds);
        for (XhpcImg xhpcImg : xhpcImgList) {
            //阿里云冗余二维码图片清理代码
            //String prefix = null;
            //clearRepetition(environment, prefix);
            xhpcImgMapper.updateDelFlagByTerminalId(xhpcImg.getTerminalId());
        }
        //开启多个线程，并行执行操作
        //generate qrcode for every terminal
        ThreadPoolExecutor executor =
                new ThreadPoolExecutor(30, 40, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(40));
        for (XhpcTerminal xhpcTerminal : xhpcTerminalList) {
            executor.execute(() -> {
                //获取场站名称：
                String chargingStationName = xhpcChargingStationService.selectXhpcChargingStationById(xhpcTerminal.getChargingStationId()).getName();
                //解析桩号和枪号
                String terminalSerialNumberStr = xhpcTerminal.getSerialNumber();
                String pileAndGunNumberStr = terminalSerialNumberStr.substring(12);
                String pileNumberStr = pileAndGunNumberStr.substring(0, 2);
                String gunNumberStr = pileAndGunNumberStr.substring(2, 4);
                int gunNumber = Integer.parseInt(gunNumberStr);
                Integer pileNumber = Integer.parseInt(pileNumberStr);
                //生成最终的完整图片，并上传
                /**
                 *      * @param xhpcTerminal 终端实体类
                 *      * @param serialNumber 终端序列号
                 *      * @param environment nacos对象
                 *      * @param xhpcImgMapper xhpc_img表对象
                 *      * @param chargingStationName 场站名称
                 *      * @param forIndex 枪号，用于拿出letterMap中的字母
                 *      * @param letterMap 字母集合
                 *      * @param name 桩号（桩名称）
                 */
                QrImgUtils.uploadImg(xhpcTerminal, xhpcTerminal.getSerialNumber(), environment, xhpcImgMapper, chargingStationName, gunNumber, letterMap, pileNumber.toString());
            });
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return AjaxResult.success();
    }

    @Override
    public R getChargingPileSerialNumber(String serialNumber) {
        XhpcChargingPile xhpc = xhpcChargingPileMapper.getXhpcChargingPileBySerialNumber(serialNumber);
        return R.ok(xhpc);
    }

    @Override
    public void updateXhpcChargingPilePowerNumber(String serialNumber, Integer powerNumber) {
        xhpcChargingPileMapper.updateXhpcChargingPile(serialNumber,powerNumber);
    }

}
