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

import com.xisc.pm.api.dto.export.PmStCodeBtDTO;
import com.xisc.pm.app.service.PmStCodeBtService;
import com.xisc.pm.domain.entity.PmStCodeBt;
import com.xisc.pm.domain.entity.PmStCodeBtTra;
import com.xisc.pm.domain.repository.PmStCodeBtRepository;
import com.xisc.pm.domain.repository.PmStCodeBtTraRepository;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.util.BeanUtils;
import io.choerodon.core.domain.Page;
import io.choerodon.core.exception.CommonException;
import io.choerodon.core.oauth.DetailsHelper;
import io.choerodon.mybatis.pagehelper.PageHelper;
import io.choerodon.mybatis.pagehelper.domain.PageRequest;
import org.apache.commons.collections.CollectionUtils;
import org.hzero.boot.platform.lov.adapter.LovAdapter;
import org.hzero.boot.platform.lov.dto.LovValueDTO;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 强度级别对照基准表(PmStCodeBt)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-07-26 14:15:14
 */
@Service
public class PmStCodeBtServiceImpl implements PmStCodeBtService {

    private PmStCodeBtRepository pmStCodeBtRepository;

    private PmStCodeBtTraRepository pmStCodeBtTraRepository;

    private LovAdapter lovAdapter;

    public PmStCodeBtServiceImpl(PmStCodeBtRepository pmStCodeBtRepository, PmStCodeBtTraRepository pmStCodeBtTraRepository,
                                 LovAdapter lovAdapter) {
        this.pmStCodeBtRepository = pmStCodeBtRepository;
        this.pmStCodeBtTraRepository = pmStCodeBtTraRepository;
        this.lovAdapter = lovAdapter;
    }

    @Override
    public Page<PmStCodeBt> selectList(PageRequest pageRequest, PmStCodeBt pmStCodeBt) {
        return PageHelper.doPageAndSort(pageRequest, () -> pmStCodeBtRepository.selectList(pmStCodeBt));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, List<PmStCodeBt> pmStCodeBtList) {
        // 检查列表是否为空，如果为空则直接返回
        if (CollectionUtils.isEmpty(pmStCodeBtList)) {
            return;
        }
        // 校验新增或者更新的数据是否满足唯一性校验
        Map<String, List<PmStCodeBt>> pmStCodeBtMap = pmStCodeBtList.stream().collect(Collectors.groupingBy(this::getStCodeKey));
        for (Map.Entry<String, List<PmStCodeBt>> entry : pmStCodeBtMap.entrySet()) {
            List<PmStCodeBt> stCodeBtList = entry.getValue();
            if (stCodeBtList.size() > 1) {
                throw new CommonException("pm.st_code_bt_001", stCodeBtList.get(0).getStCode(), stCodeBtList.get(0).getStNo(), stCodeBtList.get(0).getRollLineNo());
            }
        }
        // 获取字段集合，查询数据库在该范围内数据
        List<String> stCodeList = pmStCodeBtList.stream().map(PmStCodeBt::getStCode).distinct().collect(Collectors.toList());
        List<String> stNoList = pmStCodeBtList.stream().map(PmStCodeBt::getStNo).distinct().collect(Collectors.toList());
        List<String> rollLineNoList = pmStCodeBtList.stream().map(PmStCodeBt::getRollLineNo).distinct().collect(Collectors.toList());
        List<Long> idList = pmStCodeBtList.stream().filter(item->item.getPscbId()!= null).map(PmStCodeBt::getPscbId).collect(Collectors.toList());
        List<PmStCodeBt> existPmStCodeBtList = pmStCodeBtRepository.selectByCondition(Condition.builder(PmStCodeBt.class)
                .andWhere(Sqls.custom().andEqualTo(PmStCodeBt.FIELD_TENANT_ID, tenantId))
                .andWhere(Sqls.custom().andIn(PmStCodeBt.FIELD_ST_CODE, stCodeList))
                .andWhere(Sqls.custom().andIn(PmStCodeBt.FIELD_ST_NO, stNoList))
                .andWhere(Sqls.custom().andIn(PmStCodeBt.FIELD_ROLL_LINE_NO, rollLineNoList))
                .andWhere(Sqls.custom().andNotIn(PmStCodeBt.FIELD_PSCB_ID, idList, true))
                .build());
        if (CollectionUtils.isNotEmpty(existPmStCodeBtList)) {
            // 校验数据唯一性
            Map<String, PmStCodeBt> existPmStCodeBtMap = existPmStCodeBtList.stream().collect(Collectors.toMap(this::getStCodeKey, Function.identity()));
            for (PmStCodeBt pmStCodeBt : pmStCodeBtList) {
                if (existPmStCodeBtMap.containsKey(getStCodeKey(pmStCodeBt))) {
                    throw new CommonException("pm.st_code_bt_002", pmStCodeBt.getStCode(), pmStCodeBt.getStNo(), pmStCodeBt.getRollLineNo());
                }
            }
        }

        // 分别筛选出待新增和待更新的
        List<PmStCodeBt> insertList = pmStCodeBtList.stream().filter(line -> line.getPscbId() == null).collect(Collectors.toList());
        List<PmStCodeBt> updateList = pmStCodeBtList.stream().filter(line -> line.getPscbId() != null).collect(Collectors.toList());

        // 获取当前时间和用户信息。
        Date now = new Date();
        String username = DetailsHelper.getUserDetails().getUsername();
        List<PmStCodeBtTra> insertPmStCodeBtTraList = new ArrayList<>(pmStCodeBtList.size());


        // 记录历史表
        for (PmStCodeBt pmStCodeBt : updateList) {
            PmStCodeBtTra pmStCodeBtTra = new PmStCodeBtTra();
            BeanUtils.copy(pmStCodeBt, pmStCodeBtTra);

            // 设置操作类型为更新（U），并记录操作时间和用户
            pmStCodeBtTra.setOperationType("U");
            pmStCodeBtTra.setOperationTime(now);
            pmStCodeBtTra.setOperationUser(username);
            insertPmStCodeBtTraList.add(pmStCodeBtTra);

        }
        // 更新或者新增
        pmStCodeBtRepository.batchUpdateByPrimaryKey(updateList);
        pmStCodeBtRepository.batchInsertSelective(insertList);

        for (PmStCodeBt pmStCodeBt : insertList) {
            PmStCodeBtTra pmStCodeBtTra = new PmStCodeBtTra();
            BeanUtils.copy(pmStCodeBt, pmStCodeBtTra);

            // 设置操作类型为插入（I），并记录操作时间和用户
            pmStCodeBtTra.setOperationType("I");
            pmStCodeBtTra.setOperationTime(now);
            pmStCodeBtTra.setOperationUser(username);
            insertPmStCodeBtTraList.add(pmStCodeBtTra);

        }
        // 插入保存或者更新记录到对应履历表
        pmStCodeBtTraRepository.batchInsertSelective(insertPmStCodeBtTraList);
    }

