package cn.iocoder.yudao.module.order.service.order;

import cn.iocoder.yudao.framework.apollo.core.event.QueryChannelInfoEvent;
import cn.iocoder.yudao.framework.mybatis.core.service.IService;
import cn.iocoder.yudao.module.ecw.dal.dataobject.region.RegionDO;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderException.OrderExceptionDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderItem.OrderItemDO;
import cn.iocoder.yudao.module.order.dto.OrderRemindExceptionDto;
import cn.iocoder.yudao.module.order.enums.OrderAirTimeEnum;
import cn.iocoder.yudao.module.order.enums.OrderSeaTimeEnum;
import cn.iocoder.yudao.module.order.param.OrderChangePriceParam;
import cn.iocoder.yudao.module.order.param.OrderControlLogParam;
import cn.iocoder.yudao.module.order.vo.order.*;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 订单 Service 接口
 *
 * @author 系统管理员
 */
public interface OrderBusinessService extends IService<OrderDO> {


    /**
     * 处理订单未报价异常
     *
     * @param orderId 订单ID
     */
    void handleOrderNoQuote(Long orderId);


    /**
     * 切换线路、渠道处理不可出渠道异常(注：此接口不会标记处理过不可出异常，会切换线路id或渠道id后重新判定，请在处理完异常后再调用)
     *
     * @param orderId            订单ID
     * @param channelId          渠道ID
     * @param channelId          线路id
     * @param channelPriceParams 品名自主定价
     */
    void handleOrderChannelException(Long orderId, Long channelId, Long lineId, List<OrderChangePriceParam> channelPriceParams);

    /**
     * 处理超重异常
     *
     * @param orderId            订单ID
     * @param channelPriceParams 品名自主定价
     */
    void handleOrderWeightOverrun(Long orderId, List<OrderChangePriceParam> channelPriceParams);

    /**
     * 处理单询异常品名自主定价，不定价不用调用此接口
     *
     * @param orderId            订单ID
     * @param inquiryPriceParams 品名自主定价
     */
    void handleOrderInquiryException(Long orderId, List<OrderChangePriceParam> inquiryPriceParams);


    /**
     * 处理渠道异常结束
     *
     * @param orderId   订单ID
     * @param channelId 渠道ID
     */
    void handleOrderChannelException(Long orderId, Long channelId);


    /**
     * 处理订单继续不可出特性渠道异常
     *
     * @param orderId 订单ID
     */
    void handleOrderChannelAttrException(Long orderId);

    /**
     * 处理订单渠道不可出特性异常
     *
     * @param orderId            订单ID
     * @param channelPriceParams 品名自主定价列表
     */
    void handleOrderChannelAttrException(Long orderId, List<OrderChangePriceParam> channelPriceParams);

    /**
     * 自动判断渠道不可出异常信息
     *
     * @param orderDO              订单详情
     * @param event                渠道详情
     * @param orderItemDO          订单品名
     * @param warehouseInInfoVO    入仓信息
     * @param type                 类型
     * @param orderExceptionDOList 渠道不可出异常
     */
    void createNoCanShipmentChannelException(OrderDO orderDO, QueryChannelInfoEvent event, OrderItemDO orderItemDO,
                                             WarehouseInInfoVO warehouseInInfoVO, Integer type, List<OrderExceptionDO> orderExceptionDOList);


    /**
     * 处理空运订单批量加价
     *
     * @param orderIds            订单ID列表
     * @param freightFee          运费
     * @param freightCurrencyId   运费货币
     * @param freightUnitId       运费计量单位id
     * @param clearanceFee        清关费
     * @param clearanceCurrencyId 清关费货币
     * @param clearanceUnitId     清关费计量单位id
     */
    void handleAirOrderBatchMarkup(Collection<Long> orderIds, BigDecimal freightFee, Integer freightCurrencyId, Long freightUnitId,
                                   BigDecimal clearanceFee, Integer clearanceCurrencyId, Long clearanceUnitId);

