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

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.BpmCreateServiceFactory;
import cn.iocoder.yudao.module.bpm.enums.WorkFlowEmus;
import cn.iocoder.yudao.module.bpm.resp.TaskResp;
import cn.iocoder.yudao.module.order.convert.orderWarehouseAdjust.OrderWarehouseAdjustConvert;
import cn.iocoder.yudao.module.order.convert.orderWarehouseApproval.OrderWarehouseApprovalConvert;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderWarehouseAdjust.OrderWarehouseAdjustDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderWarehouseApproval.OrderWarehouseApprovalDO;
import cn.iocoder.yudao.module.order.dal.mysql.order.OrderMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderWarehouseAdjust.OrderWarehouseAdjustMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderWarehouseApproval.OrderWarehouseApprovalMapper;
import cn.iocoder.yudao.module.order.enums.ApprovalResultStatusEnum;
import cn.iocoder.yudao.module.order.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.order.enums.OrderWarehouseApprovalTypeEnum;
import cn.iocoder.yudao.module.order.vo.orderWarehouseAdjust.OrderWarehouseAdjustBackVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseAdjust.OrderWarehouseAdjustLastStatusBackVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseApproval.OrderWarehouseApprovalBackVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseApproval.OrderWarehouseApprovalCreateReqVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseApproval.OrderWarehouseApprovalQueryVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseApproval.OrderWarehouseApprovalUpdateReqVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.order.enums.ErrorCodeConstants.*;

/**
 * 入仓单审核 Service 实现类
 *
 * @author yanghao
 */
@Service
@Validated
public class OrderWarehouseApprovalServiceImpl extends AbstractService<OrderWarehouseApprovalMapper, OrderWarehouseApprovalDO> implements OrderWarehouseApprovalService {

    @Resource
    private OrderWarehouseApprovalMapper orderWarehouseApprovalMapper;

    @Resource
    private BpmCreateServiceFactory bpmCreateServiceFactory;

    @Resource
    private OrderWarehouseAdjustMapper warehouseAdjustMapper;

    @Resource
    private OrderMapper orderMapper;

    @Override
    public Long createOrderWarehouseApproval(OrderWarehouseApprovalCreateReqVO createReqVO) {
        // 插入
        OrderWarehouseApprovalDO orderWarehouseApproval = OrderWarehouseApprovalConvert.INSTANCE.convert(createReqVO);
        orderWarehouseApprovalMapper.insert(orderWarehouseApproval);
        // 返回
        return orderWarehouseApproval.getId();
    }

    @Override
    public OrderWarehouseAdjustLastStatusBackVO adjustLastWithStatus(Long orderId, Integer lang) {


        List<OrderWarehouseAdjustDO> orderWarehouseAdjustDOList = warehouseAdjustMapper.selectByOrderId(orderId, lang);
        if (CollectionUtil.isNotEmpty(orderWarehouseAdjustDOList)) {

            OrderWarehouseAdjustDO orderWarehouseAdjustDO = orderWarehouseAdjustDOList.get(orderWarehouseAdjustDOList.size()-1);

            Long adjustId = orderWarehouseAdjustDO.getId();

            OrderWarehouseApprovalDO orderWarehouseApprovalDO = orderWarehouseApprovalMapper.selectOne(new LambdaQueryWrapperX<OrderWarehouseApprovalDO>()
                    .eq(OrderWarehouseApprovalDO::getType, 2)
                    .apply(true, "FIND_IN_SET ('" + adjustId + "',  order_ids)")
                    .orderByDesc(OrderWarehouseApprovalDO::getId).last("limit 1"));
            if (orderWarehouseApprovalDO != null) {
                OrderWarehouseAdjustBackVO orderWarehouseAdjustBackVO = OrderWarehouseAdjustConvert.INSTANCE.convert(orderWarehouseAdjustDO);
                OrderWarehouseApprovalBackVO orderWarehouseApprovalBackVO = OrderWarehouseApprovalConvert.INSTANCE.convert(orderWarehouseApprovalDO);

                OrderWarehouseAdjustLastStatusBackVO orderWarehouseAdjustLastStatusBackVO = new OrderWarehouseAdjustLastStatusBackVO();
                orderWarehouseAdjustLastStatusBackVO.setOrderWarehouseApprovalBackVO(orderWarehouseApprovalBackVO);
                orderWarehouseAdjustLastStatusBackVO.setOrderWarehouseAdjustBackVO(orderWarehouseAdjustBackVO);
                return orderWarehouseAdjustLastStatusBackVO;
            }
        }
        return null;
    }

    @Override
    public OrderWarehouseApprovalDO selectOne(Integer type, Long orderId) {
        return orderWarehouseApprovalMapper.selectOne(type, orderId);
    }

