package com.zm.order.tool.server.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.dozermapper.core.Mapper;
import com.google.common.collect.Lists;
import com.zm.order.tool.server.builder.SearchRequestBuilder;
import com.zm.order.tool.server.constants.AppointFlagConstants;
import com.zm.order.tool.server.constants.CommonConstants;
import com.zm.order.tool.server.dao.OrderDiscountDao;
import com.zm.order.tool.server.dao.OrderItemDao;
import com.zm.order.tool.server.dao.RefundDao;
import com.zm.order.tool.server.dto.OrderDTO;
import com.zm.order.tool.server.dto.RefundDTO;
import com.zm.order.tool.server.enums.BizTypeEnum;
import com.zm.order.tool.server.model.*;
import com.zm.order.tool.server.query.SearchOrderQuery;
import com.zm.order.tool.server.utils.ConvertUtils;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 烘焙业务线
 * @Author nianchang
 * @ClassName BakingBusinessHandler
 * @Date 2020/12/28 10:06 AM
 */
@Component
@SuppressWarnings("all")
public class BakingBusinessHandler implements BusinessHandler {

    private static final Logger logger = LoggerFactory.getLogger(BakingBusinessHandler.class);

    @Autowired
    private Mapper mapper;

    @Autowired
    private PerformanceHandle performanceHandle;

    @Autowired
    private RefundDao refundDao;

    @Autowired
    private OrderItemDao orderItemDao;

    @Autowired
    private OrderDiscountDao discountDao;

    /**
     * 拼团状态
     */
    private static final String GROUP_STATUS = "groupStatus";

    /**
     * 雷达订单前缀
     */
    String RADAR_ORDER_SCRM = "scrm";

    /**
     * 分类ID
     */
    private static final String CATEGORY_ID = "categoryId";

    /**
     * 配送模式
     */
    private static final String DELIVERY_MODE = "deliveryMode";

    /**
     * 配送状态
     */
    private static final String DELIVERY_STATUS = "deliveryStatus";

    /**
     * 来源
     */
    private static final String FROM = "from";

    /**
     * 渠道码
     */
    private static final String CHANNEL_CODE = "channel_code";

    /**
     * 入账类型
     */
    private static final String RECEIVE_PAYMENT_TYPE = "receivePaymentType";

    /**
     * 来源门店信息
     */
    private static final String SOURCE_SHOP_INFO = "sourceShopInfo";

    /**
     * 账单号
     */
    private static final String BILL_NO = "billNo";

    /**
     * 同步ERP异常
     */
    String SYNC_ERROR = "syncError";

    /**
     * id
     */
    private static final String ID = "id";

    /**
     * 订单已完成
     */
    private static final Integer ORDER_COMPLETED_STATUS = 4;

    /**
     * 订单已关闭
     */
    private static final Integer ORDER_CLOSED_STATUS = 8;

    /**
     * 订单支付状态payStatus
     * 订单已支付
     */
    private static final Integer ORDER_PAYED_STATUS = 1;

    /**
     * 订单状态status
     * 订单已经支付
     */
    private static final Integer ORDER_PAY_STATUS = 2;

    /**
     * 配送时间类型
     */
    private static final String VERIFY_TYPE = "verifyType";

    /**
     * 订单自提点信息
     */
    String PICK_UP_INFO = "pickUpInfo";

    /**
     * 自提点id
     */
    String PICK_UP_SHOP_ID = "shopId";

    /**
     * 扩展字段-企微员工id
     */
    String WORK_WECHAT_USERID = "workWechatUserid";

    /**
     * 订单自提编号
     */
    String PICK_UP_NO = "pickUpNo";

    @Override
    public Integer bizType() {
        return BizTypeEnum.BAKING.getType();
    }

    @Override
    public BaseIndexOrder buildIndexOrder(Order order) {
        BakingIndexOrder indexOrder = mapper.map(order, BakingIndexOrder.class);
        try {
            List<String> searchCondition = new ArrayList<>();
            buildBaseInfo(indexOrder, order);
            buildItemInfo(indexOrder, order, searchCondition);
            buildPerformanceInfo(indexOrder, order);
            buildExtraMapInfo(indexOrder, order);
            buildDiscountInfo(indexOrder, order);
            buildAddressInfo(indexOrder, order);
            buildLikeSearch(indexOrder, order);
            buildGlobalSearch(indexOrder, order, searchCondition);
        } catch (Exception e) {
            logger.error("BakingBusinessHandler[buildIndexOrder]failed! orderNo:{}, cause by:{}", order.getOrderNo(), e);
        }
        return indexOrder;
    }

