package cn.newfeifan.mall.module.trade.service.order;

import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.pojo.echarts.EChartsResult;
import cn.newfeifan.mall.module.distri.mq.message.order.DistriOrderMessage;
import cn.newfeifan.mall.module.distri.mq.message.order.OrderCalcMessage;
import cn.newfeifan.mall.module.pay.controller.admin.order.vo.PayOrderPageItemRespVO;
import cn.newfeifan.mall.module.trade.controller.admin.delivery.vo.expresstemplate.ShopBO;
import cn.newfeifan.mall.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
import cn.newfeifan.mall.module.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderDetailRespVO;
import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.newfeifan.mall.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;

import java.time.LocalDate;
import java.util.Collection;
import java.util.List;

import static java.util.Collections.singleton;

/**
 * 交易订单【读】 Service 接口
 *
 * @author 非繁源码
 */
public interface TradeOrderQueryService {

    // =================== Order ===================

    /**
     * 获得指定编号的交易订单
     *
     * @param id 交易订单编号
     * @return 交易订单
     */
    TradeOrderDO getOrder(Long id);

    /**
     * 获得指定用户，指定的交易订单
     *
     * @param userId 用户编号
     * @param id     交易订单编号
     * @return 交易订单
     */
    TradeOrderDO getOrder(Long userId, Long id);

    /**
     * 获得指定用户，指定活动，指定状态的交易订单
     *
     * @param userId     用户编号
     * @param combinationActivityId 活动编号
     * @param status     订单状态
     * @return 交易订单
     */
    TradeOrderDO getOrderByUserIdAndStatusAndCombination(Long userId, Long combinationActivityId, Integer status);

    /**
     * 获得订单列表
     *
     * @param ids 订单编号数组
     * @return 订单列表
     */
    List<TradeOrderDO> getOrderList(Collection<Long> ids);

    /**
     * 【管理员】获得交易订单分页
     *
     * @param reqVO 分页请求
     * @return 交易订单
     */
    PageResult<TradeOrderDO> getOrderPage(TradeOrderPageReqVO reqVO);

    /**
     * 获得订单统计
     *
     * @param reqVO 请求参数
     * @return 订单统计
     */
    TradeOrderSummaryRespVO getOrderSummary(TradeOrderPageReqVO reqVO);

    /**
     * 【会员】获得交易订单分页
     *
     * @param userId 用户编号
     * @param reqVO  分页请求
     * @return 交易订单
     */
    PageResult<TradeOrderDO> getOrderPage(Long userId, AppTradeOrderPageReqVO reqVO);

    /**
     * 【会员】获得交易订单数量
     *
     * @param userId       用户编号
     * @param status       订单状态。如果为空，则不进行筛选
     * @param commonStatus 评价状态。如果为空，则不进行筛选
     * @return 订单数量
     */
    Long getOrderCount(Long userId, Integer status, Boolean commonStatus);

    /**
     * 【前台】获得订单的物流轨迹
     *
     * @param id     订单编号
     * @param userId 用户编号
     * @return 物流轨迹数组
     */
    List<ExpressTrackRespDTO> getExpressTrackList(Long id, Long userId);

    /**
     * 【后台】获得订单的物流轨迹
     *
     * @param id 订单编号
     * @return 物流轨迹数组
     */
    List<ExpressTrackRespDTO> getExpressTrackList(Long id);

    /**
     * 【会员】在指定秒杀活动下，用户购买的商品数量
     *
     * @param userId     用户编号
     * @param activityId 活动编号
     * @return 秒杀商品数量
     */
    int getSeckillProductCount(Long userId, Long activityId);

    // =================== Order Item ===================

    /**
     * 获得指定用户，指定的交易订单项
     *
     * @param userId 用户编号
     * @param itemId 交易订单项编号
     * @return 交易订单项
     */
    TradeOrderItemDO getOrderItem(Long userId, Long itemId);

    /**
     * 获得交易订单项
     *
     * @param id 交易订单项编号 itemId
     * @return 交易订单项
     */
    TradeOrderItemDO getOrderItem(Long id);

    /**
     * 根据交易订单编号，查询交易订单项
     *
     * @param orderId 交易订单编号
     * @return 交易订单项数组
     */
    default List<TradeOrderItemDO> getOrderItemListByOrderId(Long orderId) {
        return getOrderItemListByOrderId(singleton(orderId));
    }

    /**
     * 根据交易订单编号数组，查询交易订单项
     *
     * @param orderIds 交易订单编号数组
     * @return 交易订单项数组
     */
    List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);

    /**
     * 根据状态获取订单数量, 不通过用户ID信息
     * @param status 订单状态
     * @return 数量
     */
    Long getOrderCount(Integer status);

    /**
     * 根据条件获取订单数量
     * @param reqVO 条件
     * @param status 订单状态
     * @return 数量
     */
    Long getOrderCount(Integer status, TradeOrderPageReqVO reqVO);

    /**
     * 根据状态获取订单数量, 不通过用户ID信息
     * @param status 订单状态
     * @param userId 用户ID
     * @return 数量
     */
    Long getOrderCount(Integer status,Long userId);


    /**
     * 补充订单编号以及商品图片
     * @param list 集合
     * @return 集合
     */
    List<PayOrderPageItemRespVO> getOrderNoAndPicUrl(List<PayOrderPageItemRespVO> list);


    /**
     * 获取商户订单总数
     * @param key key值
     * @return 数量
     */
    Integer getShopSalesVolume(Long key);

    /**
     * 获取所有订单信息, 已经完成的(已经经过收款7天之后的订单)
     * @return 集合
     */
    List<AppTradeOrderDetailRespVO> cancelOrderBySystem();


    /**
     * 查询当前系统的所有订单
     * @return 集合
     */
    List<DistriOrderMessage> queryAllOrder();

    /**
     * 查询当天系统的所有订单
     * @return 集合
     */
    List<DistriOrderMessage> queryDailyOrder();

    /**
     * 获取店铺信息
     * @return 店铺商户
     */
    ShopBO getShop();

    TradeOrderDO getOrderById(Long orderId);

    /**
     * 用来判断当前的这个订单中的商品是不是虚拟商品
     * @param orderItems 订单项
     * @return 0 是虚拟商品
     */
    Integer getSpuType(List<TradeOrderItemDO> orderItems);

    List<OrderCalcMessage> getOrderCalcMessage(List<DistriOrderMessage> respVos);

    /**
     * 获取状态为退款的订单
     * @param refundStatus 订单状态
     * @param reqVO 条件
     * @return 数量
     */
    Long getOrderCountByRefundStatus(Integer refundStatus, TradeOrderPageReqVO reqVO);

    /**
     * 获取状态为退款的订单
     * @param status 订单状态
     * @param userId 用户ID
     * @return 数量
     */
    Long getOrderCountByRefundStatus(Integer status, Long userId);

    /**
     * 根据选择的时间段获取对应的订单状态数量
     * @param startTime 开始时间段
     * @param endTime 结束时间段
     * @return 订单状态数量
     */
    EChartsResult getOrderCountWithMoney(LocalDate startTime, LocalDate endTime);

    /**
     * 手动开启计算订单分配权益(用于七天分配权益变更后)
     */
    void calc();
}
