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

import com.alibaba.fastjson.JSON;
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.CommonConstants;
import com.zm.order.tool.server.dao.OrderItemDao;
import com.zm.order.tool.server.dao.OrderPayDetailsDao;
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.RefundQuery;
import com.zm.order.tool.server.query.SearchOrderQuery;
import org.elasticsearch.index.query.BoolQueryBuilder;
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.*;

/**
 * 企迈门店助手处理器
 *
 * @author nianchang
 * @date 2021/03/02 9:55 上午
 */
@Component
@SuppressWarnings("all")
public class AssistantBusinessHandler implements BusinessHandler {

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

    @Autowired
    private Mapper mapper;

    @Autowired
    private RefundDao refundDao;

    @Autowired
    private OrderItemDao orderItemDao;

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

    /**
     * 支付状态
     */
    private static final Integer ORDER_PAY_STATUS = 1;

    /**
     * 退款完成
     */
    private static final Integer REFUND_COMPLETE = 30;

    /**
     * 桌位名称
     */
    private static final String SEAT_NAME = "seatName";

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

    @Override
    public BaseIndexOrder buildIndexOrder(Order order) {
        AssistantIndexOrder indexOrder = mapper.map(order, AssistantIndexOrder.class);
        try {
            buildBaseInfo(indexOrder, order);
            buildItemInfo(indexOrder, order);
            buildExtInfo(indexOrder, order);
            buildPayInfo(indexOrder, order);
            buildLikeSearch(indexOrder, order);
            buildAddressInfo(indexOrder, order);
        } catch (Exception e) {
            logger.error("AssistantBusinessHandler[buildIndexOrder]failed! orderNo:{}, cause by:{}", order.getOrderNo(), e);
        }
        return indexOrder;
    }

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

