package com.liquidnet.client.admin.zhengzai.kylin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.client.admin.common.utils.StringUtils;
import com.liquidnet.client.admin.zhengzai.kylin.utils.DataUtils;
import com.liquidnet.client.admin.zhengzai.kylin.utils.ShunfengSignUtils;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dao.*;
import com.liquidnet.service.kylin.dto.param.*;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressRouteVo;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.*;
import com.liquidnet.service.kylin.service.IKylinOrderExpress;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 演出 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-05
 */
@Service
@Slf4j
public class PerformancesExpressServiceImpl extends ServiceImpl<KylinOrderExpressMapper, KylinOrderExpress> implements IKylinOrderExpress {

    @Value("${liquidnet.shunfeng.custid}")
    private String custid;
    @Value("${liquidnet.shunfeng.jCompany}")
    private String jCompany;
    @Value("${liquidnet.shunfeng.jContact}")
    private String jContact;
    @Value("${liquidnet.shunfeng.jTel}")
    private String jTel;
    @Value("${liquidnet.shunfeng.jProvince}")
    private String jProvince;
    @Value("${liquidnet.shunfeng.jCity}")
    private String jCity;
    @Value("${liquidnet.shunfeng.jAddress}")
    private String jAddress;
    @Value("${liquidnet.shunfeng.expressType}")
    private Integer expressType;
    @Value("${liquidnet.shunfeng.depositumInfo}")
    private String depositumInfo;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    private ShunfengSignUtils shunfengSignUtils;

    @Autowired
    private KylinPerformancesMapper performancesMapper;

    @Autowired
    private KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    private KylinOrderExpressMapper kylinOrderExpressMapper;

    @Autowired
    private KylinOrderExpressFeeInfoMapper kylinOrderExpressFeeInfoMapper;

    @Autowired
    private KylinOrderExpressRouteMapper kylinOrderExpressRouteMapper;

    @Autowired
    private DataUtils dataUtils;

    public List<PerformanceExpressPerformanceListAdminDao> getPerformancesList(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<PerformanceExpressPerformanceListAdminDao> voList = new ArrayList();
        try {
            Map<String, Object> map = BeanUtil.convertBeanToMap(performanceExpressSearchAdminParam);
            voList = performancesMapper.performanceExpressPerformanceList(map);
            if (!CollectionUtil.isEmpty(voList)) {
                for (PerformanceExpressPerformanceListAdminDao info : voList) {
                    PerformanceExpressPerformanceListAdminDao countInfo = performancesMapper.countExpressNumber(info.getPerformancesId());
                    if (null != countInfo) {
                        info.setTotalNumber(countInfo.getTotalNumber());
                        info.setTotal1(countInfo.getTotal1());
                        info.setTotal2(countInfo.getTotal2());
                        info.setTotal3(countInfo.getTotal3());
                    }
                }
            }
        } catch (Exception e) {
        }
        return voList;
    }

    public List<PerformanceExpressPerformanceOrderListAdminDao> getPerformancesOrderList(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<PerformanceExpressPerformanceOrderListAdminDao> voList = new ArrayList();
        try {
            Map<String, Object> map = BeanUtil.convertBeanToMap(performanceExpressSearchAdminParam);
            voList = kylinOrderTicketsMapper.performanceExpressPerformanceOrderList(map);
        } catch (Exception e) {
        }
        return voList;
    }

