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.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.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.JacksonUtils;
import com.zm.order.tool.server.utils.OrderCommonUtils;
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.*;

/**
 * 外卖到家业务处理器
 *
 * <p>
 *
 * </p>
 *
 * @author nianchang
 * @date 2024/03/21 5:15 下午
 */
@Component
public class TakeawayBusinessHandler implements BusinessHandler {

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

    @Autowired
    private Mapper mapper;

    @Autowired
    private RefundDao refundDao;

    @Autowired
    private OrderWriteServiceHelper helper;

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

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

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

    @Override
    public BaseIndexOrder buildIndexOrder(Order order) {
        TakeawayIndexOrder index = mapper.map(order, TakeawayIndexOrder.class);
        buildBaseInfo(index, order);
        buildExtInfo(index, order);
        buildPerInfo(index, order);
        buildItemInfo(index, order);
        buildAddressInfo(index, order);
        return index;
    }

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

    private void buildAddressInfo(TakeawayIndexOrder 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("CateringBusinessHandler[buildAddressInfo]failed! orderNo:{}, cause by:{}", order.getOrderNo(), e);
        }
    }

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

    /**
     * 解析商品属性赋值
     *
     * <p>
     *      获取商品type支持检索
     *      获取商品名称、itemId支持检索
     * </p>
     *
     * @param index	ES mapping文档
     * @param itemList 商品列表
     * @param searchCondition 全局搜索条件
     */
    private void parseItemAttribute(TakeawayIndexOrder 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);
        helper.parseItem(itemList, searchCondition, itemTypeSet, itemIdList, itemNameList, itemBarcodeList);

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

    private void buildBaseInfo(TakeawayIndexOrder indexOrder, Order order) {
        indexOrder.setOrderId(order.getId());
        indexOrder.setSearchPayer(order.getPayer());
        if (Objects.nonNull(order.getCompletedAt())) {
            indexOrder.setSearchCompletedAt(order.getCompletedAt());
        }
        if (Objects.nonNull(order.getActualAmount())) {
            indexOrder.setSearchActualAmount(order.getActualAmount());
        }
        if (ORDER_PAYED.equals(order.getPayStatus())) {
            RefundQuery refundQuery = new RefundQuery();
            refundQuery.setOrderNo(order.getOrderNo());
            List<Refund> refundList = refundDao.selectList(refundQuery);
            if (!CollectionUtils.isEmpty(refundList)) {
                indexOrder.setRefundCompleted(1);
            }
        }
    }

    private void buildExtInfo(TakeawayIndexOrder indexOrder, Order order) {
        Map<String, Object> extraMap = order.getExtraMap();
        if (!CollectionUtils.isEmpty(extraMap)) {
            if (!StringUtils.isEmpty(extraMap.get(SEAT_NAME))) {
                String seatName = extraMap.get(SEAT_NAME).toString();
                indexOrder.setSeatName(seatName);
                String globalSearch = indexOrder.getGlobalSearch();
                if (StringUtils.isEmpty(globalSearch)) {
                    globalSearch = seatName;
                } else {
                    globalSearch = globalSearch + "," + seatName;
                }
                indexOrder.setGlobalSearch(globalSearch);
            }
            if (Objects.nonNull(extraMap.get(SYNC_ERROR))) {
                indexOrder.setSyncErpError(Integer.valueOf(extraMap.get(SYNC_ERROR).toString()));
            }
            if (!StringUtils.isEmpty(extraMap.get(GROUP_STATUS))) {
                indexOrder.setGroupStatus(extraMap.get(GROUP_STATUS).toString());
            }
            if (!StringUtils.isEmpty(extraMap.get(BILL_NO))) {
                indexOrder.setBillNo(extraMap.get(BILL_NO).toString());
            }
            if (!StringUtils.isEmpty(extraMap.get(MEAL_TAKING_DEVICE_NO))) {
                String globalSearch = indexOrder.getGlobalSearch();
                indexOrder.setGlobalSearch(globalSearch + "," + extraMap.get(MEAL_TAKING_DEVICE_NO));
            }
        }
    }



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

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

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

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

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

    @Autowired
    private OrderPayDetailsDao payDetailsDao;

    private static final String USE_WALLET = "useWallet";

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

    /**
     * 餐牌号
     */
    String MEAL_TAKING_DEVICE_NO = "mealTakingDeviceNo";

    /**
     * 商品订单类型
     */
    String GOODS_TYPE = "goodsSubType";

    /**
     * 雷达订单前缀
     */
    String RADAR_ORDER_SCRM = "scrm";
    /**
     * 实体储值卡类型
     */
    String DEPOSIT_ENTITY_BIZ_TYPE = "depositEntityBizType";

    /**
     * 推广码id
     */
    String ORDER_PROMOTE_CODE = "orderPromoteCode";

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

    /**
     * 拼团类型
     */
    private static final String GROUP_TYPE = "groupType";

    /**
     * 订单排队状态
     */
    String ORDER_LINE_UP_STATUS = "lineUpStatus";

    /**
     * 进排队时间
     */
    String QUEUE_TIME = "queueTime";

    /**
     * 企业订单信息
     */
    String EXTRA_ENTERPRISE_ORDER_INFO = "extraEnterpriseOrderInfo";

    /**
     * 企业订单id
     */
    String ENTERPRISE_ID = "enterpriseId";

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

    /**
     * 收货手机号
     */
    String RECEIVER_MOBILE = "receiverMobile";

    /**
     * 预约时间
     */
    String RESERVE_TIME = "reserveTime";
    private void buildPerInfo(TakeawayIndexOrder indexOrder, Order order) {
        if (!StringUtils.isEmpty(order.getPerformanceInfo())) {
            Map<String, Object> performanceMap = JSON.parseObject(order.getPerformanceInfo());
            if (!CollectionUtils.isEmpty(performanceMap)) {
                if (Objects.nonNull(performanceMap.get(DELIVERY_STATUS))) {
                    indexOrder.setDeliveryStatus(Integer.valueOf(performanceMap.get(DELIVERY_STATUS).toString()));
                }
                if (!StringUtils.isEmpty(performanceMap.get(RECEIVER_MOBILE))) {
                    String receiverMobile = performanceMap.get(RECEIVER_MOBILE).toString();
                    indexOrder.setReceiverMobile(receiverMobile);
                }
                if (!StringUtils.isEmpty(performanceMap.get(RESERVE_TIME))) {
                    String reserveTime = performanceMap.get(RESERVE_TIME).toString();
                    try {
                        Date date = new Date();
                        date.setTime(Long.parseLong(reserveTime));
                        indexOrder.setReserveTime(date);
                    } catch (Throwable ex) {
                        logger.error("TakeawayBusinessHandler[buildPerInfoError] time:{} orderNo:{}, cause by:{}",
                                reserveTime, order.getOrderNo(), ex);
                    }
                }
            }
        }

    }

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





    @Override
    public List<BaseIndexOrder> parseIndexOrder(SearchHit[] searchHits) {
        List<BaseIndexOrder> list = Lists.newArrayListWithCapacity(searchHits.length);
        for (SearchHit searchHit : searchHits) {
            list.add(JacksonUtils.getObjectFromJsonString(searchHit.getSourceAsString(), TakeawayIndexOrder.class));
        }
        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;
    }

}
