package com.xhpc.evcs.ykc.api;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.xhpc.common.api.PowerPileService;
import com.xhpc.common.api.dto.ChargingStationDto;
import com.xhpc.common.core.utils.bean.BeanUtils;
import com.xhpc.common.domain.XhpcTerminal;
import com.xhpc.evcs.cdjgpc.dto.CDConnectorInfo;
import com.xhpc.evcs.cdjgpc.dto.CDEquipmentInfo;
import com.xhpc.evcs.cdjgpc.dto.CDStationFee;
import com.xhpc.evcs.cdjgpc.dto.CDStationInfo;
import com.xhpc.evcs.cwj.dto.*;
import com.xhpc.evcs.domain.AuthSecretToken;
import com.xhpc.evcs.domain.XhpcInternetUser;
import com.xhpc.evcs.domain.XhpcStationInternetBlacklist;
import com.xhpc.evcs.dto.*;
import com.xhpc.evcs.encryption.EvcsConst;
import com.xhpc.evcs.jpa.*;
import com.xhpc.evcs.notification.CoreDispatcher;
import com.xhpc.evcs.utils.JSONUtil;
import com.xhpc.order.domain.XhpcPlaceholderOrder;
import com.xhpc.order.domain.XhpcPlacreholder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.util.NumberUtil.isInteger;
import static com.xhpc.common.data.redis.StaticBeanUtil.REDIS;
import static com.xhpc.evcs.domain.AuthSecretToken.SECRET_TOKEN_TYPE_OUT;

/**
 * 云快充
 *
 * @author yuyang
 * @Date 2026-03-17 13:41
 */
@Slf4j
@RestController
public class YKCQueryStationsInfoController extends CoreDispatcher {
    @Resource
    XhpcInternetUserRepository xhpcInternetUserRepository;
    @Resource
    XhpcStationInternetBlacklistRepository xhpcStationInternetBlacklistRepo;
    @Resource
    PowerPileService powerPileService;
    @Resource
    AuthSecretTokenRepository authSecretTokenRepository;
    @Resource
    XhpcTerminalRepository terminalRepository;
    @Resource
    private PlaceholderIRepository placeholderIRepository;
    @Autowired
    private PlaceholderIOrderRepository placeholderIOrderRepository;
    /**
     * 云快充查询充电站信息
     * @param commonRequest
     * @return
     * @throws Exception
     */
    @PostMapping("/v50/query_stations_info")
    public CommonResponse queryStationsInfo(@RequestBody(required = false) CommonRequest<CWJPageRequest> commonRequest) {

        // System.out.println("================车为家查询充电站信息=======================");
        CommonResponse resp = new CommonResponse();
        try{
            //当前页数
            CWJPageRequest pageRequest = commonRequest.transformDataType(CWJPageRequest.class);
            Integer pageNo = pageRequest.getPageNo();
            CWJPageStationsInfoResponse response = new CWJPageStationsInfoResponse();
            response.setPageNo(pageNo);
            //页码总数
            String operatorId = commonRequest.getOperatorId();
            Instant now = Instant.now();
            XhpcInternetUser xhpcInternetUser =xhpcInternetUserRepository.findByOperatorIdEvcsLikeAndCooperationStartTimeBeforeAndCooperationEndTimeAfter(operatorId, now, now);
            Long internetUserId = xhpcInternetUser.getInternetUserId();
            List<XhpcStationInternetBlacklist> xhpcStationInternetBlacklist =xhpcStationInternetBlacklistRepo.findByInternetUserId(internetUserId);
            List<String> stationKeys = new ArrayList<>(REDIS.keys("station:*"));
            List<String> validStationKeys = new ArrayList<>();
            for (String stationKey : stationKeys) {
                boolean isValid = true;
                //查询不合作的电桩
                for (XhpcStationInternetBlacklist xhpcStationInternetBlack : xhpcStationInternetBlacklist) {
                    if (stationKey.substring(8).equals(xhpcStationInternetBlack.getChargingStationId().toString())) {
                        isValid = false;
                    }
                }
                ChargingStationDto chargingStationDto = REDIS.getCacheObject(stationKey);
                if (chargingStationDto.getPiles() != null) {
                    if (isValid) {
                        validStationKeys.add(stationKey);
                    }
                }
            }
            if (validStationKeys.size() > 0) {
                Integer pageSize = pageRequest.getPageSize();
                int totalPage = validStationKeys.size() % pageSize == 0 ? validStationKeys.size() / pageSize :
                        (validStationKeys.size() / pageSize) + 1;
                response.setPageCount(totalPage);
            }
            //总记录条数
            response.setItemSize(validStationKeys.size());

            //充电站信息列表
            List<CWJStationInfo> stationInfos = new ArrayList<>();
            //计算每页开始索引
            int startIndex = -1;
            int endIndex = -1;
            if (pageNo == 1 && validStationKeys.size() <= 10) {
                startIndex = 0;
                endIndex = validStationKeys.size() - 1;
            } else {
                Integer pageSize = pageRequest.getPageSize();
                startIndex = (pageNo - 1) * pageSize;
                endIndex = startIndex + (pageSize - 1);
            }
            for (int i = startIndex; i <= endIndex; i++) {
                String stationKey = null;
                try {
                    stationKey = validStationKeys.get(i);
                } catch (Exception e) {
                    continue;
                }
                String stationId = stationKey.replace("station:", "");
                stationInfos.add(getNotificationStationInfo(stationId));
            }
            response.setStationInfos(stationInfos);
            resp.setRet("0");
            resp.setMsg("Query station info success");

            System.out.println("========/v50/query_stations_info=============="+ JSONUtil.toJSONString(response));
            resp.setData(JSONUtil.toJSONString(response));

        }catch (Exception e){
            e.printStackTrace();
        }

        return resp;
    }