    /**
     * 全局搜索
     *
     * <p>
     *      多个条件拼接在一起，用','分割，多条件精准搜索
     *      现有条件：订单号、手机号、取餐号、三方单号、商品名称、商品id、桌台号
     *      后续可能还会增加
     * </p>
     *
     * @param indexOrder ES mapping文档
     * @param order 订单详情
     * @param searchCondition 全局搜索条件
     */
    private void buildGlobalSearch(BakingIndexOrder indexOrder, Order order, List<String> searchCondition) {
        searchCondition.add(order.getMobile());
        searchCondition.add(order.getOrderNo());
        if (!StringUtils.isEmpty(order.getSourceNo())) {
            searchCondition.add(order.getSourceNo());
        }
        if (!StringUtils.isEmpty(order.getStoreOrderNo())) {
            searchCondition.add(order.getStoreOrderNo());
        }
        indexOrder.setGlobalSearch(String.join(",", searchCondition));
    }

    private void buildLikeSearch(BakingIndexOrder index, Order order) {
        List<String> likeSearch = new ArrayList<>(2);
        try {
            // 手机号截取后四位支持搜索
            String mobile = order.getMobile();
            if (!StringUtils.isEmpty(order.getMobile()) && !order.getMobile().equals("0")) {
                String suffix;
                if (mobile.contains(",")) {
                    int idx = mobile.indexOf(",");
                    suffix = mobile.substring(idx - 4, idx);
                } else {
                    suffix = mobile.substring(mobile.length() - 4);
                }
                likeSearch.add(suffix);
            }
            // 订单号截取后六位支持搜索
            if (!StringUtils.isEmpty(order.getOrderNo())) {
                likeSearch.add(order.getOrderNo().substring(order.getOrderNo().length() - 6));
            }
        } catch (Exception e) {
            logger.error("[buildLikeSearch]failed! order:{}, cause by:{}", order, e);
        }
        index.setLikeSearch(likeSearch);
    }

    private void buildBaseInfo(BakingIndexOrder indexOrder, Order order) {
        indexOrder.setOrderId(order.getId());
        indexOrder.setRefundCompleted(0);
        if (checkStatus(order.getStatus(), order.getPayStatus())) {
            try {
                indexOrder.setRefundCompleted(order.getRefundFlag());
            } catch (Exception e) {
                logger.error("[SELECT_REFUND_ID_LIST]failed! cause by:{}", e);
            }
        }
        if (Objects.nonNull(order.getActualAmount())) {
            indexOrder.setSearchActualAmount(order.getActualAmount());
        }
        List<String> searchList = new ArrayList<>(10);
        searchList.add(order.getOrderNo());
        if (!StringUtils.isEmpty(order.getMobile())) {
            searchList.add(order.getMobile());
        }
        if (!StringUtils.isEmpty(order.getStoreOrderNo())) {
            searchList.add(order.getStoreOrderNo());
            // 多存一份小写，支持忽略大小写查询
            searchList.add(order.getStoreOrderNo().toLowerCase());
        }
        indexOrder.setSearchList(searchList);
        if (Objects.nonNull(order.getCompletedAt())) {
            indexOrder.setSearchCompletedAt(order.getCompletedAt());
        }
        indexOrder.setSearchPayer(order.getPayer());
    }

    private void buildDiscountInfo(BakingIndexOrder indexOrder, Order order) {
        try {
            List<InnerOrderDiscount> discountList = parseInnerOrderDiscount(order);
            if (!CollectionUtils.isEmpty(discountList)) {
                List<Integer> discountType = discountList.stream()
                        .map(InnerOrderDiscount::getDiscountType).collect(Collectors.toList());
                indexOrder.setDiscountTypeList(discountType);
            }
        } catch (Exception e) {
            logger.error("BakingBusinessHandler[buildDiscountInfo]failed!orderNo:{}, cause by:{}",
                    order.getOrderNo(), e);
        }
    }

    public List<InnerOrderDiscount> parseInnerOrderDiscount(Order order) {
        String discountInfo = order.getDiscountInfo();
        List<InnerOrderDiscount> discountList = new ArrayList<>();
        if (!StringUtils.isEmpty(discountInfo)) {
            if (Objects.equals(discountInfo, CommonConstants.DISCOUNT_FLAG)) {
                List<OrderDiscount> orderDiscounts = discountDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
                discountList = ConvertUtils.convertList(orderDiscounts, InnerOrderDiscount.class);
            } else {
                discountList = JSON.parseArray(discountInfo, InnerOrderDiscount.class);
            }
        }
        return discountList;
    }