    @Override
    public void updateOrderWarehouseApproval(OrderWarehouseApprovalUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateOrderWarehouseApprovalExists(updateReqVO.getId());
        // 更新
        OrderWarehouseApprovalDO updateObj = OrderWarehouseApprovalConvert.INSTANCE.convert(updateReqVO);
        orderWarehouseApprovalMapper.updateById(updateObj);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long applyAndCreate(OrderWarehouseApprovalDO orderWarehouseApprovalDO, WorkFlowEmus workFlowEmus, String[] copyUserId) {

        //查看是否有退仓正在审批中
        String orderIds = orderWarehouseApprovalDO.getOrderIds();
        List<OrderWarehouseApprovalDO> orderWarehouseApprovalDOList = orderWarehouseApprovalMapper.selectList(new LambdaQueryWrapperX<OrderWarehouseApprovalDO>()
                .eq(OrderWarehouseApprovalDO::getOrderIds, orderIds)
                .eq(OrderWarehouseApprovalDO::getType, orderWarehouseApprovalDO.getType())
                .eq(OrderWarehouseApprovalDO::getStatus, ApprovalResultStatusEnum.processing.getValue()));
        if (CollectionUtil.isNotEmpty(orderWarehouseApprovalDOList)) {
            throw exception(WAREHOUSE_APPROVAL_APPLYING);
        }

        orderWarehouseApprovalDO.setStatus(ApprovalResultStatusEnum.processing.getValue());

        orderWarehouseApprovalMapper.insert(orderWarehouseApprovalDO);

        //查询编号
        String orderNo = null;
        try {
            if (OrderWarehouseApprovalTypeEnum.WAREHOUSE_IN_TRANSFER.getValue().equals(orderWarehouseApprovalDO.getType())) {
                OrderWarehouseAdjustDO orderWarehouseAdjustDO = warehouseAdjustMapper.selectById(Long.parseLong(orderIds));
                if (orderWarehouseAdjustDO != null) {
                    orderNo = orderWarehouseAdjustDO.getOrderNo();
                }
            } else {
                OrderDO orderDO = orderMapper.selectById(Long.parseLong(orderIds));
                orderNo = orderDO.getOrderNo();
            }
        } catch (Exception e) {
            log.error("查询出现异常", e);
        }

        //发起流程
        String formId = bpmCreateServiceFactory.createBmp(orderWarehouseApprovalDO.getFollowUpAdminId(),
                orderWarehouseApprovalDO.getId(), workFlowEmus.getKey(),orderNo, copyUserId);

        orderWarehouseApprovalDO.setFormId(formId);
        orderWarehouseApprovalMapper.updateById(orderWarehouseApprovalDO);

        return orderWarehouseApprovalDO.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelApplyAndUpdate(OrderWarehouseApprovalDO orderWarehouseApprovalDO, String reason) {

        if (orderWarehouseApprovalDO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_WAREHOUSE_APPROVAL_NOT_EXISTS);
        }

        bpmCreateServiceFactory.cancelBmpById(SecurityFrameworkUtils.getLoginUserId(), orderWarehouseApprovalDO.getFormId(), reason);

        //更新状态
        orderWarehouseApprovalDO.setStatus(ApprovalResultStatusEnum.cancel.getValue());
        orderWarehouseApprovalMapper.updateById(orderWarehouseApprovalDO);
    }

    @Override
    public void cancelOrderWarehouseApproval(Long orderApprovalId, String reason) {

        OrderWarehouseApprovalDO orderWarehouseApprovalDO = orderWarehouseApprovalMapper.selectById(orderApprovalId);
        if (orderWarehouseApprovalDO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_WAREHOUSE_APPROVAL_NOT_EXISTS);
        }
        //审核通过后不可以取消
        if (ApprovalResultStatusEnum.pass.getValue().equals(orderWarehouseApprovalDO.getStatus())) {
            throw exception(WAREHOUSE_APPROVAL_PASSED_CANNOT_CANCEL);
        }
        // //若是调仓，则判断是否批量，批量调仓不可以取消
        // if (OrderWarehouseApprovalTypeEnum.WAREHOUSE_IN_TRANSFER.getValue().equals(orderWarehouseApprovalDO.getType())
        //         && orderWarehouseApprovalDO.getIsBatch()) {
        //     throw exception(WAREHOUSE_APPROVAL_BATCH_CANNOT_CANCEL);
        // }

        //取消审核并更新审批状态
        this.cancelApplyAndUpdate(orderWarehouseApprovalDO, reason);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void callbackUpdate(OrderWarehouseApprovalDO orderWarehouseApprovalDO, Integer result) {
        if (orderWarehouseApprovalDO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_WAREHOUSE_APPROVAL_NOT_EXISTS);
        }

        if (ApprovalResultStatusEnum.processing.getValue().equals(result)) {
            //do nothing
        } else {
            //设置状态
            orderWarehouseApprovalDO.setStatus(result);

            TaskResp taskResp = bpmCreateServiceFactory.getLastTaskByProcessInstanceId(orderWarehouseApprovalDO.getFormId());
            if (taskResp != null) {
                if (taskResp.getAssigneeUser() != null) {
                    orderWarehouseApprovalDO.setFinishBy(taskResp.getAssigneeUser().getId().toString());
                }
                //设置结束时间
                orderWarehouseApprovalDO.setFinishTime(taskResp.getEndTime() == null ? taskResp.getEndTime() : new Date());
                //设置原因
                orderWarehouseApprovalDO.setProcessingResults(taskResp.getComment());
            }
            orderWarehouseApprovalMapper.updateById(orderWarehouseApprovalDO);
        }
    }