    //组合场站数据
    public CWJStationInfo getNotificationStationInfo(String stationId){
        CWJStationInfo cwjStationInfo = new CWJStationInfo();

        String key = "cdjgpc:station:".concat(stationId)+".notification";
        CDStationInfo cdStationInfo = REDIS.getCacheObject(key);

        BeanUtils.copyBeanProp(cwjStationInfo,cdStationInfo);
        cwjStationInfo.setBusineHours("00:00-24:00");
        cwjStationInfo.setParkingDiscountType(2);

        //获取占位费信息
        XhpcPlacreholder xhpcPlacreholder = placeholderIRepository.findByYkcStatusAndChargingStationIdAndDelFlag(1,Long.valueOf(stationId), 0);
        if(xhpcPlacreholder !=null){
            cwjStationInfo.setOvertimeFee(xhpcPlacreholder.getContent());
        }
        //cwjStationInfo.setAreaCode(cdStationInfo.getAreaCodeCountryside());
        cwjStationInfo.setEquipmentInfos(new ArrayList<>());
        //查询场站是桩是否对应上
        ChargingStationDto stationDto = REDIS.getCacheObject("station:"+stationId);

        List<CWJEquipmentInfo> cwjEquipmentInfos = new ArrayList<>();

        Set<String> pks = stationDto.getPiles();
        if (pks != null) {
            for (String pileNo : pks) {
                String pk = "pile:".concat(pileNo);
                String skey = "cdjgpc:".concat(pk) + ".notification";
                CDEquipmentInfo cdEquipmentInfo = REDIS.getCacheObject(skey);
                CWJEquipmentInfo cwjEquipmentInfo = new CWJEquipmentInfo();
                BeanUtils.copyBeanProp(cwjEquipmentInfo,cdEquipmentInfo);

                List<CWJConnectorInfo> connectorInfos =new ArrayList<>();
                List<CDConnectorInfo> connectorInfos1 = cdEquipmentInfo.getConnectorInfos();

                for (int i = 0; i <connectorInfos1.size() ; i++) {
                    CDConnectorInfo cdConnectorInfo = connectorInfos1.get(i);
                    CWJConnectorInfo cwjConnectorInfo = new CWJConnectorInfo();
                    BeanUtils.copyBeanProp(cwjConnectorInfo,cdConnectorInfo);
                    connectorInfos.add(cwjConnectorInfo);
                }
                cwjEquipmentInfo.setConnectorInfos(connectorInfos);
                cwjEquipmentInfo.setPower(cdEquipmentInfo.getEquipmentPower());
                cwjEquipmentInfos.add(cwjEquipmentInfo);
            }
            cwjStationInfo.setEquipmentInfos(cwjEquipmentInfos);
            REDIS.setCacheObject(key, cdStationInfo);
        }
        return cwjStationInfo;
    }