    private void buildAddressInfo(BakingIndexOrder indexOrder, Order order) {
        try {
            if (!StringUtils.isEmpty(order.getAddrInfo())) {
                InnerOrderAddr orderAddr = JSON.parseObject(order.getAddrInfo(), InnerOrderAddr.class);
                indexOrder.setAcceptName(orderAddr.getAcceptName());
                indexOrder.setAcceptMobile(orderAddr.getMobile());
            }
        } catch (Exception e) {
            logger.error("BakingBusinessHandler[buildAddressInfo]failed!orderNo:{}, cause by:{}",
                    order.getOrderNo(), e);
        }
    }

    private void buildItemInfo(BakingIndexOrder indexOrder, Order order, List<String> searchCondition) {
        try {
            if (order != null) {
                // 获取订单下所有的商品信息
                String itemInfo = order.getItemInfo();
                List<OrderItem> itemList;
                if (!StringUtils.isEmpty(itemInfo) && !Objects.equals(itemInfo, CommonConstants.ITEM_FLAG)) {
                    itemList = JSONArray.parseArray(itemInfo, OrderItem.class);
                } else {
                    itemList = orderItemDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
                }
                if (!CollectionUtils.isEmpty(itemList)) {
                    List<String> itemIdList = new ArrayList<>(itemList.size());
                    List<String> itemNameList = new ArrayList<>(itemList.size());
                    List<Integer> itemTypeList = new ArrayList<>(itemList.size());
                    Set<Long> categoryIdSet = new HashSet<>(itemList.size() * 2);
                    Set<String> itemBarcodeList = new HashSet<>(itemList.size());
                    for (OrderItem orderItem : itemList) {
                        itemIdList.add(orderItem.getItemId());
                        itemNameList.add(orderItem.getItemName().trim());
                        itemTypeList.add(orderItem.getItemType());
                        itemBarcodeList.add(orderItem.getItemBarcode());
                        if (!CollectionUtils.isEmpty(orderItem.getExtraMap())) {
                            Map<String, Object> extraMap = orderItem.getExtraMap();
                            if (!StringUtils.isEmpty(extraMap.get(CATEGORY_ID))) {
                                List<Long> categoryIdList = (List) JSON.parseArray(extraMap.get(CATEGORY_ID).toString());
                                categoryIdSet.addAll(categoryIdList);
                            }
                        }
                    }
                    searchCondition.addAll(itemIdList);
                    searchCondition.addAll(itemNameList);

                    indexOrder.setItemIdList(itemIdList);
                    indexOrder.setItemNamesKeyword(itemNameList);
                    indexOrder.setItemTypeList(itemTypeList);
                    indexOrder.setCategoryIdList(Lists.newArrayList(categoryIdSet));
                    indexOrder.setItemBarcodeList(Lists.newArrayList(itemBarcodeList));
                }
            }
        } catch (Exception e) {
            logger.error("buildItemInfo failed! orderNo:{},cause by:{}", order.getOrderNo(), e);
        }
    }