    private void buildLikeSearch(AssistantIndexOrder index, Order order) {
        List<String> likeSearch = new ArrayList<>(2);
        try {
            // 手机号截取后四位支持搜索
            String mobile = order.getMobile();
            if (!StringUtils.isEmpty(mobile)) {
                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);
            }
            // 订单号截取后六位支持搜索
            String orderNo = order.getOrderNo();
            if (!StringUtils.isEmpty(orderNo)) {
                likeSearch.add(orderNo.substring(orderNo.length() - 6));
            }
        } catch (Exception e) {
            logger.error("[buildLikeSearch]failed! order:{}, cause by:{}", order, e);
        }
        index.setLikeSearch(likeSearch);
    }

    private void buildPayInfo(AssistantIndexOrder indexOrder, Order order) {
        try {
            setPayTypeList(indexOrder, order);
        } catch (Exception e) {
            logger.error("AssistantBusinessHandler[BUILD_PAY_AMOUNT_ERROR]failed! order:{}, cause by:{}", order, e);
        }
    }

    @Autowired
    private OrderPayDetailsDao payDetailsDao;

    private void setPayTypeList(AssistantIndexOrder indexOrder, Order order) {
        List<OrderPayDetails> payDetailsList = this.parsePayList(order);
        List<Integer> payTypeList = new ArrayList<>(payDetailsList.size());
        if (!CollectionUtils.isEmpty(payDetailsList)) {
            for (OrderPayDetails payDetails : payDetailsList) {
                payTypeList.add(payDetails.getPayType());
            }
        }
        indexOrder.setPayTypeList(payTypeList);
    }

    private List<OrderPayDetails> parsePayList(Order order) {
        List<OrderPayDetails> payDetailsList;
        String payDetailInfo = order.getPayDetailInfo();
        if (!StringUtils.isEmpty(payDetailInfo) && !Objects.equals(payDetailInfo, CommonConstants.PAY_FLAG)) {
            payDetailsList = JSON.parseArray(payDetailInfo, OrderPayDetails.class);
        } else {
            payDetailsList = payDetailsDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
        }
        return payDetailsList;
    }

    private void buildBaseInfo(AssistantIndexOrder indexOrder, Order order) {
        indexOrder.setOrderId(order.getId());
        indexOrder.setRefundCompleted(0);
        if (checkStatus(order.getPayStatus())) {
            RefundQuery refundQuery = new RefundQuery();
            refundQuery.setOrderNo(order.getOrderNo());
            List<Refund> refundList = refundDao.selectList(refundQuery);
            if (!CollectionUtils.isEmpty(refundList)) {
                indexOrder.setRefundCompleted(1);
            }
        }
        if (Objects.nonNull(order.getActualAmount())) {
            indexOrder.setSearchActualAmount(order.getActualAmount());
        }
    }

    private void buildItemInfo(AssistantIndexOrder indexOrder, Order order) {
        List<OrderItem> itemList = this.getItemList(order);
        List<String> searchCondition = new ArrayList<>();
        this.parseItemAttribute(indexOrder, itemList, searchCondition);
        this.setSearchAttribute(indexOrder, order, searchCondition);
    }

    private void buildExtInfo(AssistantIndexOrder indexOrder, Order order) {
        Map<String, Object> extraMap = order.getExtraMap();
        if (!CollectionUtils.isEmpty(extraMap)) {
            if (!StringUtils.isEmpty(extraMap.get(SEAT_NAME))) {
                indexOrder.setSeatName(extraMap.get(SEAT_NAME).toString());

                String globalSearch = indexOrder.getGlobalSearch();
                indexOrder.setGlobalSearch(globalSearch + "," + indexOrder.getSeatName());
            }
            if (Objects.nonNull(extraMap.get(SYNC_ERROR))) {
                indexOrder.setSyncErpError(Integer.valueOf(extraMap.get(SYNC_ERROR).toString()));
            }
            if (!StringUtils.isEmpty(extraMap.get("mealTakingDeviceNo"))) {
                String globalSearch = indexOrder.getGlobalSearch();
                indexOrder.setGlobalSearch(globalSearch + "," + extraMap.get("mealTakingDeviceNo"));
            }
            if (extraMap.get("lineUpStatus") != null) {
                indexOrder.setLineUpStatus(Integer.valueOf(extraMap.get("lineUpStatus").toString()));
            }
            if (extraMap.get("queueTime") != null) {
                indexOrder.setSearchQueueTime(new Date(Long.parseLong(extraMap.get("queueTime").toString())));
            }
        }
    }

    /**
     * 全局搜索
     *
     * <p>
     *      多个条件拼接在一起，用','分割，多条件精准搜索
     *      现有条件：订单号、手机号、取餐号、三方单号、商品名称、商品id、桌台号、商品编码
     *      后续可能还会增加
     * </p>
     *
     * @param indexOrder ES mapping文档
     * @param order 订单详情
     * @param searchCondition 全局搜索条件
     */
    private void setSearchAttribute(AssistantIndexOrder 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));
    }

    /**
     * 解析商品属性赋值
     *
     * <p>
     *      获取商品type支持检索
     *      获取商品名称、itemId支持检索
     * </p>
     *
     * @param index	ES mapping文档
     * @param itemList 商品列表
     * @param searchCondition 全局搜索条件
     */
    private void parseItemAttribute(AssistantIndexOrder index, List<OrderItem> itemList, List<String> searchCondition) {
        if (CollectionUtils.isEmpty(itemList)) {
            return;
        }
        final int size = itemList.size();
        Set<Integer> itemTypeSet = new HashSet<>(size);
        Set<String> itemIdList = new HashSet<>(size);
        Set<String> itemNameList = new HashSet<>(size);
        Set<String> itemBarcodeList = new HashSet<>(size);
        for (OrderItem item : itemList) {
            if (!StringUtils.isEmpty(item.getItemName())) {
                itemNameList.add(item.getItemName());
                searchCondition.add(item.getItemName());
            }
            if (Objects.nonNull(item.getItemId())) {
                itemIdList.add(item.getItemId());
                searchCondition.add(item.getItemId());
            }
            if (Objects.nonNull(item.getItemType())) {
                itemTypeSet.add(item.getItemType());
            }
            if (!StringUtils.isEmpty(item.getItemBarcode())) {
                itemBarcodeList.add(item.getItemBarcode());
            }
        }

        index.setItemIdList(Lists.newArrayList(itemIdList));
        index.setItemBarcodeList(Lists.newArrayList(itemBarcodeList));
        index.setItemTypeList(Lists.newArrayList(itemTypeSet));
        index.setItemNamesKeyword(Lists.newArrayList(itemNameList));
    }


    private List<OrderItem> getItemList(Order order) {
        List<OrderItem> itemList;
        if (StringUtils.isEmpty(order.getItemInfo()) || Objects.equals(CommonConstants.ITEM_FLAG, order.getItemInfo())) {
            itemList = orderItemDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
        } else {
            itemList = JSON.parseArray(order.getItemInfo(), OrderItem.class);
        }
        return itemList;
    }

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

    @Override
    public SearchSourceBuilder buildSearchSourceBuilder(SearchOrderQuery searchOrderQuery) {
        SearchSourceBuilder searchSourceBuilder = SearchRequestBuilder.buildOrderSearchBuilder(searchOrderQuery);
        BoolQueryBuilder boolQueryBuilder = (BoolQueryBuilder) searchSourceBuilder.query();
        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];
            CateringIndexOrder t = JSON.parseObject(searchHit.getSourceAsString(), CateringIndexOrder.class);
            list.add(t);
        }
        return list;
    }

    @Override
    public Integer getRefundAmount(RefundDTO refundDTO) {
        if (Objects.equals(refundDTO.getStatus(), REFUND_COMPLETE)) {
            return refundDTO.getRefundAmount();
        }
        return 0;
    }

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


}
