package com.xisc.pm.app.service.impl;

import com.xisc.boot.common.feign.pojo.MtUserInfo;
import com.xisc.boot.common.sys.UserClient;
import com.xisc.pm.api.dto.PmProductionLineDTO;
import com.xisc.pm.app.service.PmProductionLineService;
import com.xisc.pm.domain.entity.PmProductionLine;
import com.xisc.pm.domain.repository.PmProductionLineRepository;
import io.choerodon.core.domain.Page;
import io.choerodon.core.exception.CommonException;
import io.choerodon.mybatis.pagehelper.PageHelper;
import io.choerodon.mybatis.pagehelper.domain.PageRequest;
import org.apache.commons.collections.CollectionUtils;
import org.apache.logging.log4j.util.Strings;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 生产线表(PmProductionLine)应用服务
 *
 * @author jie.yang04@hand-china.com
 * @since 2024-10-09 09:42:02
 */
@Service
public class PmProductionLineServiceImpl implements PmProductionLineService {
    @Autowired
    private PmProductionLineRepository pmProductionLineRepository;
    @Autowired
    private UserClient userClient;

    /**
     * 选择生产线路列表
     *
     * @param pageRequest 分页请求对象，包含了分页的页码和页面大小等信息
     * @param tenantId 租户ID，用于区分不同租户的数据
     * @param productionLineDTO 生产线路DTO对象，包含了生产线路的相关信息
     * @return 返回一个分页的生产线路DTO列表
     */
    @Override
    public Page<PmProductionLineDTO> selectList(PageRequest pageRequest, Long tenantId, PmProductionLineDTO productionLineDTO) {

        // 使用PageHelper进行分页和排序，调用pmProductionLineRepository的selectList方法获取生产线路列表
        Page<PmProductionLineDTO> objectPage = PageHelper.doPageAndSort(pageRequest, () -> pmProductionLineRepository.selectList(tenantId, productionLineDTO));

        // 如果生产线路列表为空，则返回一个空的Page对象
        if (CollectionUtils.isEmpty(objectPage.getContent())) {
            return new Page<>();
        }

        // 初始化一个用户ID列表，用于存储生产线路的创建人和最后更新人的用户ID
        List<Long> userIds = new ArrayList<>(16);
        // 添加创建人的用户ID到用户ID列表中
        userIds.addAll(objectPage.getContent().stream().map(PmProductionLineDTO::getCreatedBy).distinct().collect(Collectors.toList()));
        // 添加最后更新人的用户ID到用户ID列表中
        userIds.addAll(objectPage.getContent().stream().map(PmProductionLineDTO::getLastUpdatedBy).distinct().collect(Collectors.toList()));

        // 调用userClient的userInfoBatchGet方法，批量获取用户信息
        Map<Long, MtUserInfo> mtUserInfoMap = userClient.userInfoBatchGet(tenantId, userIds);

        // 遍历生产线路列表，设置创建人和最后更新人的名称
        objectPage.getContent().forEach(line -> {
            // 获取创建人名称
            if (!mtUserInfoMap.isEmpty() && mtUserInfoMap.containsKey(line.getCreatedBy())) {
                MtUserInfo mtUserInfo = mtUserInfoMap.get(line.getCreatedBy());
                line.setCreatedByName(Strings.concat(mtUserInfo.getLoginName(), mtUserInfo.getRealName()));
            }
            // 获取更新人名称
            if (!mtUserInfoMap.isEmpty() && mtUserInfoMap.containsKey(line.getLastUpdatedBy())) {
                MtUserInfo mtUserInfo = mtUserInfoMap.get(line.getLastUpdatedBy());
                line.setUpdateByName(Strings.concat(mtUserInfo.getLoginName(), mtUserInfo.getRealName()));
            }
        });

        // 返回分页的生产线路列表
        return objectPage;
    }

