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.dto.FaceOrderPickTaskDDTO;
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 org.springframework.web.context.request.RequestContextHolder;
import springfox.documentation.spring.web.json.Json;

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 KyBaseFaceOrderHandler {

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

    abstract String generateCreateFaceOrderParam(OmsDoBillHDO omsDoBillHDO, List<FaceOrderPickTaskDDTO> list, List<WaveBillDDO> waveBillDDOS,Integer count);

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

    /**
     * 请求接口平台
     * @return
     */
    public JSONObject sendRequest(String param){
        String url = getUrl();
        log.info("请求创建面单url：{}", JSON.toJSONString(url));
        //String param = JSON.toJSONString(param);
        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);
                    }
                }

            }
        }

        log.info("请求创建面单返回结果：{}",JSON.toJSONString(result));
        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,OmsDoBillHDO omsDoBillHDO);

    /**
     * 保存面单
     * @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<FaceOrderPickTaskDDTO> list, List<WaveBillDDO> waveBillDDOS,Integer count){
        log.info("获取面单承运商："+omsDoBillHDO.getCarrierCode());
        String param = generateCreateFaceOrderParam(omsDoBillHDO,list, waveBillDDOS, count);
        JSONObject result  = sendRequest(param);

        Boolean success = (Boolean) result.get("success");
        if(success == null || !success){
            String result_str = JSON.toJSONString(result);
            new Thread(()-> {

                try {
                    saveErrorlog(getUrl(),omsDoBillHDO.getBillno(),omsDoBillHDO.getCarrierCode(),param,result_str,omsDoBillHDO.getAttrNum1());
                }catch (Exception e) {
                    log.error("保存面单获取失败日志失败：{}", e.getMessage());
                }
            }).start();

            //判断错误码是否需要重试
            RestMessage<List<BaseCommonDict>> restMessage = commonClient.getDictBasicListByCodes("face_order_error_code", null);
            log.info("查询面单错误码通用参照：{}",JSON.toJSONString(restMessage));
            if(restMessage != null && restMessage.isSuccess() && restMessage.getData() != null && restMessage.getData().size() > 0){
                List<BaseCommonDict> baseCommonDicts = restMessage.getData();
                BaseCommonDict baseCommonDict = baseCommonDicts.stream().filter(item -> item.getDictCode().equals(omsDoBillHDO.getCarrierCode())).findFirst().orElse(null);
                if(baseCommonDict != null){
                    String errorCode;
                    if("JD".equals(omsDoBillHDO.getCarrierCode())){
                        JSONObject error_response = result.getJSONObject("error_response");
                        if(error_response != null){
                            errorCode = String.valueOf(error_response.get("code"));
                        }else {
                            errorCode = String.valueOf(result.get("code"));
                        }

                    }else {
                        errorCode = String.valueOf(result.get("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(getUrl(), param);
                                break;
                            }catch (Exception e2){
                                e2.printStackTrace();
                                result = new JSONObject();
                                result.put("success",false);
                                result.put("msg",false);
                            }
                        }
                    }
                }

            }
        }


        List<String> wayBillNos = new ArrayList<>();
        List<WmsFaceOrder> wmsFaceOrders = convertResult(result,omsDoBillHDO);
        log.info("保存数据：{}", JSONObject.toJSONString(wmsFaceOrders));
//        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("青牛医药");
            wmsFaceOrder.setSenderAddress("江西省赣州市章贡区经济技术开发区凤凰路7号");
            wmsFaceOrder.setSenderMobile("4009158120");
            wmsFaceOrder.setReceiverName(omsDoBillHDO.getCustPerson());
            wmsFaceOrder.setReceiverAddress(omsDoBillHDO.getReceiveAddress());
            wmsFaceOrder.setReceiverMobile(omsDoBillHDO.getCustPersonTel());
            wayBillNos.add(wmsFaceOrder.getWaybillCode());
        }
        saveWmsFaceOrder(wmsFaceOrders);
        return wayBillNos;
    }

    private void saveErrorlog(String url, String billno, String carrierCode, String param, String result, BigDecimal lastFlag) {
        FaceorderErrorLog faceorderErrorLog = new FaceorderErrorLog();
        faceorderErrorLog.setId(UUIDUtils.generateWithoutSeperator());
        faceorderErrorLog.setBillno(billno);
        faceorderErrorLog.setCarrierCode(carrierCode);
        faceorderErrorLog.setRequestUrl(url);
        faceorderErrorLog.setRequestParam(param);
        faceorderErrorLog.setRequestResult(result);
        faceorderErrorLog.setAttrStr1(String.valueOf(lastFlag));

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