    public ResponseDto placeOrder(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<String> ids = performanceExpressSearchAdminParam.getIds();
        for (String orderTicketsId : ids) {
            // 已经存在未取消的下单数据过滤掉
            Integer[] expressStatus = {KylinTableStatusConst.ORDER_EXPRESS_STATUS1, KylinTableStatusConst.ORDER_EXPRESS_STATUS3};
            KylinOrderExpress orderExpressInfo = kylinOrderExpressMapper.selectOne(
                    new QueryWrapper<KylinOrderExpress>().eq("order_tickets_id", orderTicketsId)
                            .notIn("express_status", expressStatus)
            );
            if (null != orderExpressInfo) {
                continue;
            }
            KylinOrderTickets orderInfo = kylinOrderTicketsMapper.selectOne(
                    new QueryWrapper<KylinOrderTickets>().eq("order_tickets_id", orderTicketsId)
            );
            // 生成预快递单 防止因失败没办法再次发起也不能主动获取数据
            KylinOrderExpress kylinOrderExpressPre = new KylinOrderExpress();
            String orderExpressId = IDGenerator.nextSnowId();
            kylinOrderExpressPre.setExpressStatus(KylinTableStatusConst.ORDER_EXPRESS_STATUS1);
            kylinOrderExpressPre.setOrderExpressId(orderExpressId);
            kylinOrderExpressPre.setOrderTicketsId(orderTicketsId);
            // 防止重复前面加上 "NEW" 因取消后再发起订单号也不能一致所有后面做补位操作
            Integer placeCount = kylinOrderExpressMapper.selectCount(
                    new QueryWrapper<KylinOrderExpress>()
                            .eq("order_tickets_id", orderTicketsId)
            );
            String codeNum = StringUtils.leftPad(String.valueOf(placeCount), 3, "0");
            String OrderExpressCode = "NEW" + orderInfo.getOrderCode().concat(codeNum);
            kylinOrderExpressPre.setOrderExpressCode(OrderExpressCode);
            kylinOrderExpressPre.setExpressType(expressType);
            kylinOrderExpressPre.setCreatedAt(DateUtil.getNowTime());
            kylinOrderExpressMapper.insert(kylinOrderExpressPre);

            // 请求下单数据
            HashMap<String, Object> hBody = new HashMap<>();
            hBody.put("custid", custid);
            hBody.put("jCompany", jCompany);
            hBody.put("jContact", jContact);
            hBody.put("jTel", jTel);
            hBody.put("jProvince", jProvince);
            hBody.put("jCity", jCity);
            hBody.put("jAddress", jAddress);

            // TODO: 2021/6/30 前端选择
            hBody.put("payMethod", 0);// 运费付款方式：0-寄付月结；1-寄付现结；2-收方付；3-第三方付；
            hBody.put("expressType", expressType);// 顺丰特快

            hBody.put("depositumInfo", depositumInfo);

            hBody.put("orderId", OrderExpressCode);

            hBody.put("depositumNo", orderInfo.getNumber());

            hBody.put("dContact", orderInfo.getExpressContacts());
            hBody.put("dMobile", orderInfo.getExpressPhone());
            hBody.put("dAddress", orderInfo.getExpressAddress());

            // 生成签名并请求
            String result = shunfengSignUtils.generateSignatureAndRequest(hBody, "/public/order/v1/placeOrder");
            HashMap hashMap = JsonUtils.fromJson(result, HashMap.class);
            System.out.println(result);
            if (hashMap.get("succ").equals("fail")) {
                String msg = (String) hashMap.get("msg");
                return ResponseDto.failure(msg);
            } else {
                HashMap hashMapResult = (HashMap) hashMap.get("result");
                KylinOrderExpress kylinOrderExpress = new KylinOrderExpress();
                kylinOrderExpress.setExpressStatus(KylinTableStatusConst.ORDER_EXPRESS_STATUS2);
                kylinOrderExpress.setMailno((String) hashMapResult.get("mailno"));
                kylinOrderExpress.setFilterResult(hashMapResult.get("filter_result").toString());
                kylinOrderExpress.setRemark((String) hashMapResult.get("remark"));
                kylinOrderExpress.setOrigincode((String) hashMapResult.get("origincode"));
                kylinOrderExpress.setDestcode((String) hashMapResult.get("destcode"));
                kylinOrderExpress.setPrintIcon((String) hashMapResult.get("printIcon"));
                kylinOrderExpress.setPrintFlag((String) hashMapResult.get("printFlag"));
                kylinOrderExpress.setTwoDimensionCode((String) hashMapResult.get("twoDimensionCode"));
                kylinOrderExpress.setUpdatedAt(DateUtil.getNowTime());
                kylinOrderExpressMapper.update(
                        kylinOrderExpress
                        , new UpdateWrapper<KylinOrderExpress>().in("order_express_id", orderExpressId)
                );

                KylinOrderExpressVo kylinOrderExpressVo = new KylinOrderExpressVo();
                BeanUtils.copyProperties(kylinOrderExpressPre, kylinOrderExpressVo);
                kylinOrderExpressVo.setMailno(kylinOrderExpress.getMailno());
                kylinOrderExpressVo.setExpressStatus(kylinOrderExpress.getExpressStatus());
                dataUtils.setOrderExpressInfo(orderTicketsId, kylinOrderExpressVo);
            }
        }
        return ResponseDto.success();
    }