    /**
     * 设备接口状态查询(成都市平台调用我们平台)  --已调用
     * @param commonRequest
     * @return
     * @throws Exception
     */
    @PostMapping("/v50/query_station_status")
    public CommonResponse queryStationsStatus(@RequestBody CommonRequest<StationStatusRequest> commonRequest) throws Exception {

        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
        StationStatusRequest stationStatusRequest = JSONUtil.readParams(commonRequest.getData(), StationStatusRequest.class);
        if (stationStatusRequest == null) {
            resp.setMsg("Request or token params validation failed");
        } else {
            String[] stationIDs = stationStatusRequest.getStationIds();
            List<CWJStationStatusInfo> cdStationStatusInfos = new ArrayList<>();
            //Loading data through redis at first.
            Collection<String> guns = REDIS.keys("gun:*");
            List<String> gunsNewList = new ArrayList<>();
            for (String value : guns) {
                gunsNewList.add(value.substring(4));
            }
            List<String> gunsIds = new ArrayList<>();
            for (String value : gunsNewList) {
                if (value.length() == 16) {
                    gunsIds.add(value);
                }
            }
            Map<String, Integer> statusMap = new HashMap<>();
            String[] keys = {"离线", "空闲", "故障", "插枪"};
            Integer[] values = {0, 1, 255,2};
            for (int i = 0; i < keys.length; i++) {
                statusMap.put(keys[i], values[i]);
            }

            List<XhpcTerminal> terminalList = terminalRepository.selectStatusBySql();
            Map<String,Integer> terminalDBMap = terminalList.stream().collect(Collectors.toMap(XhpcTerminal::getSerialNumber,XhpcTerminal::getStatus));

            for (String stationID : stationIDs) {
                ChargingStationDto chargingStationDto = REDIS.getCacheObject("station:" + stationID);
                Set<String> pileIds = new HashSet<>();
                if (null != chargingStationDto) {
                    pileIds = chargingStationDto.getPiles();
                }
                boolean existsGun = false;
                List<CWJConnectorStatusInfo> connectorStatusInfos = new ArrayList<>();
                for (String pileId : pileIds) {
                    for (String value : gunsIds) {
                        if (pileId.equals(value.substring(0, 14))) {
                            existsGun = true;
                            CWJConnectorStatusInfo cdConnectorStatusInfo = new CWJConnectorStatusInfo();
                            Integer gunStatus = terminalDBMap.get(value);
                            if (gunStatus == null){
                                existsGun = false;
                            } else {
                                if (gunStatus == 0){
                                    Object status = REDIS.getCacheMapValue("gun:" + value, "status");
                                    if (isInteger(status.toString())) {
                                        cdConnectorStatusInfo.setStatus(3);
                                    } else {
                                        cdConnectorStatusInfo.setStatus(statusMap.get(status));
                                    }
                                } else {
                                    cdConnectorStatusInfo.setStatus(0);
                                }
                                cdConnectorStatusInfo.setConnectorID(value);
                                connectorStatusInfos.add(cdConnectorStatusInfo);
                            }
                        }
                    }
                }
                if (existsGun) {
                    CWJStationStatusInfo cdStationStatusInfo = new CWJStationStatusInfo();
                    cdStationStatusInfo.setStationID(stationID);
                    cdStationStatusInfo.setConnectorStatusInfos(connectorStatusInfos);
                    cdStationStatusInfos.add(cdStationStatusInfo);
                }
            }
            CWJStationStatusInfoWrapper stationStatusInfoWrappers = new CWJStationStatusInfoWrapper();
            stationStatusInfoWrappers.setTotal(cdStationStatusInfos.size());
            if (cdStationStatusInfos.size() != 0) {
                stationStatusInfoWrappers.setStationStatusInfos(cdStationStatusInfos);
            }
            resp.setRet("0");
            resp.setMsg("Query station status success");
            resp.setData(JSONUtil.toJSONString(stationStatusInfoWrappers));
        }
        return resp;
    }


