package cn.iocoder.yudao.module.pms.service.iotmaterialrequisition;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.pms.constant.PmsConstants;
import cn.iocoder.yudao.module.pms.controller.admin.iotmaterialrequisition.vo.IotMaterialRequisitionPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotmaterialrequisition.vo.IotMaterialRequisitionSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotmaterialrequisition.vo.IotMaterialRequisitionSaveVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotmaterialrequisitiondetail.vo.IotMaterialRequisitionDetailSaveReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotmaterialrequisition.IotMaterialRequisitionDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotmaterialrequisitiondetail.IotMaterialRequisitionDetailDO;
import cn.iocoder.yudao.module.pms.dal.mysql.iotmaterialrequisition.IotMaterialRequisitionMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.iotmaterialrequisitiondetail.IotMaterialRequisitionDetailMapper;
import cn.iocoder.yudao.module.pms.dal.redis.BizNoRedisDAO;
import cn.iocoder.yudao.module.pms.message.PmsMessage;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MATERIAL_REQUISITION_NOT_EXISTS;
import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;

/**
 * 物料领用 Service 实现类
 *
 * @author ruiqi
 */
@Service
@Validated
public class IotMaterialRequisitionServiceImpl implements IotMaterialRequisitionService {

    @Resource
    private IotMaterialRequisitionMapper iotMaterialRequisitionMapper;
    @Resource
    private IotMaterialRequisitionDetailMapper iotMaterialRequisitionDetailMapper;
    @Resource
    private BizNoRedisDAO bizNoRedisDAO;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private DeptApi deptApi;
    @Resource
    private PmsMessage pmsMessage;
    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;

    @Override
    public Long createIotMaterialRequisition(IotMaterialRequisitionSaveReqVO createReqVO) {
        // 插入
        IotMaterialRequisitionDO iotMaterialRequisition = BeanUtils.toBean(createReqVO, IotMaterialRequisitionDO.class);
        iotMaterialRequisitionMapper.insert(iotMaterialRequisition);
        // 返回
        return iotMaterialRequisition.getId();
    }

    @Override
    public void updateIotMaterialRequisition(IotMaterialRequisitionSaveReqVO updateReqVO) {
        // 校验存在
        validateIotMaterialRequisitionExists(updateReqVO.getId());
        // 更新
        IotMaterialRequisitionDO updateObj = BeanUtils.toBean(updateReqVO, IotMaterialRequisitionDO.class);
        iotMaterialRequisitionMapper.updateById(updateObj);
    }

    @Override
    public void deleteIotMaterialRequisition(Long id) {
        // 校验存在
        validateIotMaterialRequisitionExists(id);
        // 删除
        iotMaterialRequisitionMapper.deleteById(id);
    }

    private void validateIotMaterialRequisitionExists(Long id) {
        if (iotMaterialRequisitionMapper.selectById(id) == null) {
            throw exception(IOT_MATERIAL_REQUISITION_NOT_EXISTS);
        }
    }

    @Override
    public IotMaterialRequisitionDO getIotMaterialRequisition(Long id) {
        return iotMaterialRequisitionMapper.selectById(id);
    }

    @Override
    public PageResult<IotMaterialRequisitionDO> getIotMaterialRequisitionPage(IotMaterialRequisitionPageReqVO pageReqVO) {
        return iotMaterialRequisitionMapper.selectPage(pageReqVO);
    }

    @Override
    public void addMaterialRequisition(IotMaterialRequisitionSaveVO saveVO) {
        if (ObjectUtil.isEmpty(saveVO)) {
            throw exception(IOT_MATERIAL_REQUISITION_NOT_EXISTS);
        }
        IotMaterialRequisitionSaveReqVO materialRequisition = saveVO.getMaterialRequisition();
        if (ObjectUtil.isEmpty(materialRequisition)) {
            throw exception(IOT_MATERIAL_REQUISITION_NOT_EXISTS);
        }
        List<IotMaterialRequisitionDetailSaveReqVO> materialReqDetails = saveVO.getMaterialReqDetails();
        if (ObjectUtil.isEmpty(materialReqDetails)) {
            throw exception(IOT_MATERIAL_REQUISITION_NOT_EXISTS);
        }
        // 保养工单 主表 还有 保养费用 、人工费用 、其他费用
        IotMaterialRequisitionDO requisition = BeanUtils.toBean(materialRequisition, IotMaterialRequisitionDO.class);
        requisition.setRequisitionNumber(createMaterialReqNumber());
        iotMaterialRequisitionMapper.insert(requisition);
        // 添加物料领用单明细
        List<IotMaterialRequisitionDetailDO> requisitionDetails = new ArrayList<>();
        materialReqDetails.forEach(material -> {
            IotMaterialRequisitionDetailDO tempMaterial = BeanUtils.toBean(material, IotMaterialRequisitionDetailDO.class);
            tempMaterial.setRequisitionId(requisition.getId());
            requisitionDetails.add(tempMaterial);
        });
        if (CollUtil.isNotEmpty(requisitionDetails)) {
            iotMaterialRequisitionDetailMapper.insertBatch(requisitionDetails);
        }
        // 记录物料出库
        // 向当前登录人的上级 发送钉钉 站内信 消息
        // 查询当前便当人的上级部门 合并 指定角色 关联查询
        List<String> receiveRoles = DictFrameworkUtils.getDictDataLabelList("iot_material_req_msg_receive_role");
        // 查询当前登录人的上级部门
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        AdminUserRespDTO user = adminUserApi.getUser(userId);
        Long deptId = user.getDeptId();
        DeptRespDTO dept = deptApi.getDept(deptId);
        Long parentDeptId = dept.getParentId();
        // 结合上级部门id 和 角色id 筛选出消息接收人
        if (CollUtil.isNotEmpty(receiveRoles) && ObjUtil.isNotEmpty(parentDeptId)) {
            List<AdminUserRespDTO> receiveUsers = iotMaterialRequisitionMapper.msgReceiveUsers(receiveRoles.get(0), parentDeptId);
            // 发送 站内信 和 钉钉消息
            if (CollUtil.isNotEmpty(receiveUsers)) {
                receiveUsers.forEach(ru -> {
                    CountDownLatch latch = new CountDownLatch(receiveUsers.size());
                    pmsThreadPoolTaskExecutor.execute(() -> {
                        try {
                            pmsMessage.sendMessage(requisition.getId(), requisition.getName(), PmsConstants.MATERIAL_REQUISITION, ru.getId(), ru.getMobile());
                            System.out.println("领料消息：" + requisition.getId() + "-" + ru.getMobile());
                        }  finally {
                            latch.countDown();
                        }
                    });
                });
            }
        }
    }

    @Override
    public String createMaterialReqNumber() {
        return bizNoRedisDAO.generate(BizNoRedisDAO.MATERIAL_REQ_ORDER_NO_PREFIX);
    }

}