package com.xhpc.evcs.cwj.api;

import com.xhpc.common.api.PileOrderService;
import com.xhpc.common.core.domain.R;
import com.xhpc.common.core.utils.DateUtils;
import com.xhpc.evcs.cwj.dto.CWJStartChargeRequest;
import com.xhpc.evcs.domain.AuthSecretToken;
import com.xhpc.evcs.domain.EtOrderMapping;
import com.xhpc.evcs.domain.XhpcChargingStation;
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.XhpcHistoryOrder;
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.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.xhpc.common.data.redis.StaticBeanUtil.REDIS;
import static com.xhpc.common.data.redis.StaticBeanUtil.genOrder;
import static com.xhpc.evcs.domain.AuthSecretToken.SECRET_TOKEN_TYPE_OUT;

/**
 * @author yuyang
 * @Date 2025-07-16 14:46
 */
@RestController
public class CWJQueryStartChargeController  extends CoreDispatcher {

    @Resource
    AuthSecretTokenRepository authSecretTokenRepository;
    @Resource
    private OrderMappingRepository etOrderMappingRepo;
    @Resource
    private XhpcHistoryOrderRepository xhpcHistoryOrderRepository;
    @Resource
    private XhpcTerminalRepository xhpcTerminalRepository;
    @Resource
    private PileOrderService pileOrderService;
    @Resource
    private XhpcInternetUserRepository xhpcInternetUserRepository;
    @Resource
    private XhpcChargingStationRepository xhpcChargingStationRepository;

