package com.cf.imes.module.executor.dal.mysql.order;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.cf.imes.framework.common.enums.DeletedCodeEnum;
import com.cf.imes.framework.common.enums.OrderPackageStatusEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.framework.mybatis.core.query.QueryWrapperX;
import com.cf.imes.framework.organ.core.aop.OrganIgnore;
import com.cf.imes.module.executor.controller.admin.manage.pack.vo.PackPageReqVO;
import com.cf.imes.module.executor.controller.admin.manage.pack.vo.PackRespVO;
import com.cf.imes.module.executor.controller.admin.manage.pack.vo.PrintOrderPackRespVO;
import com.cf.imes.module.executor.controller.admin.manage.query.vo.productionStatus.OrderPlatePageReqVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.LabelOrderData;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderCountProducePeriodRespVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderOverdueRespVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderPageReqVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderPlanPlateNumAndAreaRespVO;
import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds;
import com.cf.imes.module.executor.controller.admin.plan.vo.*;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderPackNumDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderPlateNumAndAreaDO;
import com.cf.imes.module.executor.enums.OrderDeletedEnum;
import com.cf.imes.module.executor.enums.OrderStatusEnum;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static com.cf.imes.module.executor.dal.dataobject.order.OrderDO.PARENT_ID_ROOT;

/**
 * 订单表 order_{N} Mapper
 *
 * @author 晨丰科技
 */
@Mapper
public interface OrderMapper extends BaseMapperX<OrderDO> {

    default PageResult<OrderDO> selectPage(OrderPageReqVO reqVO) {
        LambdaQueryWrapperX<OrderDO> query = new LambdaQueryWrapperX<OrderDO>()
                .eqIfPresent(OrderDO::getParentId, reqVO.getParentNo())
                .likeIfPresent(OrderDO::getId, reqVO.getId() == null ? null : reqVO.getId())
                .betweenIfPresent(OrderDO::getDeliveryDate, reqVO.getDeliveryDate())
                .eqIfPresent(OrderDO::getApiOrderId, reqVO.getApiOrderId())
                .betweenIfPresent(OrderDO::getOrderDate, reqVO.getOrderDate())
                .eqIfPresent(OrderDO::getOrderType, reqVO.getOrderType())
                .eqIfPresent(OrderDO::getOrderSort, reqVO.getOrderSort())
                .eqIfPresent(OrderDO::getDataType, reqVO.getDataType())
                .eqIfPresent(OrderDO::getStatus, reqVO.getStatus())
                .likeIfPresent(OrderDO::getCustomOrderNo, reqVO.getCustomOrderNo())
                .eqIfPresent(OrderDO::getCustomer, reqVO.getCustomer())
                .likeIfPresent(OrderDO::getAddress, reqVO.getAddress())
                .eqIfPresent(OrderDO::getPhoneNumber, reqVO.getPhoneNumber())
                .likeIfPresent(OrderDO::getDealer, reqVO.getDealer())
                .eqIfPresent(OrderDO::getDealerPhoneNumber, reqVO.getDealerPhoneNumber())
                .eqIfPresent(OrderDO::getSalesman, reqVO.getSalesman())
                .eqIfPresent(OrderDO::getSplitter, reqVO.getSplitter())
                .eqIfPresent(OrderDO::getRemark, reqVO.getRemark())
                .eqIfPresent(OrderDO::getOrganId, reqVO.getOrganId())
                .eqIfPresent(OrderDO::getDeleted, reqVO.getDeleted())
                .betweenIfPresent(OrderDO::getCreateTime, reqVO.getCreateTime())
                .eq(OrderDO::getParentId, PARENT_ID_ROOT);

        if (reqVO.getOrder() == null) {
            query.orderByDesc(OrderDO::getId);
        } else {
            if (reqVO.getOrder().equals("ascend")) {
                switch (reqVO.getField()) {
                    case "id" -> query.orderByAsc(OrderDO::getId);
                    case "customOrderNo" -> query.orderByAsc(OrderDO::getCustomOrderNo);
                    case "orderDate" -> query.orderByAsc(OrderDO::getOrderDate);
                    case "deliveryDate" -> query.orderByAsc(OrderDO::getDeliveryDate);
                    case "apiOrderId" -> query.orderByAsc(OrderDO::getApiOrderId);
                    default -> {
                        // default不排序
                    }
                }
            } else if (reqVO.getOrder().equals("descend")) {
                switch (reqVO.getField()) {
                    case "id" -> query.orderByDesc(OrderDO::getId);
                    case "customOrderNo" -> query.orderByDesc(OrderDO::getCustomOrderNo);
                    case "orderDate" -> query.orderByDesc(OrderDO::getOrderDate);
                    case "deliveryDate" -> query.orderByDesc(OrderDO::getDeliveryDate);
                    case "apiOrderId" -> query.orderByDesc(OrderDO::getApiOrderId);
                    default -> {
                        // default不排序
                    }
                }
            }
        }

        return selectPage(reqVO, query);
    }

