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.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 java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import static com.xhpc.common.data.redis.StaticBeanUtil.REDIS;
import static com.xhpc.pp.logic.RealtimeDataLogic.calcem;
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;

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

        Map<String, Object> req = sp.getParameters();
        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", "已结束");
        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);
        Long rdtime = (Long) cacheOrder.get("rdtime");
        Map<String, Object> cachePile = REDIS.getCacheMap("pile:".concat(orderData.getPileNo()));
        if (cachePile.get("version").equals("0B")) {
            final String hex = orderData.getHex();
            String cdhex = hex.substring(0xA2 * 2 + 4, hex.length() - 4);
            if (cdhex.length() > 0) {
                cacheOrder.put("em2", calcem(cdhex));
                REDIS.setCacheMap(orderkey, cacheOrder);
            }
        }
        String resultStr =
                "6815".concat(req.get("seqhex").toString()).concat("0040").concat(orderNo).concat(ServiceResult.HEX_00);
        resultStr = resultStr.concat(CRCCalculator.calcCrc(resultStr));
        if (orderNo.equals("00000000000000000000000000000000")) {
            return new ServiceResult(HexUtils.toBytes(resultStr), ServiceResult.OK);
        }
        final R r = pileOrderService.pileEndOrder(orderNo);
        if (r.getCode() == 200)
            return new ServiceResult(HexUtils.toBytes(resultStr), ServiceResult.OK);
        else
            return new ServiceResult(ServiceResult.FAIL);
    }

    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);
    }

}