    public String getStCodeKey(PmStCodeBt pmStCodeBt) {
        return pmStCodeBt.getStCode() + "-" + pmStCodeBt.getStNo() + "-" + pmStCodeBt.getRollLineNo();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteForUi(List<PmStCodeBt> pmStCodeBtList) {
        if (CollectionUtils.isNotEmpty(pmStCodeBtList)) {
            // 删除
            pmStCodeBtRepository.batchDeleteByPrimaryKey(pmStCodeBtList);

            // 获取时间和当前操作人信息
            Date now = new Date();
            String username = DetailsHelper.getUserDetails().getUsername();
            List<PmStCodeBtTra> insertPmSpeStAddvBtTraList = new ArrayList<>(pmStCodeBtList.size());
            for (PmStCodeBt pmStCodeBt : pmStCodeBtList) {
                PmStCodeBtTra pmStCodeBtTra = new PmStCodeBtTra();

                // 设置操作类型为插入（D），并记录操作时间和用户
                BeanUtils.copy(pmStCodeBt, pmStCodeBtTra);
                pmStCodeBtTra.setOperationType("D");
                pmStCodeBtTra.setOperationTime(now);
                pmStCodeBtTra.setOperationUser(username);
                insertPmSpeStAddvBtTraList.add(pmStCodeBtTra);

            }
            // 插入删除记录到对应履历表
            pmStCodeBtTraRepository.batchInsertSelective(insertPmSpeStAddvBtTraList);
        }
    }

    @Override
    public List<PmStCodeBtDTO> exportList(Long tenantId, PmStCodeBt pmStCodeBt) {
        List<PmStCodeBt> pmStCodeBtList = pmStCodeBtRepository.selectList(pmStCodeBt);
        // 如果集合为空，则返回
        if (CollectionUtils.isEmpty(pmStCodeBtList)) {
            return Collections.EMPTY_LIST;
        }
        List<PmStCodeBtDTO> resultList = new ArrayList<>();
        // 获取轧制产线号值集含义
        List<LovValueDTO> rollLineNoList = lovAdapter.queryLovValue(Constants.LovCode.ROLL_LINE_NO, tenantId);
        Map<String, String> rollLineNoLovMap = new HashMap<>(rollLineNoList.size());

        // 赋值
        if (CollectionUtils.isNotEmpty(rollLineNoList)) {
            rollLineNoLovMap = rollLineNoList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        for (PmStCodeBt line : pmStCodeBtList) {
            PmStCodeBtDTO dto = new PmStCodeBtDTO();
            BeanUtils.copy(line, dto);
            dto.setRollLineNoDesc(rollLineNoLovMap.getOrDefault(line.getRollLineNo(), line.getRollLineNo()));
            resultList.add(dto);
        }
        return resultList;
    }
}

