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

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.github.dozermapper.core.Mapper;
import com.zm.order.tool.server.constants.CommonConstants;
import com.zm.order.tool.server.dao.OrderItemDao;
import com.zm.order.tool.server.dao.PerformanceSelfTakeDao;
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.model.*;
import com.zm.order.tool.server.query.RefundQuery;
import com.zm.order.tool.server.query.SearchOrderQuery;

/**
 * 零售处理器
 * 
 * @Author chang.n
 * @ClassName RetailBusinessHandler
 * @Date 2020/4/14 10:07 AM
 */
@Component
public class RetailBusinessHandler implements BusinessHandler {

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

    @Autowired
    private Mapper mapper;

    @Autowired
    private RefundDao refundDao;

    @Autowired
    private OrderItemDao orderItemDao;

    @Autowired
    private PerformanceSelfTakeDao selfTakeDao;

    @Autowired
    private RefundItemDao refundItemDao;

    @Autowired
    private PerformanceHandle performanceHandle;

    private static final String CODE = "code";

    /**
     * 当日流水(零售业务字段)
     */
    private static final String SORT_NUM = "sort_num";

    /**
     * 订单子信息
     */
    private static final String ORDER_SUB_INFO = "orderSubinfo";

    /**
     * 订单发票
     */
    private static final String IS_INVOICE = "is_invoice";

    /**
     * 发货时间
     */
    private static final String SENT_AT = "sent_at";

    private static final String EXPRESS = "express";

    /**
     * 钱包支付金额
     */
    private static final String WALLET_AMOUNT = "wallet_amount";

    /**
     * 使用余额
     */
    private static final String USE_WALLET = "use_wallet";

    private static final String GROUP_ORDER_INFO = "groupOrderInfo";

    /**
     * 拼团类型
     */
    private static final String SUCCESS_TYPE = "success_type";

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

    /**
     * 自动评论时间
     */
    private static final String AUTO_COMMENT_AT = "auto_comment_at";

    /**
     * 卡券订单自提码code
     */
    private static final String CARD_COUPON_ORDER_CODE = "cardCouponOrderCode";

    private static final String GLOBAL_SEARCH = "globalSearch";

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

    /**
     * 订单已关闭
     */
    private static final Integer ORDER_CLOSE_STATUS = 6;

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

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

    /**
     * 申请退款
     */
    private static final Integer HAS_AFTER_SALE_STATUS = 1;

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

    @Override
    public BaseIndexOrder buildIndexOrder(Order order) {
        RetailIndexOrder indexOrder = mapper.map(order, RetailIndexOrder.class);
        indexOrder.setOrderId(order.getId());
        buildBaseInfo(indexOrder, order);
        buildOrderInfo(indexOrder, order);
        buildExtraMapInfo(indexOrder, order);
        buildPerformanceInfo(indexOrder, order);
        buildPayInfo(indexOrder, order);
        return indexOrder;
    }

    private void buildBaseInfo(RetailIndexOrder indexOrder ,Order order) {
        if (!StringUtils.isEmpty(indexOrder.getMobile())) {
            String mobile = indexOrder.getMobile();
            if (mobile.length() > 3) {
                String tail = mobile.substring(mobile.length() - 4);
                indexOrder.setUserMobile(mobile + ";" + tail);
            }
        }
        // 设置是否退款完成
        indexOrder.setRefundCompleted(0);
        if (checkStatus(order.getStatus(), 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.getCompletedAt())) {
            indexOrder.setSearchCompletedAt(order.getCompletedAt());
        }
    }

    private void buildPayInfo(RetailIndexOrder indexOrder, Order order) {
        if (order != null) {
            String payInfo = order.getPayInfo();
            if (!StringUtils.isEmpty(payInfo)) {
                Map<String, Object> jsonMap = JSON.parseObject(payInfo);
                Object useWallet = jsonMap.get(USE_WALLET);
                if (!StringUtils.isEmpty(useWallet)) {
                    indexOrder.setUseWallet(Integer.valueOf(useWallet.toString()));
                }
                if (!StringUtils.isEmpty(jsonMap.get(WALLET_AMOUNT))) {
                    Object walletAmount = jsonMap.get(WALLET_AMOUNT);
                    // 兼容零售老数据迁移
                    if (walletAmount instanceof BigDecimal) {
                        BigDecimal aDouble = (BigDecimal) walletAmount;
                        indexOrder.setWalletAmount(aDouble.multiply(new BigDecimal("100")).intValue());
                    } else {
                        indexOrder.setWalletAmount(Integer.valueOf(walletAmount.toString()));
                    }
                }
            }
        }
    }