    private final ExecutorService executorService = Executors.newFixedThreadPool(20);
    /**
     * 请求启动充电
     * @param commonRequest
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/v40/query_start_charge")
    public CommonResponse queryStartCharge(@RequestBody CommonRequest<CWJStartChargeRequest> commonRequest) throws Exception {

        CommonResponse resp = new CommonResponse();
        resp.setRet(EvcsConst.RET_FAIL);
        CWJStartChargeRequest startChargeRequest = JSONUtil.readParams(commonRequest.getData(), CWJStartChargeRequest.class);
        String order ="";
        if (startChargeRequest == null) {
            resp.setMsg("Request or token params validation failed");
        } else {
            String startChargeSeq = startChargeRequest.getStartChargeSeq();
            EtOrderMapping orderMapping = etOrderMappingRepo.findByEvcsOrderNo(startChargeSeq).orElse(null);
            if (orderMapping != null) {
                resp.setMsg("Duplicated StartChargeSeq");
            } else {
                StartChargeResponse startChargeResponse = new StartChargeResponse();
                startChargeResponse.setFailReason(0);
                startChargeResponse.setSuccStat(1);
                startChargeResponse.setStartChargeSeqStat(4);
                String connectorId = startChargeRequest.getConnectorId();
                Map<String, Object> cacheGun = REDIS.getCacheMap("gun:".concat(connectorId));
                String terminalStatus = (String) cacheGun.get("vehicleGunStatus");
                String status = (String) cacheGun.get("status");
                EtOrderMapping etOrderMapping = new EtOrderMapping();
                Date now = DateUtils.getNowDate();
                etOrderMapping.setCreateTime(now);
                etOrderMapping.setEvcsOrderNo(startChargeSeq);
                if (!"空闲".equals(status)) {
                    resp.setMsg("终端状态异常:[".concat(status == null ? "未注册" : status).concat("]"));
                    emptyHorder(startChargeSeq, connectorId, etOrderMapping);
                } else if ("否".equals(terminalStatus)) {
                    resp.setMsg("未插枪");
                    emptyHorder(startChargeSeq, connectorId, etOrderMapping);
                } else {
                    Integer chargingAmt = (int) Math.round(startChargeRequest.getFeeLimit());
                    R res = pileOrderService.pileStartUpBy3rd(startChargeSeq, "",chargingAmt , "", -1, connectorId);
                    startChargeResponse.setStartChargeSeq(startChargeSeq);
                    startChargeResponse.setConnectorID(connectorId);
                    resp.setMsg(res.getMsg());
                    if (res.getCode() != 200) {
                        if (res.getCode() != 500) {
                            startChargeResponse.setFailReason(res.getCode());
                        } else {
                            startChargeResponse.setFailReason(3);
                        }
                        startChargeResponse.setFailReasonMsg(res.getMsg());
                        startChargeResponse.setSuccStat(1);
                        startChargeResponse.setStartChargeSeqStat(4);
                        emptyHorder(startChargeSeq, connectorId, etOrderMapping);
                    } else {
                        Map<String, Object> etOrderData = (Map<String, Object>) res.getData();
                        if (etOrderData != null) {
                            resp.setRet(EvcsConst.RET_SUCC);
                            startChargeResponse.setStartChargeSeqStat(1);
                            startChargeResponse.setSuccStat(0);
                            startChargeResponse.setFailReason(0);
                            Map<String, Object> pushOrder = new HashMap<>();
                            pushOrder.put("startChargeSeqStat", 1);
                            pushOrder.put("internetSerialNumber", startChargeRequest.getStartChargeSeq());
                            pushOrder.put("connectorID", connectorId);
                            pushOrder.put("startChargeNotificationStat", 0);
                            pushOrder.put("chargeOrderInfoNotificationStat", 0);
                            pushOrder.put("operatorId3rdpty", startChargeSeq.substring(0, 9));
                            pushOrder.put("startTime", etOrderData.get("startTime"));
                            String orderNo = (String) etOrderData.get("orderNo");
                            etOrderMapping.setXhOrderNo(orderNo);
                            REDIS.setCacheMap("pushOrder:".concat(orderNo), pushOrder);
                            order = orderNo;




                        } else {
                            emptyHorder(startChargeSeq, connectorId, etOrderMapping);
                        }
                    }
                }
                etOrderMappingRepo.save(etOrderMapping);
                resp.setData(JSONUtil.toJSONString(startChargeResponse));
                try {
                    notification(order);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

            }
        }
        return resp;
    }

    private void emptyHorder(String startChargeSeq, String connectorId, EtOrderMapping etOrderMapping) {

        final Long stationId = REDIS.getCacheMapValue("pile:".concat(connectorId.substring(0, 14)), "stationId");
        XhpcChargingStation xhpcChargingStation = xhpcChargingStationRepository.findById(stationId).orElse(null);
        if (xhpcChargingStation != null) {
            XhpcHistoryOrder emptyHorder = new XhpcHistoryOrder();
            emptyHorder.setTenantId(xhpcChargingStation.getTenantId());
            Date now = DateUtils.getNowDate();
            emptyHorder.setStartTime(now);
            emptyHorder.setEndTime(now);
            emptyHorder.setCreateTime(now);
            emptyHorder.setUpdateTime(now);
            emptyHorder.setStopReasonEvcs("平台停止");
            String sn = genOrder(connectorId);
            etOrderMapping.setXhOrderNo(sn);
            emptyHorder.setSerialNumber(sn);
            emptyHorder.setInternetSerialNumber(startChargeSeq);
            String operatorId3rdpty = startChargeSeq.substring(0, 9);
            emptyHorder.setOperatorId3rdptyEvcs(operatorId3rdpty);
            emptyHorder.setUserId(xhpcInternetUserRepository.queryDbId(operatorId3rdpty));
            emptyHorder.setType(1);
            emptyHorder.setSource(1);
            emptyHorder.setState(-1);
            emptyHorder.setChargingStationId(stationId);
            emptyHorder.setTerminalId(xhpcTerminalRepository.queryDbId(connectorId));
            emptyHorder.setConfirmResult(-1);
            xhpcHistoryOrderRepository.save(emptyHorder);
        }
    }


    private void notification(String orderNo) throws IOException {

        String pushOrderKey="pushOrder:"+orderNo;
        Map<String, Object> pushOrder = REDIS.getCacheMap(pushOrderKey);
        if (pushOrder.get("startChargeSeqStat") != null && (Integer) pushOrder.get("startChargeSeqStat") > 1) {
            //logger.info("===============启动推送============================"+pushOrderKey);
            Integer startChargeNotificationStat = (Integer) pushOrder.get("startChargeNotificationStat");
            if (null != startChargeNotificationStat && 1 != startChargeNotificationStat && startChargeNotificationStat <= 20) {
                String startChargeSeq = (String) pushOrder.get("internetSerialNumber");
                String operatorId = startChargeSeq.substring(0, 9);
                Optional<AuthSecretToken> authSecretToken =authSecretTokenRepository.findByOperatorId3irdptyAndSecretTokenType(operatorId,SECRET_TOKEN_TYPE_OUT);
                if (authSecretToken.isPresent()) {
                    NotificationStartChargeResultRequestData notificationStartChargeResultRequestData =
                            new NotificationStartChargeResultRequestData();
                    notificationStartChargeResultRequestData.setStartTime((String) pushOrder.get("startTime"));
                    notificationStartChargeResultRequestData.setStartChargeSeq(startChargeSeq);
                    notificationStartChargeResultRequestData.setConnectorId((String) pushOrder.get("connectorID"));
                    notificationStartChargeResultRequestData.setStartChargeSeqStat((Integer) pushOrder.get("startChargeSeqStat"));
                    notify(notificationStartChargeResultRequestData, authSecretToken.get(), pushOrderKey.substring(10));
                }
            }
        }
    }

    public void notify(NotificationStartChargeResultRequestData notificationStartChargeResultRequestData,
                       AuthSecretToken authSecretTokenOut, String orderNo) throws IOException {
        String data = JSONUtil.toJSONString(notificationStartChargeResultRequestData);
        System.out.println("==========车为家=====启动推送数据===========data============="+data);
        CommonRequest<NotificationStartChargeResultRequestData> commonRequest = new CommonRequest<>();
        commonRequest.setData(data);
        String responseBody = ok(commonRequest, "/notification_start_charge_result", authSecretTokenOut);
        System.out.println("==========车为家=====启动充电结果===========responseBody============="+responseBody);
        NotificationStartStopChargeResultResponse notificationStartStopChargeResultResponse =DTOJsonHelper.parseResponseData(responseBody,NotificationStartStopChargeResultResponse.class, authSecretTokenOut);
        if (null != notificationStartStopChargeResultResponse) {
            //Ensuring that only when startChargeNotificationStat equals 1 won't be notified.
            System.out.println("==========车为家=====启动充电结果===========notificationStartStopChargeResultResponse============="+notificationStartStopChargeResultResponse.toString());
            if (notificationStartStopChargeResultResponse.getSuccStat() == 0) {
                REDIS.setCacheMapValue("pushOrder:".concat(orderNo), "startChargeNotificationStat", 1);
            } else {
                Integer startChargeNotificationStat = REDIS.getCacheMapValue("pushOrder:".concat(orderNo),
                        "startChargeNotificationStat");
                if (startChargeNotificationStat == 0) {
                    startChargeNotificationStat = 2;
                } else {
                    ++startChargeNotificationStat;
                }
                REDIS.setCacheMapValue("pushOrder:".concat(orderNo), "startChargeNotificationStat",startChargeNotificationStat);
                throw new RuntimeException(String.format("push CD start charge order status [%s] failed: %s",notificationStartChargeResultRequestData.getStartChargeSeq(), responseBody));
            }
        }
    }
}