    public ResponseDto cancelOrder(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<String> ids = performanceExpressSearchAdminParam.getIds();
        Integer[] expressStatus = {KylinTableStatusConst.ORDER_EXPRESS_STATUS1, KylinTableStatusConst.ORDER_EXPRESS_STATUS3};
        for (String orderTicketsId : ids) {
            KylinOrderExpress orderExpressInfo = kylinOrderExpressMapper.selectOne(
                    new QueryWrapper<KylinOrderExpress>().eq("order_tickets_id", orderTicketsId)
                            .notIn("express_status", expressStatus)
            );
            if (null != orderExpressInfo) {
                HashMap<String, Object> hBody = new HashMap<>();
                hBody.put("orderId", orderExpressInfo.getOrderExpressCode());

                // 生成签名并请求
                String result = shunfengSignUtils.generateSignatureAndRequest(hBody, "/public/order/v1/cancelOrder");
                HashMap hashMap = JsonUtils.fromJson(result, HashMap.class);
                System.out.println(result);
                if (hashMap.get("succ").equals("fail")) {
                    String msg = (String) hashMap.get("msg");
                    return ResponseDto.failure(msg);
                } else {
                    KylinOrderExpress kylinOrderExpress = new KylinOrderExpress();
                    kylinOrderExpress.setExpressStatus(KylinTableStatusConst.ORDER_EXPRESS_STATUS3);
                    kylinOrderExpress.setUpdatedAt(DateUtil.getNowTime());
                    kylinOrderExpressMapper.update(
                            kylinOrderExpress
                            , new UpdateWrapper<KylinOrderExpress>().in("order_express_id", orderExpressInfo.getOrderExpressId())
                    );
                    dataUtils.delOrderExpressInfo(orderTicketsId);
                    mongoTemplate.remove(Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)), KylinOrderExpressRouteVo.class.getSimpleName());

                }
            }
        }
        return ResponseDto.success();
    }

    public ResponseDto getResult(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<String> ids = performanceExpressSearchAdminParam.getIds();
        Integer[] expressStatus = {KylinTableStatusConst.ORDER_EXPRESS_STATUS1, KylinTableStatusConst.ORDER_EXPRESS_STATUS3};
        for (String orderTicketsId : ids) {
            KylinOrderExpress orderExpressInfo = kylinOrderExpressMapper.selectOne(
                    new QueryWrapper<KylinOrderExpress>().eq("order_tickets_id", orderTicketsId)
                            .notIn("express_status", expressStatus)
            );
            if (null != orderExpressInfo) {
                HashMap<String, Object> hBody = new HashMap<>();
                hBody.put("orderId", orderExpressInfo.getOrderExpressCode());
                hBody.put("searchType", 1); //查询类型：1,正向单查询，传入的orderid为正向定单号，2，退货单查询，传入的orderid为退货原始订单号

                // 生成签名并请求
                String result = shunfengSignUtils.generateSignatureAndRequest(hBody, "/public/order/v1/getResult");
                HashMap hashMap = JsonUtils.fromJson(result, HashMap.class);
                System.out.println(result);
                if (hashMap.get("succ").equals("fail")) {
                    String msg = (String) hashMap.get("msg");
                    return ResponseDto.failure(msg);
                } else {
                    HashMap hashMapResult = (HashMap) hashMap.get("result");
                    KylinOrderExpress kylinOrderExpress = new KylinOrderExpress();
                    kylinOrderExpress.setExpressStatus(KylinTableStatusConst.ORDER_EXPRESS_STATUS2);
                    kylinOrderExpress.setMailno((String) hashMapResult.get("mailno"));
                    kylinOrderExpress.setFilterResult(hashMapResult.get("filter_result").toString());
                    kylinOrderExpress.setRemark((String) hashMapResult.get("remark"));
                    kylinOrderExpress.setOrigincode((String) hashMapResult.get("origincode"));
                    kylinOrderExpress.setDestcode((String) hashMapResult.get("destcode"));
                    kylinOrderExpress.setPrintIcon((String) hashMapResult.get("printIcon"));
                    kylinOrderExpress.setPrintFlag((String) hashMapResult.get("printFlag"));
                    kylinOrderExpress.setTwoDimensionCode((String) hashMapResult.get("twoDimensionCode"));
                    kylinOrderExpress.setUpdatedAt(DateUtil.getNowTime());
                    kylinOrderExpressMapper.update(
                            kylinOrderExpress
                            , new UpdateWrapper<KylinOrderExpress>().in("order_express_id", orderExpressInfo.getOrderExpressId())
                    );
                }
            }
        }
        return ResponseDto.success();
    }

    public ResponseDto getFreight(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<String> ids = performanceExpressSearchAdminParam.getIds();
        Integer[] expressStatus = {KylinTableStatusConst.ORDER_EXPRESS_STATUS1, KylinTableStatusConst.ORDER_EXPRESS_STATUS3};
        for (String orderTicketsId : ids) {
            KylinOrderExpress orderExpressInfo = kylinOrderExpressMapper.selectOne(
                    new QueryWrapper<KylinOrderExpress>().eq("order_tickets_id", orderTicketsId)
                            .notIn("express_status", expressStatus)
            );
            KylinOrderTickets orderInfo = kylinOrderTicketsMapper.selectOne(
                    new QueryWrapper<KylinOrderTickets>().eq("order_tickets_id", orderTicketsId)
            );
            if (null != orderExpressInfo) {
                HashMap<String, Object> hBody = new HashMap<>();
                hBody.put("jProvince", jProvince);
                hBody.put("jCity", jCity);
                hBody.put("jAddress", jAddress);

                hBody.put("dProvince", orderInfo.getProvince());
                hBody.put("dCity", orderInfo.getCity());
                hBody.put("dAddress", orderInfo.getExpressAddress());
                hBody.put("expressType", expressType);
                // hBody.put("parcelWeighs", 2.00);
                // hBody.put("volume", "10,10,20");

                // 生成签名并请求
                String result = shunfengSignUtils.generateSignatureAndRequest(hBody, "/public/order/v1/getFreight");
                HashMap hashMap = JsonUtils.fromJson(result, HashMap.class);
                System.out.println(result);
                if (hashMap.get("succ").equals("fail")) {
                    String msg = (String) hashMap.get("msg");
                    return ResponseDto.failure(msg);
                } else {
                    // TODO: 2021/6/30 储存金额
                    // {"result":{"deliverTime":"2021-07-01 18:00:00,2021-07-01 18:00:00","price":"23元","businessTypeDesc":"顺丰特快","businessType":"1"},"succ":"ok","msg":null}
                }
            }
        }
        return ResponseDto.success();
    }

    public ResponseDto getListFreight(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<String> ids = performanceExpressSearchAdminParam.getIds();
        Integer[] expressStatus = {KylinTableStatusConst.ORDER_EXPRESS_STATUS1, KylinTableStatusConst.ORDER_EXPRESS_STATUS3};
        for (String orderTicketsId : ids) {
            KylinOrderExpress orderExpressInfo = kylinOrderExpressMapper.selectOne(
                    new QueryWrapper<KylinOrderExpress>().eq("order_tickets_id", orderTicketsId)
                            .notIn("express_status", expressStatus)
            );
            if (null != orderExpressInfo) {
                HashMap<String, Object> hBody = new HashMap<>();
                hBody.put("orderId", orderExpressInfo.getOrderExpressCode());

                // 生成签名并请求
                String result = shunfengSignUtils.generateSignatureAndRequest(hBody, "/public/order/v1/getListFreight");
                HashMap hashMap = JsonUtils.fromJson(result, HashMap.class);
                System.out.println(result);
                if (hashMap.get("succ").equals("fail")) {
                    String msg = (String) hashMap.get("msg");
                    return ResponseDto.failure(msg);
                } else {
                    HashMap resultResult = (HashMap) hashMap.get("result");
                    List<HashMap> feeList = (List) resultResult.get("feeList");
                    if (!CollectionUtil.isEmpty(feeList)) {
                        kylinOrderExpressFeeInfoMapper.delete(new QueryWrapper<KylinOrderExpressFeeInfo>().eq("order_express_id", orderExpressInfo.getOrderExpressId()));
                        for (HashMap feeInfo : feeList) {
                            KylinOrderExpressFeeInfo kylinOrderExpressFeeInfo = new KylinOrderExpressFeeInfo();
                            String orderExpressFeeInfoId = IDGenerator.nextSnowId();
                            kylinOrderExpressFeeInfo.setOrderExpressFeeInfoId(orderExpressFeeInfoId);
                            kylinOrderExpressFeeInfo.setOrderExpressId(orderExpressInfo.getOrderExpressId());
                            kylinOrderExpressFeeInfo.setType((String) feeInfo.get("type"));
                            kylinOrderExpressFeeInfo.setName((String) feeInfo.get("name"));
                            kylinOrderExpressFeeInfo.setValue(new BigDecimal(feeInfo.get("value").toString()));
                            kylinOrderExpressFeeInfo.setCreatedAt(DateUtil.getNowTime());
                            kylinOrderExpressFeeInfoMapper.insert(kylinOrderExpressFeeInfo);
                        }
                    }
                }
            }
        }
        return ResponseDto.success();
    }

    public ResponseDto listOrderRoute(PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam) {
        List<String> ids = performanceExpressSearchAdminParam.getIds();
        Integer[] expressStatus = {KylinTableStatusConst.ORDER_EXPRESS_STATUS1, KylinTableStatusConst.ORDER_EXPRESS_STATUS3};
        for (String orderTicketsId : ids) {
            KylinOrderExpress orderExpressInfo = kylinOrderExpressMapper.selectOne(
                    new QueryWrapper<KylinOrderExpress>().eq("order_tickets_id", orderTicketsId)
                            .notIn("express_status", expressStatus)
            );
            if (null != orderExpressInfo) {
                HashMap<String, Object> hBody = new HashMap<>();
                hBody.put("orderId", orderExpressInfo.getOrderExpressCode());

                // 生成签名并请求
                String result = shunfengSignUtils.generateSignatureAndRequest(hBody, "/public/order/v1/listOrderRoute");
                HashMap hashMap = JsonUtils.fromJson(result, HashMap.class);
                System.out.println(result);
                if (hashMap.get("succ").equals("fail")) {
                    String msg = (String) hashMap.get("msg");
                    return ResponseDto.failure(msg);
                } else {
                    List<HashMap> resultResult = (List) hashMap.get("result");
                    if (!CollectionUtil.isEmpty(resultResult)) {
                        kylinOrderExpressRouteMapper.delete(new QueryWrapper<KylinOrderExpressRoute>().eq("order_express_id", orderExpressInfo.getOrderExpressId()));
                        for (HashMap routeInfo : resultResult) {
                            KylinOrderExpressRoute kylinOrderExpressRoute = new KylinOrderExpressRoute();
                            String orderExpressRouteId = IDGenerator.nextSnowId();
                            kylinOrderExpressRoute.setOrderExpressRouteId(orderExpressRouteId);
                            kylinOrderExpressRoute.setOrderExpressId(orderExpressInfo.getOrderExpressId());
                            kylinOrderExpressRoute.setAcceptAddress((String) routeInfo.get("accept_address"));
                            kylinOrderExpressRoute.setAcceptDate((String) routeInfo.get("accept_date"));
                            kylinOrderExpressRoute.setAcceptTime((String) routeInfo.get("accept_time"));
                            kylinOrderExpressRoute.setAcceptTotaltime((String) routeInfo.get("accept_totaltime"));
                            kylinOrderExpressRoute.setRemark((String) routeInfo.get("remark"));
                            kylinOrderExpressRoute.setOpcode((String) routeInfo.get("opcode"));
                            kylinOrderExpressRoute.setCreatedAt(DateUtil.getNowTime());
                            kylinOrderExpressRouteMapper.insert(kylinOrderExpressRoute);
                        }
                    }
                }
            }
        }
        return ResponseDto.success();
    }