    /**
     * 分页查询已作废订单
     * @param reqVO
     * @return
     */
    default PageResult<OrderDO> selectDeletedPage(OrderPageReqVO reqVO) {
        LambdaQueryWrapperX<OrderDO> query = new LambdaQueryWrapperX<OrderDO>()
                .likeIfPresent(OrderDO::getId, reqVO.getId() == null ? null : reqVO.getId())
                .betweenIfPresent(OrderDO::getDeliveryDate, reqVO.getDeliveryDate())
                .betweenIfPresent(OrderDO::getOrderDate, reqVO.getOrderDate())
                .eqIfPresent(OrderDO::getStatus, reqVO.getStatus())
                .likeIfPresent(OrderDO::getCustomOrderNo, reqVO.getCustomOrderNo())
                .likeIfPresent(OrderDO::getDealer, reqVO.getDealer())
                .likeIfPresent(OrderDO::getAddress, reqVO.getAddress())
                .eqIfPresent(OrderDO::getDealerPhoneNumber, reqVO.getDealerPhoneNumber())
                .eqIfPresent(OrderDO::getDeleted, DeletedCodeEnum.DELETED.getStatus())
                .betweenIfPresent(OrderDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(OrderDO::getRootId)
                .orderByAsc(OrderDO::getId);

        return selectPage(reqVO, query);
    }

    /**
     * 分页查询主单id（带子单过滤）
     *
     * @param page
     * @param reqVO
     * @return
     */
    IPage<Long> selectMainOrderIds(@Param("page") IPage<OrderDO> page, @Param("reqVO") OrderPageReqVO reqVO);

    /**
     * 查询子单列表
     *
     * @param reqVO
     * @param parentIds
     * @return
     */
    List<Long> selectChildIdList(@Param("reqVO") OrderPageReqVO reqVO, @Param("parentIds") List<Long> parentIds);

    IPage<OrderRespVOCopy> selectOrderPage(@Param("page") IPage<OrderRespVOCopy> page, @Param(Constants.WRAPPER) Wrapper<OrderDO> wrapper);


    Map<String, Object> selectDynamicSqlString(@Param("sqlStr") String sqlStr);


    // 查找订单
    default List<OrderDO> selectOrder(Long id, Long organId) {
        return selectList(new LambdaQueryWrapperX<OrderDO>()
                .eqIfPresent(OrderDO::getId, id)
                .eqIfPresent(OrderDO::getOrganId, organId));
    }

    // 修改订单状态 单个
    default int updateOrderStatus(Long id, Integer status, Long organId) {
        return update(new LambdaUpdateWrapper<OrderDO>()
                .set(OrderDO::getStatus, status)
                .eq(OrderDO::getId, id)
//                .eq(OrderDO::getDeleted, 0)
                .eq(OrderDO::getOrganId, organId));
    }

    // 查询单个订单
    default OrderDO selectOrderOne(Long id, Long organId) {
        return selectOne(new LambdaQueryWrapper<OrderDO>()
                .eq(OrderDO::getOrganId, organId)
                .eq(OrderDO::getId, id));
    }

    // 删除状态为条件，查询订单
    default OrderDO selectOrderOne(Long id, Long organId, Integer deleted) {
        return selectOne(new LambdaQueryWrapper<OrderDO>()
                .eq(OrderDO::getId, id)
                .eq(OrderDO::getOrganId, organId)
                .eq(OrderDO::getDeleted, deleted));
    }

    // 批量查询订单
    default List<OrderDO> selectOrderList(Collection<Long> ids, Long organId) {
        return selectList(new LambdaQueryWrapper<OrderDO>()
                .in(OrderDO::getId, ids)
                .eq(OrderDO::getOrganId, organId));
    }

    // 修改删除状态
    default int updateOrderDeleted(Long id, Integer deleted, Long organId) {
        return update(new LambdaUpdateWrapper<OrderDO>()
                .set(OrderDO::getDeleted, deleted)
                .eq(OrderDO::getId, id)
                .eq(OrderDO::getOrganId, organId));
    }


    List<OrderRespVOCopy> selectOrderListByIds(@Param("orderIds") List<Long> orderIds, @Param("organId") Long organId);


    /**
     * 查询今日要完成订单
     *
     * @param orderDate
     * @param organId
     * @param page
     * @return
     */
    IPage<OrderOverdueRespVO> selectOrderNear(@Param("orderDate") LocalDate orderDate,
                                              @Param("organId") Long organId,
                                              @Param("page") IPage<OrderOverdueRespVO> page);


    /**
     * 查询预期订单
     *
     * @param today
     * @param organId
     * @param page
     * @return
     */
    IPage<OrderOverdueRespVO> selectOrderOverdue(@Param("today") LocalDate today,
                                                 @Param("organId") Long organId,
                                                 @Param("page") IPage<OrderOverdueRespVO> page);

    /**
     * 订单数量统计
     */
    default Integer selectOrderCount(Long organId) {
        return Math.toIntExact(selectCount(new LambdaQueryWrapperX<OrderDO>()
                .eqIfPresent(OrderDO::getOrganId, organId)
                .eq(OrderDO::getDeleted, 0)));
    }

    /**
     * 今日新增订单总数统计
     */
    default Integer selectOrderCountToday(Long organId) {
        return Math.toIntExact(selectCount(new LambdaQueryWrapperX<OrderDO>()
                .eqIfPresent(OrderDO::getOrganId, organId)
                .eq(OrderDO::getOrderDate, LocalDate.now())));

    }

    /**
     * 今日完成订单总数统计
     */
    default Integer selectOrderCountTodayFinish(Long organId) {
        return Math.toIntExact(selectCount(new LambdaQueryWrapperX<OrderDO>()
                .eqIfPresent(OrderDO::getOrganId, organId)
                .between(OrderDO::getFinishTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN), LocalDateTime.of(LocalDate.now(), LocalTime.MAX))));
    }

