package com.xhpc.pp.logic;

import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xhpc.common.api.PileOrderService;
import com.xhpc.common.core.domain.R;
import com.xhpc.common.data.redis.CacheOrderData;
import com.xhpc.common.data.up.OrderData;
import com.xhpc.common.enums.StationDeviceEnum;
import com.xhpc.pp.domain.XhpcDeviceMessage;
import com.xhpc.pp.mapper.XhpcDeviceMessageMapper;
import com.xhpc.pp.tx.ServiceParameter;
import com.xhpc.pp.tx.ServiceResult;
import com.xhpc.pp.tx.logic.ServiceLogic;
import com.xhpc.pp.utils.HexUtils;
import com.xhpc.pp.utils.security.CRCCalculator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import static com.xhpc.common.data.redis.StaticBeanUtil.REDIS;
import static com.xhpc.pp.logic.RealtimeDataLogic.calcem2;
import static com.xhpc.pp.utils.security.CacheDataUtils.reflectTranslate;

@Lazy
@Component("OrderDataLogic")
public class OrderDataLogic implements ServiceLogic {

    private static final Logger log = LoggerFactory.getLogger(OrderDataLogic.class);

    @Autowired
    private PileOrderService pileOrderService;
    @Resource
    XhpcDeviceMessageMapper deviceMessageMapper;
    private static Map<String, String> SM = new HashMap<>();

    static {
        SM.put("40", "APP 远程停止");
        SM.put("41", "SOC 达到 100%");
        SM.put("42", "充电电量满足设定条件");
        SM.put("43", "充电金额满足设定条件");
        SM.put("44", "充电时间满足设定条件");
        SM.put("45", "手动停止充电");
        SM.put("72", "急停按钮停止充电(0X72)");
        SM.put("91", "平台结算(0X91)");
    }

    @Override
    public ServiceResult service(ServiceParameter sp) throws Exception {

        Map<String, Object> req = sp.getParameters();
        //log.info("================订单结束报文==============================");
        //log.info("================订单结束报文================req=============="+req.toString());
        //log.info("================订单结束报文==============================");
        ObjectMapper objectMapper = new ObjectMapper();
        OrderData orderData = objectMapper.convertValue(req, OrderData.class);
        String orderNo = orderData.getOrderNo();
        String orderkey = "order:".concat(orderNo);
        Map<String, Object> cacheOrder = REDIS.getCacheMap(orderkey);
        CacheOrderData cacheOrderData = translate(orderData);
        Integer startSoc = (Integer) cacheOrder.get("startSoc");
        cacheOrderData.setStartSoc(startSoc == null ? 0 : startSoc);
        cacheOrderData.setEndSoc((Integer) cacheOrder.get("endSoc"));
        cacheOrderData.setStatus(1);
        cacheOrderData.setCreateTime(DateUtil.now());
        cacheOrder.put("orderData", cacheOrderData);
        cacheOrder.put("status", "已结束");
        cacheOrder.put("stopReason", translate(cacheOrderData.getStopReason()));
        cacheOrder.put("stopReasonHex", cacheOrderData.getStopReason());
        cacheOrder.put("stopTime", cacheOrderData.getEndTime());
        REDIS.setCacheMap(orderkey, cacheOrder);
        String gunkey = "gun:".concat(orderData.getPileNo()).concat(orderData.getGunId());
        Map<String, Object> cacheGun = REDIS.getCacheMap(gunkey);
        cacheGun.put("orderstoptime", cacheOrderData.getEndTime());
        cacheGun.put("orderkey", null);
        REDIS.setCacheMap(gunkey, cacheGun);
        Map<String, Object> cachePile = REDIS.getCacheMap("pile:".concat(orderData.getPileNo()));
        if (cachePile.get("version").equals("0C")) {
            final String hex = orderData.getHex();
            String cdhex = hex.substring(0xA2 * 2 + 4, hex.length() - 4);
            if (cdhex.length() > 0) {
                cacheOrder.put("em2", calcem2(cdhex));
                REDIS.setCacheMap(orderkey, cacheOrder);
            }
        }

        R r = null;
        if (!orderNo.equals("00000000000000000000000000000000")) r = pileOrderService.pileEndOrder(orderNo);
        if (orderNo.equals("00000000000000000000000000000000") || (r != null && r.getMsg() != null && r.getMsg().contains("无效订单"))) {
            log.error(">>INVALID order [{}] detected. MUST check the system or [{}].<<", orderNo, gunkey);
        }

        XhpcDeviceMessage deviceMessage = new XhpcDeviceMessage();
        deviceMessage.setType(StationDeviceEnum.PILE.getCode());
        deviceMessage.setSerialNumber(sp.getPileNo());
        deviceMessage.setRemark("充电交易结算记录");
        deviceMessage.setStatus(0);
        deviceMessage.setContent((String) req.get("hex"));
        deviceMessage.setChargeOrderNo((String) req.get("orderNo"));
        deviceMessageMapper.insertByDomain(deviceMessage);
        String seq =(String) req.get("hex");
        String resultStr = "6815".concat(seq.substring(4,8)).concat("0040").concat(orderNo);
        if ((r != null && r.getCode() == 200) || (r != null && r.getMsg() != null && r.getMsg().contains("重复结算"))) {
            resultStr = resultStr.concat(ServiceResult.HEX_00);
            resultStr = resultStr.concat(CRCCalculator.calcCrc(resultStr));
            return new ServiceResult(HexUtils.toBytes(resultStr), ServiceResult.OK);
        } else {
            resultStr = resultStr.concat(ServiceResult.HEX_00);
            resultStr = resultStr.concat(CRCCalculator.calcCrc(resultStr));
            return new ServiceResult(HexUtils.toBytes(resultStr), ServiceResult.FAIL);
        }
    }

    private String translate(String stopReason) {

        String sr = SM.get(stopReason);
        if (sr == null) {
            final Integer stopReasonInt = Integer.valueOf(stopReason, 16);
            if (stopReasonInt <= 0x49) {
//            if (stopReasonInt >= 0x40 && stopReasonInt <= 0x49) { // todo wi lh 0x40?
                sr = "充电完成(0X".concat(stopReason).concat(")");
            } else if (stopReasonInt <= 0x69) {
                sr = "充电启动失败(0X".concat(stopReason).concat(")");
            } else if (stopReasonInt < 0x90) {
                sr = "充电异常中止(0X".concat(stopReason).concat(")");
            } else if (stopReasonInt == 0x90) {
                sr = "未知原因中止(0X".concat(stopReason).concat(")");
            } else {
                sr = "未知原因中止(UC_0X".concat(stopReason).concat(")");
            }
        }
        return sr;
//        }
    }

    private CacheOrderData translate(OrderData orderData) throws InvocationTargetException, IllegalAccessException,
            InstantiationException {

        Class<CacheOrderData> codclz = CacheOrderData.class;
        Class<OrderData> odclz = OrderData.class;
        Field[] codfields = codclz.getDeclaredFields();
        return (CacheOrderData) reflectTranslate(orderData, codclz, odclz, codfields);
    }

    public static void main(String[] args) {
        Integer stopReasonInt = Integer.valueOf("72", 16);
        System.out.println(stopReasonInt);
        String st ="充电完成(0X".concat("72").concat(")");
        System.out.println("==========st==========="+st);
    }
}