    private void buildOrderInfo(RetailIndexOrder indexOrder, Order order) {
        if (order != null) {
            // 获取订单下所有的商品信息
            if (!StringUtils.isEmpty(order.getItemInfo())) {
                String itemInfo = order.getItemInfo();
                List<OrderItem> itemList;
                if (Objects.equals(itemInfo, CommonConstants.ITEM_FLAG)) {
                    itemList = orderItemDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
                } else {
                    try {
                        itemList = JSONArray.parseArray(itemInfo, OrderItem.class);
                    } catch (JSONException e) {
                        logger.error(
                                "RetailBusinessHandler[buildBaseInsertInfo]itemInfo convert json failed,request:{},cause by:{}",
                                itemInfo, e);
                        throw new RuntimeException("转换商品信息异常");
                    }
                }
                if (!CollectionUtils.isEmpty(itemList)) {
                    List<String> itemNames = itemList.stream().map(OrderItem::getItemName).collect(Collectors.toList());
                    indexOrder.setSearchItemName(org.apache.commons.lang3.StringUtils.join(itemNames, ","));
                    indexOrder.setBrandSignList(itemList.stream().map(OrderItem::getBrandSign).collect(Collectors.toList()));
                    indexOrder.setItemBarcodeList(itemList.stream().map(OrderItem::getItemBarcode).collect(Collectors.toList()));
                }
            }
            if (!StringUtils.isEmpty(order.getDiscountInfo())) {
                String discount = order.getDiscountInfo();
                try {
                    List<InnerOrderDiscount> discountList = JSONArray.parseArray(discount, InnerOrderDiscount.class);
                    List<String> discountNames = discountList.stream().map(InnerOrderDiscount::getDiscountName).collect(
                            Collectors.toList());
                    indexOrder.setDiscountNameList(discountNames);
                } catch (Exception e) {
                    logger.error("[buildOrderInfo]convert discountName failed!orderNo:{},cause by:{}",
                            order.getOrderNo(), e);
                }
            }
        }
    }


    private void buildExtraMapInfo(RetailIndexOrder indexOrder, Order order) {
        if (!CollectionUtils.isEmpty(order.getExtraMap())) {
            Map<String, Object> extraMap = order.getExtraMap();
            if (Objects.nonNull(extraMap.get(IS_INVOICE))) {
                String isInvoice = extraMap.get(IS_INVOICE).toString();
                indexOrder.setIsInvoice(Integer.valueOf(isInvoice));
            }
            if (Objects.nonNull(extraMap.get(GROUP_ORDER_INFO))) {
                Map<String, Object> groupOrderInfo = JSON.parseObject(extraMap.get(GROUP_ORDER_INFO).toString());
                if (!StringUtils.isEmpty(groupOrderInfo.get(SUCCESS_TYPE))) {
                    Integer successType = Integer.valueOf(groupOrderInfo.get(SUCCESS_TYPE).toString());
                    indexOrder.setSuccessType(successType);
                }
                if (!StringUtils.isEmpty(groupOrderInfo.get(GROUP_STATUS))) {
                    Integer groupStatus = Integer.valueOf(groupOrderInfo.get(GROUP_STATUS).toString());
                    indexOrder.setGroupStatus(groupStatus);
                }
            }
            if (!StringUtils.isEmpty(extraMap.get(AUTO_COMMENT_AT))) {
                Long autoCommentAt = Long.valueOf(extraMap.get(AUTO_COMMENT_AT).toString());
                indexOrder.setAutoCommentAt(new Date(autoCommentAt));
            }
            if (!StringUtils.isEmpty(extraMap.get(ORDER_SUB_INFO))) {
                Map<String, Object> orderSubinfo = JSON.parseObject(extraMap.get(ORDER_SUB_INFO).toString());
                // 零售业务当日流水单号：sortNum --> todayNo
                if (!StringUtils.isEmpty(orderSubinfo.get(SORT_NUM))) {
                    indexOrder.setTodayNo(orderSubinfo.get(SORT_NUM).toString());
                }
            }
            if (!StringUtils.isEmpty(extraMap.get(CARD_COUPON_ORDER_CODE))) {
                Map<String, Object> jsonObject = JSON.parseObject(extraMap.get(CARD_COUPON_ORDER_CODE).toString());
                if (!StringUtils.isEmpty(jsonObject.get(CODE))) {
                    indexOrder.setSelfTakeCode(Long.valueOf(jsonObject.get(CODE).toString()));
                }
            }
            if (!StringUtils.isEmpty(extraMap.get(GLOBAL_SEARCH))) {
                String globalSearch = extraMap.get(GLOBAL_SEARCH).toString();
                indexOrder.setGlobalSearch(globalSearch);
            }
        }
    }

    private void buildPerformanceInfo(RetailIndexOrder indexOrder, Order order) {
        RetailPerformanceHandler handle = this.performanceHandle.getPerformanceHandle(order.getPerformanceType());
        if (handle != null) {
            handle.buildPerformanceInfo(indexOrder, order);
        }
        if (!StringUtils.isEmpty(order.getPerformanceInfo())) {
            String performanceInfo = order.getPerformanceInfo();
            Map<String, Object> performanceMap = JSON.parseObject(performanceInfo);
            if (!CollectionUtils.isEmpty(performanceMap)) {
                Object sentAt = performanceMap.get(SENT_AT);
                if (!StringUtils.isEmpty(sentAt)) {
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                    // 兼容零售老数据迁移
                    if (sentAt instanceof Integer) {
                        indexOrder.setSentAt(new Date(Long.valueOf(sentAt + "000")));
                    }else {
                        try {
                            indexOrder.setSentAt(format.parse(sentAt.toString()));
                        } catch (ParseException e) {
                            logger.error(
                                    "RetailBusinessHandler[buildPerformanceInfo]sent_at convert failed,sentAt:{},orderNo:{} cause by:{}",
                                    sentAt, order.getOrderNo(), e);
                            throw new RuntimeException("发货时间参数异常");
                        }
                    }
                }
                Object express = performanceMap.get(EXPRESS);
                if (Objects.nonNull(express)) {
                    indexOrder.setThirdDeliveryExpress(Integer.valueOf(express.toString()));
                }
            }
        }
    }

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


    @Override
    public SearchSourceBuilder buildSearchSourceBuilder(SearchOrderQuery searchOrderQuery) {
        return null;
    }

    @Override
    public List<BaseIndexOrder> parseIndexOrder(SearchHit[] searchHits) {
        return null;
    }

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

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

}