    /**
     * 生产中订单总数
     */
    default Integer selectOrderCountProduce(Long organId) {
        return Math.toIntExact(selectCount(new LambdaQueryWrapperX<OrderDO>()
                .eqIfPresent(OrderDO::getOrganId, organId)
                .eq(OrderDO::getStatus, OrderStatusEnum.IN_PRODUCTION.getStatus())));
    }

    /**
     * 生产中生产平方数
     *
     * @param organId
     * @return
     */
    Integer selectOrderSquareProduce(@Param("organId") Long organId);

    //    订单单量
    @OrganIgnore
    List<OrderCountProducePeriodRespVO> selectOrderCountProducePeriod(@Param("organId") Long organId,
                                                                      @Param("startTime") String startTime, @Param("endTime") String endTime);

    //    物理删除订单
    default int deleteOrder(Long id, Long organId) {
        return delete(new LambdaQueryWrapperX<OrderDO>()
                .eq(OrderDO::getOrganId, organId)
                .eqIfPresent(OrderDO::getId, id));
    }

    /**
     * 查询修改时间距离当天日期为30的订单
     *
     * @param organId
     * @return
     */
    default List<Long> selectOrderListByUpdateTime(Long organId) {
        return selectList(new LambdaQueryWrapper<OrderDO>()
                .eq(OrderDO::getDeleted, OrderDeletedEnum.DELETED.getStatus())
                .lt(OrderDO::getUpdateTime, LocalDateTime.now().minusDays(30))
                .eq(OrderDO::getOrganId, organId)
        ).stream().map(OrderDO::getId).toList();
    }

    default int updateOrderListStatus(List<Long> orderIds, Integer status,Long organId) {
        return update(new LambdaUpdateWrapper<OrderDO>()
                .set(OrderDO::getStatus, status)
                .in(OrderDO::getId, orderIds)
                .eq(OrderDO::getDeleted, 0)
                .eq(OrderDO::getOrganId, organId));
    }



    List<OrderDO> selectOrderDataSource(@Param("filed") String filed,@Param("orderIds")  List<Long> orderIds,@Param("organId")  Long organId);


    List<OrderGoodsResp> selectGoodsListByGoodsId(@Param(Constants.WRAPPER) QueryWrapperX<OrderDO> queryWrapperX);


    default List<OrderDO> selectOrderPackList(List<Long> orderIds, Long organId) {
        return selectList(new LambdaQueryWrapperX<OrderDO>()
                .eq(OrderDO::getOrganId, organId)
                .eq(OrderDO::getDeleted, false)
                .in(OrderDO::getId,orderIds)
                .eq(OrderDO::getPackaged, OrderPackageStatusEnum.PACKAGED.getStatus()));

    }

