package com.prolog.cs.biz.outbound.service.impl.faceorder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.prolog.cs.basic.common.model.BaseCommonDict;
import com.prolog.cs.biz.outbound.dao.FaceorderErrorLogMapper;
import com.prolog.cs.biz.outbound.dao.WmsFaceOrderMapper;
import com.prolog.cs.biz.outbound.model.OmsDoBillHDO;
import com.prolog.cs.biz.outbound.model.entity.FaceorderErrorLog;
import com.prolog.cs.biz.outbound.model.entity.WaveBillDDO;
import com.prolog.cs.biz.outbound.model.entity.WmsFaceOrder;
import com.prolog.cs.biz.outbound.model.vo.faceorder.FaceOrderAddVO;
import com.prolog.cs.biz.outbound.resource.CommonClient;
import com.prolog.cs.biz.outbound.utils.HttpClientUtils;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.utils.MapUtils;
import com.prolog.framework.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.conn.ConnectTimeoutException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public abstract class BaseFaceOrderHandler {

    @Autowired
    private CommonClient commonClient;
    @Autowired
    private WmsFaceOrderMapper wmsFaceOrderMapper;
    @Autowired
    private FaceorderErrorLogMapper faceorderErrorLogMapper;


    //获取请求面单入参
    public FaceOrderAddVO generateCreateFaceOrderParam(OmsDoBillHDO omsDoBillHDO, List<WaveBillDDO> waveBillDDOS,Integer count){
        FaceOrderAddVO faceOrderAddVO = new FaceOrderAddVO();
        String carrierCode = omsDoBillHDO.getCarrierCode();
        faceOrderAddVO.setCarrierCode(carrierCode);
        if("EMS".equals(carrierCode)){
            carrierCode = "EMSPROD";
            if(count == 1){
                faceOrderAddVO.setOneBillFlag("0");
                faceOrderAddVO.setOneBillNum("1");
            }else {
                faceOrderAddVO.setOneBillFlag("1");
                faceOrderAddVO.setOneBillNum(String.valueOf(count-1));
            }
            faceOrderAddVO.setBizProductNo("1");

        }
        if("YUNDA".equals(carrierCode)){
            carrierCode = "YUNDAPROD";
            faceOrderAddVO.setCarrierCode(carrierCode);
        }
        if("SF".equals(omsDoBillHDO.getCarrierCode())){
            RestMessage<List<BaseCommonDict>> restMessage = commonClient.getDictBasicListByCodes("CarrierConfig", null);
            if(restMessage == null || !restMessage.isSuccess() || restMessage.getData() == null || restMessage.getData().size() <= 0){
                throw new BizException("获取面单配置失败!");
            }
            List<BaseCommonDict> data = restMessage.getData();
            List<BaseCommonDict> commonDicts = data.stream().filter(item -> omsDoBillHDO.getCarrierCode().equals(item.getAttr3())).collect(Collectors.toList());
            if(commonDicts.isEmpty()){
                throw new BizException("承运商："+omsDoBillHDO.getCarrierCode()+"未配置面单参数!");
            }
            for (BaseCommonDict commonDict : commonDicts) {

                if(">=".equals(commonDict.getAttr1()) && omsDoBillHDO.getTotWeight().compareTo(new BigDecimal(commonDict.getAttr2())) >= 0){
                    faceOrderAddVO.setExpressTypeId(commonDict.getDictCode());
                    break;
                }

                if("<".equals(commonDict.getAttr1()) && omsDoBillHDO.getTotWeight().compareTo(new BigDecimal(commonDict.getAttr2())) < 0){
                    faceOrderAddVO.setExpressTypeId(commonDict.getDictCode());
                    break;
                }
            }

            faceOrderAddVO.setTotalNumber(count);

        }


        faceOrderAddVO.setPlatformNo(omsDoBillHDO.getBillno());
//        faceOrderAddVO.setPlatformNo("ZJ"+ ThreadLocalRandom.current().nextInt(100000));
        FaceOrderAddVO.SenderAddressBean senderAddressBean = new FaceOrderAddVO.SenderAddressBean();
        senderAddressBean.setProvince("江西省");
        senderAddressBean.setCity("赣州市");
        senderAddressBean.setArea("经济技术开发区");
        senderAddressBean.setTown("金潭大道");
        senderAddressBean.setAddressDetail("江西省章贡区赣州市经济技术开发区金潭大道青牛医药5G智慧云仓");
        senderAddressBean.setSenderName("青牛医药");
        senderAddressBean.setDelivererContact("青牛医药");
        senderAddressBean.setDelivererContactTel("07977302078");
        faceOrderAddVO.setSenderAddress(senderAddressBean);

        if("DBL".equals(carrierCode)){
            faceOrderAddVO.setOrderType("2");
            faceOrderAddVO.setTransportType("PACKAGE");
            faceOrderAddVO.setTotalNumber(count);
            faceOrderAddVO.setTotalWeight(omsDoBillHDO.getTotWeight() == null ? null : omsDoBillHDO.getTotWeight().doubleValue());
            faceOrderAddVO.setTotalVolume(omsDoBillHDO.getTotVolume() == null ? null : omsDoBillHDO.getTotVolume().doubleValue());

        }

        FaceOrderAddVO.ReceiverAddressBean receiverAddressBean = new FaceOrderAddVO.ReceiverAddressBean();
        if(!"SF".equals(carrierCode)){
            receiverAddressBean.setReceiveProvinceName(omsDoBillHDO.getReceiveProvinceName());
            receiverAddressBean.setReceiveCityName(omsDoBillHDO.getReceiveCityName());
            receiverAddressBean.setReceiveDistrictName(omsDoBillHDO.getReceiveDistrictName());
            receiverAddressBean.setReceiveTownName(omsDoBillHDO.getReceiveTownName());
        }

        receiverAddressBean.setReceiveAddress(omsDoBillHDO.getReceiveAddress());
        receiverAddressBean.setReceiverName(omsDoBillHDO.getCustPerson());
        receiverAddressBean.setReceiveContact(omsDoBillHDO.getCustPerson());
        receiverAddressBean.setReceiveContactTel(omsDoBillHDO.getCustPersonTel());
        faceOrderAddVO.setReceiverAddress(receiverAddressBean);

        List<FaceOrderAddVO.CargoDetailListBean> cargoDetailListBeans = new ArrayList<>();
        for (WaveBillDDO waveBillDDO : waveBillDDOS) {
            FaceOrderAddVO.CargoDetailListBean cargoDetailListBean = new FaceOrderAddVO.CargoDetailListBean();
//            cargoDetailListBean.setName(waveBillDDO.getItemName());
            cargoDetailListBean.setName("药品");
            cargoDetailListBean.setCount(count);

            cargoDetailListBeans.add(cargoDetailListBean);
        }

        faceOrderAddVO.setCargoDetailList(cargoDetailListBeans);

        faceOrderAddVO.setLastFlag(String.valueOf(omsDoBillHDO.getAttrNum1()));

        return faceOrderAddVO;
    }

    //获取请求面单url
    abstract String getUrl();

    /**
     * 请求接口平台
     * @return
     */
    public JSONObject sendRequest(FaceOrderAddVO vo){
        String url = getUrl();
        log.info("请求创建面单url：{}", JSON.toJSONString(url));
        String param = JSON.toJSONString(vo);
        log.info("请求创建面单param：{}", param);
        JSONObject result = null;
        try {
            result = HttpClientUtils.postByJson(url, param);
        }catch (Exception e){
            //如果是链接超时，则再重新请求一次
            if(e.getClass().isInstance(ConnectTimeoutException.class)){
                //重试次数
                int times ;
                RestMessage<List<BaseCommonDict>> restMessage = commonClient.getDictBasicListByCodes("face_order_retry_times", null);
                if(restMessage == null || !restMessage.isSuccess() || restMessage.getData() == null || restMessage.getData().size() <= 0){
                    times = 1;
                }else {
                    times = Integer.parseInt(restMessage.getData().get(0).getAttr1());
                }
                for (int i = 0; i < times; i++) {
                    try {
                        result = HttpClientUtils.postByJson(url, param);
                        break;
                    }catch (Exception e2){
                        e2.printStackTrace();
                        result = new JSONObject();
                        result.put("success",false);
                        result.put("msg",false);
                    }
                }

            }
        }

        //判断错误码是否需要重试
        RestMessage<List<BaseCommonDict>> restMessage = commonClient.getDictBasicListByCodes("face_order_error_code", null);
        if(restMessage == null || !restMessage.isSuccess() || restMessage.getData() == null || restMessage.getData().size() <= 0){
            return result;
        }
        List<BaseCommonDict> baseCommonDicts = restMessage.getData();
        BaseCommonDict baseCommonDict = baseCommonDicts.stream().filter(item -> item.getDictCode().equals(vo.getCarrierCode())).findFirst().orElse(null);
        if(baseCommonDict == null){
            return result;
        }
        Object code = result.get("code");
        String errorCode = String.valueOf(code);
        if(Arrays.asList(baseCommonDict.getAttr1().split(",")).contains(errorCode)){
            //重试次数
            int times ;
            RestMessage<List<BaseCommonDict>> retryTimes = commonClient.getDictBasicListByCodes("face_order_retry_times", null);
            if(retryTimes == null || !retryTimes.isSuccess() || retryTimes.getData() == null || retryTimes.getData().size() <= 0){
                times = 1;
            }else {
                times = Integer.parseInt(retryTimes.getData().get(0).getAttr1());
            }
            for (int i = 0; i < times; i++) {
                try {
                    result = HttpClientUtils.postByJson(url, param);
                    break;
                }catch (Exception e2){
                    e2.printStackTrace();
                    result = new JSONObject();
                    result.put("success",false);
                    result.put("msg",false);
                }
            }
        }
        log.info("请求创建面单返回结果：{}",JSON.toJSONString(result));
//        return JSON.parseObject(result.toJSONString(), RestMessage.class);
        Boolean success = (Boolean) result.get("success");
        String result_str = JSON.toJSONString(result);
        if(!success){
            new Thread(()-> {

                log.error("获取面单失败：{}");
                saveErrorlog(url,vo,result_str,vo.getLastFlag());
            }).start();
        }
        return result;
    }

    /**
     * 获取请求地址
     * @return
     */
    public List<BaseCommonDict> getRequestUrls(){
        RestMessage<List<BaseCommonDict>> restMessage = commonClient.getDictBasicListByCodes("CREATE_FACE_ORDER_URL", null);
        if(restMessage == null || !restMessage.isSuccess() || restMessage.getData() == null || restMessage.getData().size() <= 0){
            throw new BizException("获取创建面单请求url列表失败!");
        }

        return restMessage.getData();
    }

    /**
     * 转换成对象
     * @param result
     * @return
     */
    public abstract List<WmsFaceOrder> convertResult(JSONObject result);

    /**
     * 保存面单
     * @param wmsFaceOrders
     */
    public void saveWmsFaceOrder(List<WmsFaceOrder> wmsFaceOrders){
        if(wmsFaceOrders == null || wmsFaceOrders.size() <= 0){
            throw new BizException("获取面单失败!");
        }
        String billNo = wmsFaceOrders.get(0).getBillNo();
        List<WmsFaceOrder> faceOrders = wmsFaceOrderMapper.findByMap(MapUtils.put("billNo", billNo).getMap(), WmsFaceOrder.class);
        if(faceOrders != null && faceOrders.size() > 0){
            List<String> extWaybillCodes = faceOrders.stream().map(WmsFaceOrder::getWaybillCode).collect(Collectors.toList());
            wmsFaceOrders = wmsFaceOrders.stream().filter(item -> !extWaybillCodes.contains(item.getWaybillCode())).collect(Collectors.toList());
        }
        if(wmsFaceOrders == null || wmsFaceOrders.size() <= 0){
            throw new BizException("面单号重复!");
        }
        wmsFaceOrderMapper.saveBatch(wmsFaceOrders);
    }

    /**
     * 获取面单
     * @param omsDoBillHDO
     * @param waveBillDDOS
     * @return
     */
    public List<String> getFaceOrderNo(OmsDoBillHDO omsDoBillHDO, List<WaveBillDDO> waveBillDDOS,Integer count){
        FaceOrderAddVO vo = generateCreateFaceOrderParam(omsDoBillHDO,waveBillDDOS,count);
        JSONObject result  = sendRequest(vo);

        List<String> wayBillNos = new ArrayList<>();
        List<WmsFaceOrder> wmsFaceOrders = convertResult(result);
//        WmsFaceOrder wmsFaceOrder = new WmsFaceOrder();
//        wmsFaceOrder.setWaybillCode("WB"+ThreadLocalRandom.current().nextInt(100000));
        for (WmsFaceOrder wmsFaceOrder : wmsFaceOrders) {
            wmsFaceOrder.setId(UUIDUtils.generateWithoutSeperator());
            wmsFaceOrder.setBillNo(omsDoBillHDO.getBillno());
            wmsFaceOrder.setSenderName(vo.getSenderAddress().getSenderName());
            wmsFaceOrder.setSenderAddress(vo.getSenderAddress().getAddressDetail());
            wmsFaceOrder.setSenderMobile(vo.getSenderAddress().getDelivererContactTel());
            wmsFaceOrder.setReceiverName(vo.getReceiverAddress().getReceiverName());
            wmsFaceOrder.setReceiverAddress(vo.getReceiverAddress().getReceiveAddress());
            wmsFaceOrder.setReceiverMobile(vo.getReceiverAddress().getReceiveContactTel());
            wayBillNos.add(wmsFaceOrder.getWaybillCode());
        }
        saveWmsFaceOrder(wmsFaceOrders);
        return wayBillNos;
    }

    private void saveErrorlog(String url,FaceOrderAddVO vo,String result,String lastFlag){
        FaceorderErrorLog faceorderErrorLog = new FaceorderErrorLog();
        faceorderErrorLog.setId(UUIDUtils.generateWithoutSeperator());
        faceorderErrorLog.setBillno(vo.getPlatformNo());
        faceorderErrorLog.setCarrierCode(vo.getCarrierCode());
        faceorderErrorLog.setRequestUrl(url);
        faceorderErrorLog.setRequestParam(JSON.toJSONString(vo));
        faceorderErrorLog.setRequestResult(result);
        faceorderErrorLog.setAttrStr1(lastFlag);

        faceorderErrorLog.setCreator("SYS");
        faceorderErrorLog.setGmtCreate(new Date());
        faceorderErrorLogMapper.save(faceorderErrorLog);
    }

}