    @Override
    public void deleteOrderWarehouseApproval(Long id) {
        // 校验存在
        this.validateOrderWarehouseApprovalExists(id);
        // 删除
        orderWarehouseApprovalMapper.deleteById(id);
    }

    private void validateOrderWarehouseApprovalExists(Long id) {
        if (orderWarehouseApprovalMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_WAREHOUSE_APPROVAL_NOT_EXISTS);
        }
    }

    @Override
    public OrderWarehouseApprovalDO getOrderWarehouseApproval(Long id) {
        return orderWarehouseApprovalMapper.selectById(id);
    }

    @Override
    public OrderWarehouseApprovalDO getOrderWarehouseApproval(String formId) {
        return orderWarehouseApprovalMapper.selectOne(OrderWarehouseApprovalDO::getFormId, formId);
    }

    @Override
    public List<OrderWarehouseApprovalDO> getOrderWarehouseApprovalList(Collection<Long> ids) {
        return orderWarehouseApprovalMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OrderWarehouseApprovalDO> getOrderWarehouseApprovalPage(OrderWarehouseApprovalQueryVO query, PageVO page) {
        return orderWarehouseApprovalMapper.selectPage(page, query);
    }

    @Override
    public List<OrderWarehouseApprovalDO> getOrderWarehouseApprovalList(OrderWarehouseApprovalQueryVO query) {
        return orderWarehouseApprovalMapper.selectList(query);
    }

    @Override
    public OrderWarehouseApprovalBackVO getUpdateApprovalInfo(String formId) {
        OrderWarehouseApprovalDO orderWarehouseApprovalDO = orderWarehouseApprovalMapper.selectOne(new LambdaQueryWrapperX<OrderWarehouseApprovalDO>()
                .eq(OrderWarehouseApprovalDO::getType, OrderWarehouseApprovalTypeEnum.WAREHOUSE_IN_UPDATE.getValue())
                .eq(OrderWarehouseApprovalDO::getFormId, formId).orderByDesc(OrderWarehouseApprovalDO::getId)
                .last("limit 1"));
        OrderWarehouseApprovalBackVO convert = OrderWarehouseApprovalConvert.INSTANCE.convert(orderWarehouseApprovalDO);
        return convert;
    }

    @Override
    public OrderWarehouseApprovalBackVO getAdjustApprovalInfo(Long formId) {
        OrderWarehouseApprovalDO orderWarehouseApprovalDO = orderWarehouseApprovalMapper.selectOne(new LambdaQueryWrapperX<OrderWarehouseApprovalDO>()
                .eq(OrderWarehouseApprovalDO::getType, OrderWarehouseApprovalTypeEnum.WAREHOUSE_IN_TRANSFER.getValue())
                .eq(OrderWarehouseApprovalDO::getOrderItemId, formId).orderByDesc(OrderWarehouseApprovalDO::getId)
                .last("limit 1"));
        OrderWarehouseApprovalBackVO convert = OrderWarehouseApprovalConvert.INSTANCE.convert(orderWarehouseApprovalDO);
        return convert;
    }

    @Override
    public OrderWarehouseApprovalBackVO getLastUpdateApprovalInfo(Long orderId, Long orderItemId) {
        OrderWarehouseApprovalDO orderWarehouseApprovalDO = orderWarehouseApprovalMapper.selectOne(new LambdaQueryWrapperX<OrderWarehouseApprovalDO>()
                .eq(OrderWarehouseApprovalDO::getType, OrderWarehouseApprovalTypeEnum.WAREHOUSE_IN_UPDATE.getValue())
                .eq(OrderWarehouseApprovalDO::getOrderIds, orderId)
                .eq(OrderWarehouseApprovalDO::getOrderItemId, orderItemId)
                .orderByDesc(OrderWarehouseApprovalDO::getId)
                .last("limit 1"));
        OrderWarehouseApprovalBackVO convert = OrderWarehouseApprovalConvert.INSTANCE.convert(orderWarehouseApprovalDO);
        return convert;
    }

    @Override
    public boolean countProcessingApproval(Long orderId, List<Long> orderItemIdList, List<Integer> typeList) {
        long count = orderWarehouseApprovalMapper.countProcessingApproval(orderId, orderItemIdList, typeList);
        return count > 0;
    }
}