    IPage<OrderRespVOCopy> selectFilterOrderPagePlate(@Param("page") IPage<OrderRespVOCopy> page, @Param(Constants.WRAPPER) Wrapper<OrderDO> wrapper);

    List<Long> selectFilterOrderPlateList(@Param(Constants.WRAPPER) QueryWrapperX<OrderDO> queryWrapperX);

    List<OrderIds> selectFilterGoodsPlateList(@Param(Constants.WRAPPER) QueryWrapperX<OrderDO> queryWrapperX);

    IPage<OrderGoodsResp> selectFilterGoodsPlatePage(@Param("page") IPage<OrderGoodsResp> page,@Param(Constants.WRAPPER) QueryWrapperX<OrderDO> queryWrapperX);


    List<Long> selectNoPlanOrderPlateCount(@Param(Constants.WRAPPER) Wrapper<OrderDO> wrapper,@Param("organId") Long organId);

    List<PlateResList> selectNoPlanOrderPlateList(@Param(Constants.WRAPPER) Wrapper<OrderDO> wrapper,@Param("pageNo") Integer pageNo,@Param("pageSize") Integer pageSize,@Param("organId") Long organId);


    default PageResult<OrderDO> selectProductionPage(OrderPlatePageReqVO pageReqVO) {
        return selectPage(pageReqVO, new LambdaQueryWrapperX<OrderDO>()
                .eqIfPresent(OrderDO::getId, pageReqVO.getOrderNo())
                .eqIfPresent(OrderDO::getCustomOrderNo, pageReqVO.getCustomOrderNo())
                .likeIfPresent(OrderDO::getCustomer, pageReqVO.getCustomer())
                .likeIfPresent(OrderDO::getAddress, pageReqVO.getAddress())
                .and(wrapper -> {
                    for (Long status : pageReqVO.getStatusList()) {
                        wrapper.or().eq(OrderDO::getStatus, status);
                    }
                })
                .orderByDesc(OrderDO::getCreateTime));
    }



    List<PackRespVO> selectOrderIdsTrue(@Param("createTime")  String createTime, @Param("organId") Long organId, @Param("orderId") Long orderId);



    List<PackRespVO>  selectOrderIdsFalse(@Param("createTime")  String createTime,@Param("organId")  Long organId, @Param("orderId") Long orderId);




    PrintOrderPackRespVO selectOrderPack(@Param("orderNo")Long orderNo, @Param("packageNo") Long packageNo, @Param("organId")  Long organId);


    /**
     * 查询分堆打包订单分页
     *
     * @param page
     * @param pageReqVO
     * @param organId
     * @return
     */
    IPage<PackRespVO> selectPackOrderList(@Param("page") IPage<PackRespVO> page, @Param("pageReqVO") PackPageReqVO pageReqVO, @Param("organId") Long organId);

    /**
     * 查询分堆打包子单列表
     *
     * @param pageReqVO
     * @param organId
     * @return
     */
    List<PackRespVO> selectPackOrderChildList(@Param("pageReqVO") PackPageReqVO pageReqVO, @Param("orderIds") List<Long> orderIds, @Param("organId") Long organId);


    List<LabelOrderData> selectLabelOrderData(@Param("orderIds") List<Long> orderIds,@Param("organId") Long organId);

    /**
     * 查询订单下已排单的板件数量和面积
     *
     * @param orderId
     * @return
     */
    OrderPlanPlateNumAndAreaRespVO selectPlannedPlateNumAndArea(@Param("orderId") Long orderId);

    /**
     * 批量统计已排单板件数量和面积
     *
     * @param orderIds 订单id列表
     * @return 每个订单的已排板件数量和面积
     */
    List<OrderPlanPlateNumAndAreaRespVO> selectPlannedPlateNumAndAreaGroup(@Param("orderIds") Collection<Long> orderIds);

    /**
     * 查询订单下板件数量和面积
     *
     * @param orderId
     * @param delete  是否删除
     * @return
     */
    OrderPlateNumAndAreaDO selectPlateNumAndArea(@Param("orderId") Long orderId, @Param("delete") Boolean delete);

    /**
     * 查询订单列表对应的已打包数
     *
     * @param orderIds
     * @return
     */
    List<OrderPackNumDO> selectPackPlateNum(@Param("orderIds") Collection<Long> orderIds);

    /**
     * 查询订单列表对应的已打包数
     *
     * @param orderIds
     * @return
     */
    List<OrderPackNumDO> selectPackPartsNum(@Param("orderIds") Collection<Long> orderIds);

    /**
     * 物理删除订单
     *
     * @return
     */
    int physicalDeleteByOrderIds(@Param("orderIds") List<Long> orderIds);
}
