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

import com.github.dozermapper.core.Mapper;
import com.zm.order.tool.server.component.BusinessHandlerHolder;
import com.zm.order.tool.server.constants.CommonConstants;
import com.zm.order.tool.server.dao.RefundItemDao;
import com.zm.order.tool.server.dto.OrderDTO;
import com.zm.order.tool.server.dto.OrderDetailDTO;
import com.zm.order.tool.server.dto.RefundDTO;
import com.zm.order.tool.server.dto.RefundItemDTO;
import com.zm.order.tool.server.enums.BizTypeEnum;
import com.zm.order.tool.server.handler.BusinessHandler;
import com.zm.order.tool.server.model.RefundItem;
import com.zm.order.tool.server.query.RefundItemQuery;
import com.zm.order.tool.server.query.RefundQuery;
import com.zm.order.tool.server.response.OrderDetailVO;
import com.zm.order.tool.server.response.OrderItemVO;
import com.zm.order.tool.server.response.OrderVO;
import com.zm.order.tool.server.response.RefundVO;
import com.zm.order.tool.server.service.RefundService;
import com.zm.order.tool.server.utils.ConvertUtils;
import com.zm.util.dto.Result;
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 java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 订单转换类 用于转换
 * @Author: ph
 * @Date: 2019/11/13 09:53
 */
@Component
public class BuyerOrderConverter {

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

    @Autowired
    private Mapper mapper;
    @Autowired
    private RefundItemDao refundItemDao;
    @Autowired
    private BusinessHandlerHolder businessHandlerHolder;
    @Autowired
    private RefundService refundService;

    public OrderDetailVO convert(OrderDetailDTO orderDetailDTO) {
        OrderDetailVO vo = mapper.map(orderDetailDTO, OrderDetailVO.class);
        vo.setOrderAddr(vo.getAddr());
        Map<String, Object> performanceInfo = this.getPerformanceInfo(mapper.map(orderDetailDTO, OrderDTO.class));
        if (!CollectionUtils.isEmpty(performanceInfo)) {
            Map<String, Object> performanceInfoMap = vo.getPerformanceInfoMap();
            if (CollectionUtils.isEmpty(performanceInfoMap)) {
                performanceInfoMap = new HashMap<>(performanceInfo.size());
            }
            performanceInfoMap.putAll(performanceInfo);
            vo.setPerformanceInfoMap(performanceInfoMap);
        }

        // 多人点餐订单设置商品归属
        this.setItemOwner(vo);
        // 设置退款单信息
        this.setRefundInfo(vo);
        return vo;
    }

    public Map<String, Object> getPerformanceInfo(OrderDTO orderDto) {
        if (orderDto != null) {
            return orderDto.getPerformanceInfoMap();
        }
        return Collections.emptyMap();
    }

    public void setRefundInfo(OrderVO orderVO) {
        OrderDTO orderDTO = buildOrderParam(orderVO);
        List<RefundVO> refundVOList = new ArrayList<>(5);
        BusinessHandler handler = businessHandlerHolder.orderGenerator(orderVO.getBizType());
        List<RefundDTO> refundList = this.getRefundList(orderDTO);
        if (!CollectionUtils.isEmpty(refundList)) {
            int refundAmount = 0;
            for (RefundDTO refundDTO : refundList) {
                RefundVO refundVO = mapper.map(refundDTO, RefundVO.class);
                refundVO.setRefundStatus(refundDTO.getStatus());
                refundVOList.add(refundVO);
                refundAmount += handler.getRefundAmount(refundDTO);
            }
            orderVO.setRefundList(refundVOList);
            orderVO.setRefundAmount(refundAmount);
        }

    }

    public List<RefundDTO> getRefundList(OrderDTO orderDTO) {
        if (!Objects.equals(CommonConstants.REFUND_CONFIRM, orderDTO.getRefundFlag())) {
            return Collections.emptyList();
        }
        List<RefundDTO> refundDTOList = queryRefundList(orderDTO);
        this.setRefundItemInfo(refundDTOList);
        return refundDTOList;
    }

    private List<RefundDTO> queryRefundList(OrderDTO orderDTO) {
        RefundQuery refundQuery = this.buildRefundQuery(orderDTO);
        Result<List<RefundDTO>> refundListResult = refundService.listRefund(refundQuery);
        if (!refundListResult.isStatus()) {
            throw new RuntimeException(refundListResult.getMessage());
        }
        return refundListResult.getData();
    }

    public RefundQuery buildRefundQuery(OrderDTO orderDTO) {
        RefundQuery refundQuery = new RefundQuery();
        refundQuery.setPageNo(1);
        refundQuery.setPageSize(100);
        refundQuery.setUserId(orderDTO.getUserId());
        refundQuery.setOrderNo(orderDTO.getOrderNo());
        return refundQuery;
    }

    public void setRefundItemInfo(List<RefundDTO> refundList) {
        this.setRefundItemInfo1(refundList);
    }

    public void setRefundItemInfo1(List<RefundDTO> refundList) {
        if (!CollectionUtils.isEmpty(refundList)) {
            List<String> refundNoList = refundList.stream().map(RefundDTO::getRefundNo).collect(Collectors.toList());
            List<RefundItem> refundItemList = queryRefundItemList(refundNoList);
            if (!CollectionUtils.isEmpty(refundItemList)) {
                Map<String, List<RefundItem>> refundItemMap = refundItemList.stream().collect(
                        Collectors.groupingBy(RefundItem::getRefundNo));
                for (RefundDTO refundDTO : refundList) {
                    if (!CollectionUtils.isEmpty(refundItemMap.get(refundDTO.getRefundNo()))) {
                        List<RefundItem> refundItems = refundItemMap.get(refundDTO.getRefundNo());
                        refundDTO.setRefundItemList(ConvertUtils.convertList(refundItems, RefundItemDTO.class));
                    }
                }
            }
        }
    }

    private List<RefundItem> queryRefundItemList(List<String> refundNoList) {
        RefundItemQuery query = new RefundItemQuery();
        query.setPageSize(1);
        query.setPageSize(100);
        query.setRefundNoList(refundNoList);
        return refundItemDao.selectList(query);
    }

    private OrderDTO buildOrderParam(OrderVO orderVo) {
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setUserId(orderVo.getUserId());
        orderDTO.setOrderNo(orderVo.getOrderNo());
        orderDTO.setRefundFlag(orderVo.getRefundFlag());
        orderDTO.setRefundCompleted(orderVo.getRefundCompleted());
        return orderDTO;
    }

    public void setItemOwner(OrderVO orderVo) {
        // 多人点餐场景
        if (Objects.equals(CommonConstants.MULTI_USER_ORDER, orderVo.getOrderSubType())) {
            BizTypeEnum bizType = BizTypeEnum.getValue(orderVo.getBizType());
            if (bizType != null) {
                switch (bizType) {
                    case CY:
                    case CATERING:
                    case MEAL_MATE:
                        rebuildItemOwner(orderVo);
                        break;
                    default:
                }
            }
        }
    }

    private static final String REAL_USER_ID = "realUserId";

    private void rebuildItemOwner(OrderVO orderVo) {
        List<OrderItemVO> itemList = orderVo.getItemList();
        if (!CollectionUtils.isEmpty(itemList)) {
            itemList.forEach(item -> {
                Map<String, Object> extraMap = item.getExtraMap();
                if (!CollectionUtils.isEmpty(extraMap) && Objects.nonNull(extraMap.get(REAL_USER_ID))) {
                    Long userId = Long.valueOf(extraMap.get(REAL_USER_ID).toString());
                    item.setUserId(userId);
                }
            });
        }
    }
}