    /**
     * 处理订单重泡货异常
     *
     * @param orderId   订单ID
     * @param orderType 订单类型：1 普货 2 重货 3 泡货
     */
    void handleOrderHeavyBubble(Long orderId, Integer orderType);


    /**
     * 处理泡货异常(当确定订单为泡货时,使用此接口来更新订单为默认泡货，还是半抛)
     *
     * @param orderId    订单ID
     * @param pickleType 泡货类型 1 默认值 2 半泡(当订单为泡货时才使用此字段)
     */
    void handleOrderPickleType(Long orderId, Integer pickleType);



    /**
     * 空运订单价格刷新(待入仓、入仓中、已入仓-待出订单进行没日单价重定更新)
     *
     * @param orderDO 订单信息
     */
    void airOrderPriceRefresh(OrderDO orderDO);



    /**
     * 根据参数生成订单号，这里获取最新的订单编号，并保存记录
     *
     * @param objective              目的地
     * @param transportId            运输方式ID
     * @param isExternalWarehouse    是否外部仓
     * @param isConcentrateTransport 是否集运订单
     * @return 订单号
     */
    String saveOrUpdateOrderNo(RegionDO objective, Integer transportId, Boolean isExternalWarehouse, Boolean isConcentrateTransport);

    /**
     * 根据参数生成订单号，这里只获取最新的，不做数据库更新操作
     *
     * @param newOrderNo             当前最新编号
     * @param objective              目的地
     * @param transportId            运输方式ID
     * @param isExternalWarehouse    是否外部仓
     * @param isConcentrateTransport 是否集运订单
     * @return 订单号
     */
    String getNewOrderNo(String newOrderNo, RegionDO objective, Integer transportId, Boolean isExternalWarehouse, Boolean isConcentrateTransport);

    /**
     * 生成或修改订单信息的应收单
     *
     * @param orderDO 当前订单信息
     * @param type    1 生成应收 2 修改价格时同步更新应收(未生成应收不予执行)
     */
    boolean addOrderReceivable(OrderDO orderDO, Integer type);
    /**
     * 添加订单动态日志
     *
     * @param status  最新变更订单状态
     * @param orderDO 订单信息
     * @param type    0 正常主状态变更 1 拆单后创建的新订单  2 合单后创建的新订单
     *                3 特价-优惠申请通过 4 特价-管理折扣通过 5 特价-重货优惠通过 6 特价-泡货优惠通过
     *                7、订单修改审批通过 8 入仓修改审批通过 9 佣金设置审批通过
     */
    void addOrderTimeLog(Integer status, OrderDO orderDO, Integer type);

    /**
     * 添加订单动态日志
     *
     * @param orderDO          订单信息
     * @param orderAirTimeEnum {@link OrderAirTimeEnum} 空运动态枚举值
     * @param reasonZh         业务说明
     * @param reasonEn         业务说明
     * @param estTime          预计时间
     * @param businessTime     业务时间
     * @param now              当前执行时间
     * @param timeId           动态id
     */
    void addAirOrderTimeLog(OrderDO orderDO, OrderAirTimeEnum orderAirTimeEnum, String reasonZh, String reasonEn,
                            Date estTime, Date businessTime, Date now, Long timeId);

    /**
     * 添加订单动态日志
     *
     * @param orderDO          订单信息
     * @param orderSeaTimeEnum {@link OrderSeaTimeEnum} 空运动态枚举值
     * @param reasonZh         业务说明  提货动态中这个参数为提货件数
     * @param reasonEn         业务说明  提货动态中这个参数为提货剩余件数
     * @param estTime          预计时间
     * @param businessTime     业务时间
     * @param now              当前执行时间
     * @param timeId           动态id
     */
    void addSeaOrderTimeLog(OrderDO orderDO, OrderSeaTimeEnum orderSeaTimeEnum, String reasonZh, String reasonEn,
                            Date estTime, Date businessTime, Date now, Long timeId);

