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

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
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.processStep.ProcessStepDO;
import com.cf.imes.module.executor.dal.dataobject.processStepItem.OrderProcessStepItemDO;
import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper;
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.OrderDeletedEnum;
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 jakarta.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.util.object.BeanUtils;

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

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

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.*;
import static com.cf.imes.module.executor.enums.ProcessTypeEnum.TYPE_EIGHT;
import static com.cf.imes.module.executor.enums.ProcessTypeEnum.TYPE_SEVEN;

/**
 * 生产单工序 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;

    @Resource
    private GoodsMapper goodsMapper;


    // 生产单状态检测
    private void checkOrderStatus(Long orderId, Long organId, Integer status) {
        OrderDO order = orderMapper.selectOrderOne(orderId, organId, status);
//        当生产不为删除时，校验生产单存在
        if (order == null) {
            throw exception(ORDER_NOT_EXISTS);
        }else {
//          校验生产单状态
            if (order.getStatus() != OrderStatusEnum.NEW_ORDER.getStatus()) {
                throw exception(ORDER_STATUS_CONFLICT);
            }
        }
    }

    // 校验工序组存在
    private void checkProcessGroup(Long id) {
        if (!processGroupApi.getProcessGroup(id)) {
            throw exception(PROCESS_GROUP_NOT_EXISTS);
        }
    }

    // 校验是否已经存在该生产单对应的工序组
    private void checkOrderProcessExists(Long orderId, Long organId) {
        if (orderProcessMapper.getOrderProcess(orderId, organId)) {
            throw exception(ORDER_PROCESS_EXISTS);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrderProcess(OrderProcessSaveReqVO createReqVO) {
        checkOrderStatus(createReqVO.getOrderId(), OrganContextHolder.getOrganId(), OrderDeletedEnum.NOT_DELETED.getStatus());

//        校验工序组存在
        checkProcessGroup(createReqVO.getGroupId());

//        校验是否已经存在该生产单对应的工序组
        checkOrderProcessExists(createReqVO.getOrderId(), OrganContextHolder.getOrganId());

        // 插入
        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());

        AtomicInteger INDEX = new AtomicInteger(0);
        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.getAndIncrement());// 计划日期没有填写
            processStepDOS.add(processStepDO);

            // 生产单中是否存在加工组，若存在加工组，需要逐条加工组信息写入到生产单工序步骤表
//            if (processRespDTO.getType() == ProcessTypeEnum.TYPE_SEVEN.getStatus()) {
//                List<OrderGroupDO> orderGroupDOS = orderGroupMapper.getOrderGroupByOrderId(createReqVO.getOrderId(), OrganContextHolder.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 if (processRespDTO.getType() == ProcessTypeEnum.TYPE_EIGHT.getStatus()) { // 若工序类型为板材
//                List<GoodsDO> goodsDOS = goodsMapper.selectGoodsByOrderId(createReqVO.getOrderId(), OrganContextHolder.getOrganId());
//                if (goodsDOS.size() != 0) { // 有板材
//                    for (int i = 0; i < goodsDOS.size(); i++) {
//                        OrderProcessStepItemDO orderProcessStepItemDO = OrderProcessStepItemDO.builder()
//                                .name(goodsDOS.get(i).getGoodsName()) // 板块的名称
//                                .processStepId(processStepDOId)
//                                .orderProcessId(orderProcessId)
//                                .status(false)
//                                .groupName(processListReqDTO.getName())
//                                .bodyId(goodsDOS.get(i).getId())
//                                .groupId(0L)
//                                .build();
//                        orderProcessStepItemDOS.add(orderProcessStepItemDO);
//                    }
//                }
//            } else {
//                List<OrderBodyDO> orderBodyDOS = orderBodyMapper.getOrderBodyByOrderId(createReqVO.getOrderId(), OrganContextHolder.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);
//                }
//            }
            handleProcessType(processRespDTO, createReqVO, processStepDOId, orderProcessId, processListReqDTO, orderProcessStepItemDOS);
        });
        INDEX.set(0);
        // 修改生产单的状态
        orderMapper.updateOrderStatus(createReqVO.getOrderId(), OrderStatusEnum.SORTED.getStatus(), OrganContextHolder.getOrganId());
        // 批量插入
        orderProcessMapper.insert(orderProcess.setNextStepId(processListReqDTO.getLists().get(0).getId()).setStatus(false));
        processStepMapper.insertBatch(processStepDOS);
        processStepItemMapper.insertBatch(orderProcessStepItemDOS);
        // 返回
        return orderProcess.getId();
    }

    private void handleProcessType(ProcessRespDTO processRespDTO, OrderProcessSaveReqVO createReqVO, Long processStepDOId, Long orderProcessId, ProcessListReqDTO processListReqDTO, List<OrderProcessStepItemDO> orderProcessStepItemDOS) {
        if (Objects.equals(processRespDTO.getType(), TYPE_SEVEN.getStatus())) {
            handleTypeSeven(createReqVO, processStepDOId, orderProcessId, processListReqDTO, orderProcessStepItemDOS);
        } else if (Objects.equals(processRespDTO.getType(), ProcessTypeEnum.TYPE_EIGHT.getStatus())) {
            handleTypeEight(createReqVO, processStepDOId, orderProcessId, processListReqDTO, orderProcessStepItemDOS);
        } else {
            handleDefaultType(createReqVO, processRespDTO.getName(), processStepDOId, orderProcessId, orderProcessStepItemDOS);
        }
    }

    private void handleTypeSeven(OrderProcessSaveReqVO createReqVO, Long processStepDOId, Long orderProcessId, ProcessListReqDTO processListReqDTO, List<OrderProcessStepItemDO> orderProcessStepItemDOS) {
        List<OrderGroupDO> orderGroupDOS = orderGroupMapper.getOrderGroupByOrderId(createReqVO.getOrderId(), OrganContextHolder.getOrganId());
        if (!orderGroupDOS.isEmpty()) {
            orderGroupDOS.forEach(orderGroupDO -> {
                OrderProcessStepItemDO orderProcessStepItemDO = OrderProcessStepItemDO.builder()
                        .name(orderGroupDO.getName()) // 加工组的名称
                        .processStepId(processStepDOId)
                        .orderProcessId(orderProcessId)
                        .status(false)
                        .groupName(processListReqDTO.getName())
                        .bodyId(orderGroupDO.getBodyId())
                        .groupId(orderGroupDO.getId())
                        .build();
                orderProcessStepItemDOS.add(orderProcessStepItemDO);
            });
        }
    }

    private void handleTypeEight(OrderProcessSaveReqVO createReqVO, Long processStepDOId, Long orderProcessId, ProcessListReqDTO processListReqDTO, List<OrderProcessStepItemDO> orderProcessStepItemDOS) {
        List<GoodsDO> goodsDOS = goodsMapper.selectGoodsByOrderId(createReqVO.getOrderId(), OrganContextHolder.getOrganId());
        if (!goodsDOS.isEmpty()) {
            goodsDOS.forEach(goodsDO -> {
                OrderProcessStepItemDO orderProcessStepItemDO = OrderProcessStepItemDO.builder()
                        .name(goodsDO.getGoodsName()) // 板块的名称
                        .processStepId(processStepDOId)
                        .orderProcessId(orderProcessId)
                        .status(false)
                        .groupName(processListReqDTO.getName())
                        .bodyId(goodsDO.getId())
                        .groupId(0L)
                        .build();
                orderProcessStepItemDOS.add(orderProcessStepItemDO);
            });
        }
    }

    private void handleDefaultType(OrderProcessSaveReqVO createReqVO, String name, Long processStepDOId, Long orderProcessId, List<OrderProcessStepItemDO> orderProcessStepItemDOS) {
        List<OrderBodyDO> orderBodyDOS = orderBodyMapper.getOrderBodyByOrderId(createReqVO.getOrderId(), OrganContextHolder.getOrganId());
        orderBodyDOS.forEach(orderBodyDO -> {
            OrderProcessStepItemDO orderProcessStepItemDO = OrderProcessStepItemDO.builder()
                    .name(name)
                    .processStepId(processStepDOId)
                    .orderProcessId(orderProcessId)
                    .status(false)
                    .groupName(orderBodyDO.getName())
                    .bodyId(orderBodyDO.getId())
                    .groupId(0L)
                    .build();
            orderProcessStepItemDOS.add(orderProcessStepItemDO);
        });
    }

    @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 List<OrderProcessDO> getOrderProcessByProcessGroupId(Long processGroupId) {
        return orderProcessMapper.selectList(new LambdaUpdateWrapper<OrderProcessDO>()
                .eq(OrderProcessDO::getGroupId, processGroupId)
                .eq(OrderProcessDO::getOrganId, getUserOrganId()));
    }

}