    /**
     * 推送站点下线
     * @return
     * @throws Exception
     */
    @PostMapping("/v50/getNotificationStationFee")
    public void getNotificationStationFee(String stationID) throws Exception {
        AuthSecretToken authSecretTokenOut = authSecretTokenRepository.findByOperatorId3irdptyAndOperatorIdAndSecretTokenType(
                "MA6CC2LK7", "MA6DFCTD5", SECRET_TOKEN_TYPE_OUT).orElse(null);
        // maybe对接第三方
        if (authSecretTokenOut != null) {
            Map<String, Object> map =new HashMap<>();
            map.put("StationID",stationID);
            String data = JSONUtil.toJSONString(map);
            CommonRequest<CDStationFee> commonRequest = new CommonRequest<>();
            commonRequest.setData(data);
            ok(commonRequest, "/notification_stationOfflineStatus", authSecretTokenOut);
        }
    }

    @PostMapping("/v50/query_occupancy_order_info")
    public CommonResponse queryOccupancyOrderInfo(@RequestBody(required = false) CommonRequest<CancelOrderRequest> commonRequest) {
        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
      try{
          CancelOrderRequest cancelOrderRequest = JSONUtil.readParams(commonRequest.getData(), CancelOrderRequest.class);
          XhpcPlaceholderOrder placeholderOrder = placeholderIOrderRepository.findByInternetSerialNumber(cancelOrderRequest.getStartChargeSeq());
          OccupancyOrderInfo occupancyOrderInfo = new OccupancyOrderInfo();
          occupancyOrderInfo.setOccupancyFeeCode(placeholderOrder.getPlaceholderOrderNumber());
          occupancyOrderInfo.setOccupancyStatus(placeholderOrder.getStatus());
          occupancyOrderInfo.setStartChargeSeq(placeholderOrder.getInternetSerialNumber());
          occupancyOrderInfo.setConnectorID(placeholderOrder.getTerminalNumber());
          occupancyOrderInfo.setStartTime(DateUtil.format(placeholderOrder.getStartTime(), "yyyy-MM-dd HH:mm:ss"));
          occupancyOrderInfo.setEndTime(DateUtil.format(placeholderOrder.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
          occupancyOrderInfo.setFreeDuration(placeholderOrder.getFreeTime());

          if(placeholderOrder.getTotalTimeSpan() !=null || placeholderOrder.getConfirmResult()==0){
              if(placeholderOrder.getTotalTimeSpan()>30){
                  occupancyOrderInfo.setOccupancyFeeStartTime(DateUtil.format(DateUtil.offsetMinute(placeholderOrder.getStartTime(),30), "yyyy-MM-dd HH:mm:ss"));
                  occupancyOrderInfo.setOccupancyDuration(placeholderOrder.getTotalTimeSpan()-30);
                  occupancyOrderInfo.setTotalOccupancyFee(new BigDecimal(0.2).multiply(new BigDecimal(placeholderOrder.getTotalTimeSpan()-30)).setScale(2,BigDecimal.ROUND_CEILING));
              }else{
                  occupancyOrderInfo.setOccupancyDuration(0);
                  occupancyOrderInfo.setTotalOccupancyFee(new BigDecimal(0));
              }
          }else{
              DateTime parse = cn.hutool.core.date.DateUtil.parse(DateUtil.format(placeholderOrder.getStartTime(), "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss");
              DateTime parse1 = new DateTime();
              long betweenDay = cn.hutool.core.date.DateUtil.between(parse,parse1, DateUnit.MINUTE);
              if(betweenDay>30){
                  int num = (int) (betweenDay - 30);
                  occupancyOrderInfo.setOccupancyFeeStartTime(DateUtil.format(DateUtil.offsetMinute(placeholderOrder.getStartTime(),30), "yyyy-MM-dd HH:mm:ss"));
                  occupancyOrderInfo.setOccupancyDuration(num);
                  occupancyOrderInfo.setTotalOccupancyFee(new BigDecimal(0.2).multiply(new BigDecimal(num)).setScale(2,BigDecimal.ROUND_HALF_UP));
              }else{
                  occupancyOrderInfo.setOccupancyDuration(0);
                  occupancyOrderInfo.setTotalOccupancyFee(new BigDecimal(0));
              }
          }

          resp.setRet(EvcsConst.RET_SUCC);
          resp.setMsg("获取占位费信息成功");
          resp.setData(JSONUtil.toJSONString(occupancyOrderInfo));
          return resp;
      }catch (Exception e){
            e.printStackTrace();
      }
        resp.setMsg("获取占位费信息失败");

        return resp;
    }



}