    private void buildExtraMapInfo(BakingIndexOrder indexOrder, Order order) {
        Map<String, Object> extraMap = order.getExtraMap();
        if (!CollectionUtils.isEmpty(extraMap)) {
            if (Objects.nonNull(extraMap.get(GROUP_STATUS))) {
                indexOrder.setGroupStatus(Integer.valueOf(extraMap.get(GROUP_STATUS).toString()));
            }
            if (Objects.nonNull(extraMap.get(DELIVERY_MODE))) {
                indexOrder.setDeliveryMode(Integer.valueOf(extraMap.get(DELIVERY_MODE).toString()));
            }
            if (Objects.nonNull(extraMap.get(DELIVERY_STATUS))) {
                indexOrder.setDeliveryStatus(Integer.valueOf(extraMap.get(DELIVERY_STATUS).toString()));
            }
            if (Objects.nonNull(extraMap.get(FROM))) {
                indexOrder.setGoodsOrderSource(Integer.valueOf(extraMap.get(FROM).toString()));
            } else {
                indexOrder.setGoodsOrderSource(0);
            }
            if (Objects.nonNull(extraMap.get(VERIFY_TYPE))) {
                indexOrder.setVerifyType(Integer.valueOf(extraMap.get(VERIFY_TYPE).toString()));
            }
            if (Objects.nonNull(extraMap.get(AppointFlagConstants.START_LINE_UP_FLAG))) {
                indexOrder.setStartLineUp(Integer.valueOf(extraMap.get(AppointFlagConstants.START_LINE_UP_FLAG).toString()));
            }
            if (Objects.nonNull(extraMap.get(CHANNEL_CODE))) {
                indexOrder.setChannelCode(extraMap.get(CHANNEL_CODE).toString());
            }
            if (Objects.nonNull(extraMap.get("transferOrder"))) {
                indexOrder.setTransferOrder(Integer.valueOf(extraMap.get("transferOrder").toString()));
            }
            if (Objects.nonNull(extraMap.get(RECEIVE_PAYMENT_TYPE))) {
                indexOrder.setReceivePaymentType(Integer.valueOf(extraMap.get(RECEIVE_PAYMENT_TYPE).toString()));
            }
            if (Objects.nonNull(extraMap.get(SOURCE_SHOP_INFO))) {
                Map<String, Object> sourceShopInfoMap = JSON.parseObject(extraMap.get(SOURCE_SHOP_INFO).toString(), Map.class);
                if (Objects.nonNull(sourceShopInfoMap.get(ID))) {
                    indexOrder.setSourceStoreId(Integer.valueOf(sourceShopInfoMap.get(ID).toString()));
                }
            }
            if (Objects.nonNull(extraMap.get(BILL_NO))) {
                indexOrder.setBillNo(extraMap.get(BILL_NO).toString());
            }
            if (Objects.nonNull(extraMap.get(SYNC_ERROR))) {
                indexOrder.setSyncErpError(Integer.valueOf(extraMap.get(SYNC_ERROR).toString()));
            }
            if (!StringUtils.isEmpty(extraMap.get(CHANNEL_CODE))) {
                String channelCode = extraMap.get(CHANNEL_CODE).toString();
                if (channelCode.startsWith(RADAR_ORDER_SCRM)) {
                    indexOrder.setRadarOrder(1);
                }
            }
            if (Objects.nonNull(extraMap.get(PICK_UP_INFO))) {
                Map<String, Object> pickUpMap = JSON.parseObject(extraMap.get(PICK_UP_INFO).toString());
                if (!StringUtils.isEmpty(pickUpMap.get(PICK_UP_NO))) {
                    indexOrder.setPickUpNo(pickUpMap.get(PICK_UP_NO).toString());
                }
                if (pickUpMap.get(PICK_UP_SHOP_ID) != null) {
                    indexOrder.setPickUpId(Long.parseLong(pickUpMap.get(PICK_UP_SHOP_ID).toString()));
                }
            }
            if (!StringUtils.isEmpty(extraMap.get(WORK_WECHAT_USERID))) {
                indexOrder.setWorkWechatUserId(extraMap.get(WORK_WECHAT_USERID).toString());
            }
        }
    }

    private void buildPerformanceInfo(BakingIndexOrder indexOrder, Order order) {
        RetailPerformanceHandler handle = this.performanceHandle.getPerformanceHandle(order.getPerformanceType());
        if (handle != null) {
            handle.buildPerformanceIndex(indexOrder, order);
        }
    }

    /**
     * 校验订单可能存在退款单
     * @param status
     * @param payStatus
     * @return: boolean
     * @Date:   2020/5/12 6:03 PM
     */
    private boolean checkStatus(Integer status, Integer payStatus) {
        return Objects.equals(payStatus, ORDER_PAYED_STATUS);
    }

    @Override
    public SearchSourceBuilder buildSearchSourceBuilder(SearchOrderQuery searchOrderQuery) {
        SearchSourceBuilder searchSourceBuilder = SearchRequestBuilder.buildOrderSearchBuilder(searchOrderQuery);
        return searchSourceBuilder;
    }

    @Override
    public List<BaseIndexOrder> parseIndexOrder(SearchHit[] searchHits) {
        List<BaseIndexOrder> list = Lists.newArrayListWithCapacity(searchHits.length);
        for (int i = 0; i < searchHits.length; i++) {
            SearchHit searchHit = searchHits[i];
            BakingIndexOrder t = JSON.parseObject(searchHit.getSourceAsString(), BakingIndexOrder.class);
            list.add(t);
        }
        return list;
    }

    @Override
    public Integer getRefundAmount(RefundDTO refundDTO) {
        return 0;
    }

    @Override
    public BaseIndexOrder getOrderDto(BaseIndexOrder baseIndexOrder, OrderDTO orderDTO, Order order) {
        return null;
    }

}
