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.dao.RefundItemDao;
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.helper.OrderWriteServiceHelper;
import com.zm.order.tool.server.model.*;
import com.zm.order.tool.server.query.RefundQuery;
import com.zm.order.tool.server.query.SearchOrderQuery;
import com.zm.order.tool.server.utils.ConvertUtils;
import com.zm.order.tool.server.utils.OrderCommonUtils;
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.*;
import java.util.stream.Collectors;

/**
 * 商城业务
 *
 * @author zhuxiaofeng
 * @Date 2023-03-14 15:40:11
 */
@Component
public class MallBusinessHandler implements BusinessHandler {

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

    @Autowired
    private Mapper mapper;

    @Autowired
    private RefundItemDao refundItemDao;

    @Autowired
    private RefundDao refundDao;

    @Autowired
    private OrderItemDao orderItemDao;

    @Autowired
    private OrderWriteServiceHelper helper;

    @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";

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


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

    @Override
    public BaseIndexOrder buildIndexOrder(Order order) {
        MallIndexOrder indexOrder = mapper.map(order, MallIndexOrder.class);
        List<String> searchCondition = new ArrayList<>();
        buildBaseInfo(indexOrder, order);
        buildItemInfo(indexOrder, order, searchCondition);
        buildExtraMapInfo(indexOrder, order);
        buildDiscountInfo(indexOrder, order);
        buildAddressInfo(indexOrder, order);
        buildLikeSearch(indexOrder, order);
        buildGlobalSearch(indexOrder, order, searchCondition);
        return indexOrder;
    }

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

    private void buildLikeSearch(MallIndexOrder index, Order order) {
        index.setLikeSearch(helper.addElement(order.getOrderNo(), order.getMobile()));
    }

    private void buildBaseInfo(MallIndexOrder indexOrder, Order order) {
        indexOrder.setOrderId(order.getId());
        indexOrder.setRefundCompleted(order.getRefundFlag());

        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());
    }

    @SuppressWarnings("unchecked")
    private void buildItemInfo(MallIndexOrder indexOrder, Order order, List<String> searchCondition) {
        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)) {
                final int size = itemList.size();
                List<String> itemIdList = new ArrayList<>(size);
                List<String> itemNameList = new ArrayList<>(size);
                List<Integer> itemTypeList = new ArrayList<>(size);
                Set<String> itemBarcodeList = new HashSet<>(size);
                Set<Long> categoryIdSet = new HashSet<>(itemList.size() * 2);
                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));
            }
        }
    }

    private void buildExtraMapInfo(MallIndexOrder indexOrder, Order order) {
        Map<String, Object> extraMap = order.getExtraMap();
        if (!CollectionUtils.isEmpty(extraMap)) {
            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()));
            }
            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(RECEIVE_PAYMENT_TYPE))) {
                indexOrder.setReceivePaymentType(Integer.valueOf(extraMap.get(RECEIVE_PAYMENT_TYPE).toString()));
            }
            if (!StringUtils.isEmpty(extraMap.get(BILL_NO))) {
                indexOrder.setBillNo(extraMap.get(BILL_NO).toString());
            }
            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());
                }
            }
        }
    }
    
    private void buildDiscountInfo(MallIndexOrder 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("MallBusinessHandler[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(MallIndexOrder 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("MallBusinessHandler[buildAddressInfo]failed! orderNo:{}, cause by:{}", order.getOrderNo(), e);
        }

    }

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

    @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];
            MallIndexOrder t = JSON.parseObject(searchHit.getSourceAsString(), MallIndexOrder.class);
            list.add(t);
        }
        return list;
    }

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

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

