package com.cf.imes.module.executor.service.process;

import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.cf.imes.framework.common.enums.ProcessProcessingTypeEnum;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO;
import com.cf.imes.module.executor.dal.dataobject.orderGroup.OrderGroupDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.executor.dal.dataobject.processStep.ProcessStepDO;
import com.cf.imes.module.executor.dal.dataobject.processStepItem.OrderProcessStepItemDO;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.dal.mysql.orderBody.OrderBodyMapper;
import com.cf.imes.module.executor.dal.mysql.orderGroup.OrderGroupMapper;
import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper;
import com.cf.imes.module.executor.dal.mysql.processStep.ProcessStepMapper;
import com.cf.imes.module.executor.dal.mysql.processStepItem.ProcessStepItemMapper;
import com.cf.imes.module.executor.enums.OrderStatusEnum;
import com.cf.imes.module.executor.enums.ProcessTypeEnum;
import com.cf.imes.module.system.api.process.ProcessGroupApi;
import com.cf.imes.module.system.api.process.dto.ProcessListReqDTO;
import com.cf.imes.module.system.api.process.dto.ProcessRespDTO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import com.cf.imes.module.executor.controller.admin.process.vo.*;
import com.cf.imes.module.executor.dal.dataobject.process.OrderProcessDO;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.object.BeanUtils;

import com.cf.imes.module.executor.dal.mysql.process.OrderProcessMapper;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.*;

/**
 * 生产单工序 Service 实现类
 *
 * @author 晨丰科技
 */
@Service
@Validated
public class OrderProcessServiceImpl implements OrderProcessService {

    @Resource
    private OrderProcessMapper orderProcessMapper;

    @Resource
    private ProcessGroupApi processGroupApi;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private IdentifierGenerator identifierGenerator;

    @Resource
    private ProcessStepMapper processStepMapper;

    @Resource
    private ProcessStepItemMapper processStepItemMapper;

    @Resource
    private OrderGroupMapper orderGroupMapper;

    @Resource
    private OrderBodyMapper orderBodyMapper;

    @Resource
    private PlateMapper plateMapper;