//    @Async
    public void batchPlaceOrder(String performanceId) {
        int count;
        int limitNum = 10;
        int mid = 0;
        do {
            List<KylinOrderTickets> orderList = kylinOrderTicketsMapper.getCanPlaceOrderList(performanceId, mid, limitNum);

            if (!CollectionUtil.isEmpty(orderList)) {
                List<String> orderIds = orderList.stream().map(KylinOrderTickets -> KylinOrderTickets.getOrderTicketsId()).collect(Collectors.toList());
                PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam = new PerformanceExpressSearchAdminParam();
                performanceExpressSearchAdminParam.setIds(orderIds);
                placeOrder(performanceExpressSearchAdminParam);
            }

            count = orderList.size();
            if (count > 0) {
                KylinOrderTickets lastInfo = orderList.get(count - 1);
                mid = lastInfo.getMid();
            }
        } while (count >= limitNum);
    }

//    @Async
    public void batchCancelOrder(String performanceId) {
        int count;
        int limitNum = 10;
        int mid = 0;
        do {
            List<KylinOrderTickets> orderList = kylinOrderTicketsMapper.getCanCancelOrderList(performanceId, mid, limitNum);

            if (!CollectionUtil.isEmpty(orderList)) {
                List<String> orderIds = orderList.stream().map(KylinOrderTickets -> KylinOrderTickets.getOrderTicketsId()).collect(Collectors.toList());
                PerformanceExpressSearchAdminParam performanceExpressSearchAdminParam = new PerformanceExpressSearchAdminParam();
                performanceExpressSearchAdminParam.setIds(orderIds);
                cancelOrder(performanceExpressSearchAdminParam);
            }

            count = orderList.size();
            if (count > 0) {
                KylinOrderTickets lastInfo = orderList.get(count - 1);
                mid = lastInfo.getMid();
            }
        } while (count >= limitNum);
    }
}