    /**
     * 添加订单动态日志
     *
     * @param orderIdList      订单id列表
     * @param orderAirTimeEnum {@link OrderAirTimeEnum} 空运动态枚举值
     * @param reasonZh         业务说明
     * @param reasonEn         业务说明
     * @param estTime          预计时间
     * @param businessTime     业务时间
     * @param now              当前执行时间
     */
    void addAirOrderTimeLog(Collection<Long> orderIdList, OrderAirTimeEnum orderAirTimeEnum, String reasonZh, String reasonEn,
                            Date estTime, Date businessTime, Date now);


    /**
     * 添加订单动态日志
     *
     * @param orderIdList      订单id列表
     * @param orderSeaTimeEnum {@link OrderSeaTimeEnum} 空运动态枚举值
     * @param reasonZh         业务说明
     * @param reasonEn         业务说明
     * @param estTime          预计时间
     * @param businessTime     业务时间
     * @param now              当前执行时间
     */
    void addSeaOrderTimeLog(Collection<Long> orderIdList, OrderSeaTimeEnum orderSeaTimeEnum, String reasonZh, String reasonEn,
                            Date estTime, Date businessTime, Date now);

    /**
     * 添加订单动态日志
     *
     * @param containerNumber  自编号
     * @param orderAirTimeEnum {@link OrderAirTimeEnum} 空运动态枚举值
     * @param reasonZh         业务说明
     * @param reasonEn         业务说明
     * @param estTime          预计时间
     * @param businessTime     业务时间
     * @param now              当前执行时间
     */
    void addAirOrderTimeLog(String containerNumber, OrderAirTimeEnum orderAirTimeEnum, String reasonZh, String reasonEn,
                            Date estTime, Date businessTime, Date now);

    /**
     * 添加订单动态日志
     *
     * @param status       最新变更订单状态
     * @param orderDO      订单信息
     * @param type         0 正常主状态变更 1 拆单后创建的新订单  2 合单后创建的新订单
     *                     3 特价-优惠申请通过 4 特价-管理折扣通过 5 特价-重货优惠通过 6 特价-泡货优惠通过
     *                     7、订单修改审批通过 8 入仓修改审批通过 9 佣金设置审批通过
     * @param businessTime 业务时间
     */
    void addOrderTimeLog(Integer status, OrderDO orderDO, Integer type, Date businessTime);

    /**
     * 添加订单动态日志
     *
     * @param status       最新变更订单状态
     * @param orderDO      订单信息
     * @param type         0 正常主状态变更 1 拆单后创建的新订单  2 合单后创建的新订单
     *                     3 特价-优惠申请通过 4 特价-管理折扣通过 5 特价-重货优惠通过 6 特价-泡货优惠通过
     *                     7、订单修改审批通过 8 入仓修改审批通过 9 佣金设置审批通过
     * @param businessTime 业务时间
     * @param now          业务系统同一创建时间
     */
    void addOrderTimeLog(Integer status, OrderDO orderDO, Integer type, Date businessTime, Date now);
    /**
     * 更新不阻塞流程的订单异常信息
     *
     * @param orderId                订单ID
     * @param remindExceptionDtoList 异常说明列表 (空值即清空)
     */
    void handleOrderRemindException(Long orderId, List<OrderRemindExceptionDto> remindExceptionDtoList);

    /**
     * 手动更新订单收发货人信息(谨慎执行)
     */
    void updateOrderCustomer(List<String> orderNumbers);

    void addOrderCustomerService(OrderDO order, int customerType);
    /**
     * 手动更新订单价格(谨慎执行)
     *
     * @param orderNumbers 订单编号列表
     * @param isResetPrice 是否强制重订价
     */
    void updateOrderPrice(List<String> orderNumbers, Boolean isResetPrice);