    private static Integer INDEX = 0;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrderProcess(OrderProcessSaveReqVO createReqVO) {
//        当生产不为删除时，校验生产单存在
        if (orderMapper.selectOrder(createReqVO.getOrderId(), SecurityFrameworkUtils.getLoginUser().getOrganId()).isEmpty()) {
            throw exception(ORDER_NOT_EXISTS);
        }
//        校验工序组存在
        if (!processGroupApi.getProcessGroup(createReqVO.getGroupId())) {
            throw exception(PROCESS_GROUP_NOT_EXISTS);
        }
//        校验是否已经存在该生产单对应的工序组
        if (orderProcessMapper.getOrderProcess(createReqVO.getOrderId(), SecurityFrameworkUtils.getLoginUser().getOrganId())) {
            throw exception(ORDER_PROCESS_EXISTS);
        }
        // 插入
        Long orderProcessId = (Long) identifierGenerator.nextId(null);

        // 查询当前订单对应的总板材大小
        BigDecimal size = plateMapper.selectPlateSize(createReqVO.getOrderId());

        OrderProcessDO orderProcess = BeanUtils.toBean(createReqVO, OrderProcessDO.class).setId(orderProcessId).setSize(size);


        List<ProcessStepDO> processStepDOS = new ArrayList<>();
        List<OrderProcessStepItemDO> orderProcessStepItemDOS = new ArrayList<>();
        // 需要获取工序组的具体信息，以及工序组中工序的信息，然后将工序组中工序的信息插入到生产单工序步骤表中
        ProcessListReqDTO processListReqDTO = processGroupApi.getProcessGroupDetail(createReqVO.getGroupId());


        processListReqDTO.getLists().forEach(processRespDTO -> {
            Long processStepDOId = (Long) identifierGenerator.nextId(null);
            ProcessStepDO processStepDO = BeanUtils.toBean(processRespDTO, ProcessStepDO.class).setId(processStepDOId).setOrderId(createReqVO.getOrderId())
                    .setStatus(false).setProcessinfoId(processRespDTO.getId()).setOrderProcessId(orderProcess.getId()).setFinishTime(null).setSort(INDEX++);// 计划日期没有填写
            processStepDOS.add(processStepDO);
            // 生产单中是否存在加工组，若存在加工组，需要逐条加工组信息写入到生产单工序步骤表

            if (processRespDTO.getType() == ProcessTypeEnum.TYPE_SEVEN.getStatus()) {

                List<OrderGroupDO> orderGroupDOS = orderGroupMapper.getOrderGroupByOrderId(createReqVO.getOrderId(), SecurityFrameworkUtils.getLoginUser().getOrganId());
                if (orderGroupDOS.size() != 0) { // 有加工组
                    for (int i = 0; i < orderGroupDOS.size(); i++) {
                        OrderProcessStepItemDO orderProcessStepItemDO = OrderProcessStepItemDO.builder()
                                .name(orderGroupDOS.get(i).getName())
                                .processStepId(processStepDOId)
                                .orderProcessId(orderProcessId)
                                .status(false)
                                .groupName(processListReqDTO.getName())
                                .bodyId(orderGroupDOS.get(i).getBodyId())
                                .groupId(orderGroupDOS.get(i).getId())
                                .build();// 查模块id，柜体id，加工组id
                        orderProcessStepItemDOS.add(orderProcessStepItemDO);
                    }
                }
            }else {
                List<OrderBodyDO> orderBodyDOS = orderBodyMapper.getOrderBodyByOrderId(createReqVO.getOrderId(), SecurityFrameworkUtils.getLoginUser().getOrganId());
                for (int i = 0; i < orderBodyDOS.size(); i++) {
                    OrderProcessStepItemDO orderProcessStepItemDO = OrderProcessStepItemDO.builder()
                            .name(processRespDTO.getName())
                            .processStepId(processStepDOId)
                            .orderProcessId(orderProcessId)
                            .status(false)
                            .groupName(orderBodyDOS.get(i).getName())
                            .bodyId(orderBodyDOS.get(i).getId())
                            .groupId(0L)
                            .build();// 查模块id，柜体id，加工组id
                    orderProcessStepItemDOS.add(orderProcessStepItemDO);
                }
            }
        });
        INDEX = 0;
        // 修改生产单的状态
        orderMapper.updateOrderStatus(createReqVO.getOrderId(), OrderStatusEnum.NO_SORT.getStatus(), SecurityFrameworkUtils.getLoginUser().getOrganId());
        // 批量插入
        orderProcessMapper.insert(orderProcess.setNextStepId(processListReqDTO.getLists().get(0).getId()).setStatus(false));
        processStepMapper.insertBatch(processStepDOS);
        processStepItemMapper.insertBatch(orderProcessStepItemDOS);
        // 返回
        return orderProcess.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderProcess(OrderProcessSaveReqVO updateReqVO) {
        // 校验存在
        validateOrderProcessExists(updateReqVO.getId());
        // 更新
        OrderProcessDO updateObj = BeanUtils.toBean(updateReqVO, OrderProcessDO.class);
        orderProcessMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrderProcess(Long id) {
        // 校验存在
        validateOrderProcessExists(id);
        // 删除
        orderProcessMapper.deleteById(id);
    }

    private void validateOrderProcessExists(Long id) {
        if (orderProcessMapper.selectById(id) == null) {
            throw exception(ORDER_PROCESS_NOT_EXISTS);
        }
    }

    //    通过生产单Id和工序id查询是否存在
    private OrderProcessDO validateOrderProcessExists(Long orderId, Long groupId) {
        return orderProcessMapper.selectOne("order_id", orderId, "group_id", groupId);
    }

    @Override
    public OrderProcessDO getOrderProcess(Long orderId) {
        return orderProcessMapper.selectOne("order_id", orderId ,"organ_id",getUserOrganId());
    }

    @Override
    public OrderProcessDO getOrderProcessByProcessGroupId(Long processGroupId) {
        return orderProcessMapper.selectOne("group_id", processGroupId,"organ_id",getUserOrganId());
    }

}