    /**
     * 保存生产线数据
     *
     * @param tenantId 租户ID，用于设置每条生产线数据的租户归属
     * @param pmProductionLines 生产线列表，包含要保存或更新的生产线信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, List<PmProductionLine> pmProductionLines) {
        // 为每条生产线数据设置租户ID
        pmProductionLines.forEach(x -> x.setTenantId(tenantId));

        // 过滤出新增和修改的数据
        // 数据量小 查询表里所有数据  做校验
        List<PmProductionLine> eixstsList = pmProductionLineRepository.selectByCondition(Condition.builder(PmProductionLine.class)
                        .andWhere(Sqls.custom().andEqualTo(PmProductionLine.FIELD_TENANT_ID, tenantId))
                        .andWhere(Sqls.custom().andEqualTo(PmProductionLine.FIELD_VALID_FLAG, 1L))
                .build());

        if (CollectionUtils.isNotEmpty(eixstsList)) {
            // 以生产线代码为键，用于快速查找和校验
            Map<String, PmProductionLine> existsProdLineMap = eixstsList.stream().collect(Collectors.toMap(PmProductionLine::getProdLineCode, t -> t));
            // 以优先级为键，用于快速查找和校验
            Map<Long, PmProductionLine> existsPriorityMap = eixstsList.stream().collect(Collectors.toMap(PmProductionLine::getPriority, t -> t));

            // 校验生产线代码和优先级的唯一性
            for (PmProductionLine productionLine : pmProductionLines) {
                // 检查是否存在已有的生产线代码，且当前生产线ID为空，若存在则抛出异常
                if (existsProdLineMap.containsKey(productionLine.getProdLineCode())
                        && (Objects.isNull(productionLine.getProdLineId()) || existsProdLineMap.get(productionLine.getProdLineCode()).getProdLineId().compareTo(productionLine.getProdLineId()) != 0)) {
                    throw new CommonException("pm.producation_line_001", productionLine.getProdLineCode());
                }
                // 检查是否存在相同的优先级，若存在则抛出异常
                if (existsPriorityMap.containsKey(productionLine.getPriority())
                        && (Objects.isNull(productionLine.getProdLineId()) || existsPriorityMap.get(productionLine.getPriority()).getProdLineId().compareTo(productionLine.getProdLineId()) != 0)) {
                    PmProductionLine pmProductionLine = existsPriorityMap.get(productionLine.getPriority());
                    throw new CommonException("pm.producation_line_002", productionLine.getProdLineCode(), pmProductionLine.getProdLineCode(), productionLine.getPriority());
                }
            }
        }

        // 过滤出需要插入的新数据
        List<PmProductionLine> insertList = pmProductionLines.stream().filter(line -> line.getProdLineId() == null).collect(Collectors.toList());
        // 过滤出需要更新的数据
        List<PmProductionLine> updateList = pmProductionLines.stream().filter(line -> line.getProdLineId() != null).collect(Collectors.toList());

        // 批量插入新数据
        pmProductionLineRepository.batchInsertSelective(insertList);
        // 批量更新已存在数据
        pmProductionLineRepository.batchUpdateByPrimaryKey(updateList);
    }

    /**
     * 删除指定租户的生产线数据
     *
     * @param tenantId 租户ID，用于区分不同的租户数据
     * @param prodLineIds 生产线ID列表，指定需要删除的数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteData(Long tenantId, List<Long> prodLineIds) {
        // 检查生产线ID列表是否为空，如果为空则直接返回，不进行后续操作
        if (CollectionUtils.isEmpty(prodLineIds)) {
            return;
        }
        // 根据条件查询需要删除的生产线数据
        List<PmProductionLine> pmProductionLineList = pmProductionLineRepository.selectByCondition(Condition.builder(PmProductionLine.class)
                .andWhere(Sqls.custom().andIn(PmProductionLine.FIELD_PROD_LINE_ID, prodLineIds))
                .andWhere(Sqls.custom().andEqualTo(PmProductionLine.FIELD_TENANT_ID, tenantId)).build());
        // 批量删除查询到的生产线数据
        pmProductionLineRepository.batchDeleteByPrimaryKey(pmProductionLineList);
    }

}