    /**
     * 手动更新订单运费与清关费应收(谨慎执行)
     *
     * @param orderNo 订单编号列表
     */
    void updateReceivable(String orderNo);


    /**
     * 手动补全订单的原始重泡货基数
     *
     * @param orderNumbers 订单编号列表
     */
    void updateOrderOrgWeightUnitAndOrgVolumeUnit(List<String> orderNumbers);

    /**
     * 添加订单操作日志
     *
     * @param orderId 订单ID
     * @param msg     描述
     * @param note    备注 {@link ApplyInfoVO 的详情集合} 不要传空字符串
     */
    void addOrderOperateLog(Long orderId, String msg, String note);
    /**
     * 添加订单操作日志
     *
     * @param orderId 订单ID
     * @param type    类型 订单操作、入仓操作等(直接字符串类型说明)
     * @param msg     描述
     * @param note    备注 {@link ApplyInfoVO 的详情集合} 不要传空字符串
     */
    void addOrderOperateLog(Long orderId, String type, String msg, String note);

    /**
     * 添加订单操作日志
     *
     * @param orderId         订单ID
     * @param type            类型 订单操作、入仓操作等(直接字符串类型说明)
     * @param msg             描述
     * @param applyInfoVOList 备注(note) {@link ApplyInfoVO 的详情集合}
     */
    void addOrderOperateLog(Long orderId, String type, String msg, List<ApplyInfoVO> applyInfoVOList);

    /**
     * 活动订单应收未核销数量
     *
     * @param orderIds 订单id列表
     * @return
     */
    long getUnWriteOffCount(Collection<Long> orderIds);


    /**
     * 订单控货日志添加
     *
     * @param orderId    订单id
     * @param typeKey    控货日志类型key值：1 新增控货 2 更新控货 3 转移控货 4 放货 5 放货复核 6 放货取消  7 放货修改申请 8 放货反复核申请
     *                   9 被调货申请 10 调货申请 11 取消放货申请 12 放货修改失败 13 放货反复核失败 14 被调货失败 15 调货失败 16 取消放货失败 17 放货修改通过
     *                   18 放货反复核通过 19 调货审批通过 20 被调货审批通过 21 取消放货审批通过
     * @param type       控货操作类型
     * @param msg        控货操作业务详情
     * @param approvalId 审批ID
     */
    void createOrderControlLog(Long orderId, Integer typeKey, String type, String msg, Long approvalId);

    void createOrderControlLogs(List<OrderControlLogParam> controlLogParams);

    void orderCouponUpdate(OrderDO orderDO, String msg);


    /**
     * 清单费用计算
     *
     * @param userId                      操作用户ID
     * @param orderDO                     订单主体
     * @param consignorCustomerId         发货客户ID
     * @param consigneeCustomerId         收货客户ID
     * @param consignorCustomerContactsId 发货客户联系人ID
     * @param consigneeCustomerContactsId 收货客户联系人ID
     * @param orderItemDOList             订单商品项列表
     * @param type                        类型 ： 1 新增 2 修改 3 实测入仓信息 4 合单 5 拆单 6 处理未报价异常 7 特价申请 8 订单货值修改
     *                                    9 处理重泡货异常 10 已入仓订单修改重订价 11 处理渠道异常 12 处理单询异常 13 处理超重异常 14 批量加价 15 完成入仓
     *                                    16 分拣完成锁定价格 20 强制重订价格  30 空运订单每日定时更新价格 40 订单异常处理完成更新计价 50 更新订单优惠信息
     **/
    void costCalculation(String userId, OrderDO orderDO, Long consignorCustomerId, Long consigneeCustomerId,
                         Long consignorCustomerContactsId, Long consigneeCustomerContactsId,
                         List<OrderItemDO> orderItemDOList, Integer type);


    void updateItem(OrderItemDO orderItemDO);
}
