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

import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Multimaps;
import com.xisc.pm.api.dto.PmPolicyGroupReqDTO;
import com.xisc.pm.api.dto.PmPolicyGroupResDTO;
import com.xisc.pm.app.service.PmPolicyGroupService;
import com.xisc.pm.domain.entity.PmPolicy;
import com.xisc.pm.domain.entity.PmPolicyGrKpi;
import com.xisc.pm.domain.entity.PmPolicyGrOrder;
import com.xisc.pm.domain.entity.PmPolicyGroup;
import com.xisc.pm.domain.entity.PmPolicyGroupAttr;
import com.xisc.pm.domain.entity.PmPolicyGroupRel;
import com.xisc.pm.domain.repository.PmPolicyGrKpiRepository;
import com.xisc.pm.domain.repository.PmPolicyGrOrderRepository;
import com.xisc.pm.domain.repository.PmPolicyGroupAttrRepository;
import com.xisc.pm.domain.repository.PmPolicyGroupRelRepository;
import com.xisc.pm.domain.repository.PmPolicyGroupRepository;
import com.xisc.pm.domain.repository.PmPolicyRepository;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.mapper.PmPolicyGroupMapper;
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.commons.lang.StringUtils;
import org.hzero.boot.platform.code.builder.CodeRuleBuilder;
import org.hzero.boot.platform.code.constant.CodeConstants;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 策略组表(PmPolicyGroup)应用服务
 *
 * @author 纪文桃 wentao.ji01@hand-china.com
 * @since 2024-11-08 09:38:30
 */
@Service
public class PmPolicyGroupServiceImpl implements PmPolicyGroupService {
    @Autowired
    private PmPolicyGroupRepository pmPolicyGroupRepository;

    @Autowired
    private PmPolicyGroupRelRepository pmPolicyGroupRelRepository;

    @Autowired
    private PmPolicyGroupMapper pmPolicyGroupMapper;

    @Autowired
    private PmPolicyGrOrderRepository pmPolicyGrOrderRepository;

    @Autowired
    private PmPolicyGrKpiRepository pmPolicyGrKpiRepository;

    @Autowired
    private PmPolicyGroupAttrRepository pmPolicyGroupAttrRepository;

    @Autowired
    private PmPolicyRepository pmPolicyRepository;

    @Autowired
    private CodeRuleBuilder codeRuleBuilder;

    @Autowired
    private LovAdapter lovAdapter;


    @Override
    public Page<PmPolicyGroup> selectList(PageRequest pageRequest, PmPolicyGroupReqDTO dto, Long tenantId) {
        // 执行策略
        List<String> policyIdList = new ArrayList<>();
        if (StringUtils.isNotEmpty(dto.getPolicyId())) {
            for (String policyId : dto.getPolicyId().split(",")) {
                policyIdList.add(policyId);
            }
        }
        Page<PmPolicyGroup> page = PageHelper.doPageAndSort(pageRequest, () -> pmPolicyGroupRepository.queryList(dto, tenantId, policyIdList));
        if (CollectionUtils.isEmpty(page)) {
            return new Page<>();
        }
        // 获取产线编码
        List<Long> policyGroupIdList = page.getContent().stream().map(PmPolicyGroup::getPolicyGroupId).collect(Collectors.toList());
        List<PmPolicyGroup> pmPolicyGroupList = pmPolicyGroupMapper.getProdLineCodeByGroupIdList(policyGroupIdList, tenantId);
        if (CollectionUtils.isNotEmpty(pmPolicyGroupList)) {
            Map<Long, String> groupedMap = pmPolicyGroupList.stream()
                    .collect(Collectors.groupingBy(
                            PmPolicyGroup::getPolicyGroupId,
                            Collectors.mapping(PmPolicyGroup::getProdLineCodeValue, Collectors.joining(","))));
            page.getContent().forEach(item-> item.setProdLineCodeValue(groupedMap.getOrDefault(item.getPolicyGroupId(), null)));
        }
        return page;
    }

    @Override
    public PmPolicyGroupResDTO lineList(Long policyGroupId, Long tenantId) {
        PmPolicyGroupResDTO pmPolicyGroupResDTO = new PmPolicyGroupResDTO();

        // 合同分组
        List<PmPolicyGrOrder> pmPolicyGrOrderList = pmPolicyGrOrderRepository.selectByCondition(Condition.builder(PmPolicyGrOrder.class)
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrOrder.FIELD_POLICY_GROUP_ID, policyGroupId))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrOrder.FIELD_TENANT_ID, tenantId))
                .orderBy(PmPolicyGrOrder.FIELD_PRIORITY)
                .build());

        // 评价指标
        List<PmPolicyGrKpi> pmPolicyGrKpiList = pmPolicyGrKpiRepository.selectByCondition(Condition.builder(PmPolicyGrKpi.class)
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrKpi.FIELD_POLICY_GROUP_ID, policyGroupId))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrKpi.FIELD_TENANT_ID, tenantId))
                .build());

        // 执行策略
        List<PmPolicyGroupRel> pmPolicyGroupRelList = pmPolicyGroupRelRepository.selectByCondition(Condition.builder(PmPolicyGroupRel.class)
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupRel.FIELD_POLICY_GROUP_ID, policyGroupId))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupRel.FIELD_TENANT_ID, tenantId))
                .orderByAsc(PmPolicyGroupRel.FIELD_SEQ)
                .build());
        if (CollectionUtils.isNotEmpty(pmPolicyGroupRelList)) {
            List<String> policyIdList = pmPolicyGroupRelList.stream().map(PmPolicyGroupRel::getPolicyId).collect(Collectors.toList());
            List<PmPolicy> pmPolicyList = pmPolicyRepository.selectByCondition(Condition.builder(PmPolicy.class)
                    .andWhere(Sqls.custom().andIn(PmPolicy.FIELD_POLICY_ID, policyIdList))
                    .andWhere(Sqls.custom().andEqualTo(PmPolicy.FIELD_TENANT_ID, tenantId))
                    .build());
            if (CollectionUtils.isEmpty(pmPolicyList)) {
                throw new CommonException("pm.policy_group_001", policyIdList);
            }
            Map<Long, String> pmPolicyMap = pmPolicyList.stream().collect(Collectors.toMap(PmPolicy::getPolicyId, PmPolicy::getPolicyCode));
            pmPolicyGroupRelList.forEach(item-> item.setPolicyCodeValue(pmPolicyMap.getOrDefault(Long.parseLong(item.getPolicyId()), "")));
        }


        // 尾量
        List<PmPolicyGroupAttr> pmPolicyGroupAttrList = pmPolicyGroupAttrRepository.selectByCondition(Condition.builder(PmPolicyGroupAttr.class)
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupAttr.FIELD_POLICY_GROUP_ID, policyGroupId))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupAttr.FIELD_TENANT_ID, tenantId))
                .build());

        pmPolicyGroupResDTO.setPmPolicyGrOrderList(pmPolicyGrOrderList);
        pmPolicyGroupResDTO.setPmPolicyGrKpiList(pmPolicyGrKpiList);
        pmPolicyGroupResDTO.setPmPolicyGroupRelList(pmPolicyGroupRelList);
        pmPolicyGroupResDTO.setPmPolicyGroupAttrList(pmPolicyGroupAttrList);

        return pmPolicyGroupResDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long tenantId, List<Long> pmPolicyGroupIdList) {
        // 	可勾选多条数据，点击后根据勾选的POLICY_GROUP_ID删除对应表PM_POLICY_GROUP、PM_POLICY_GROUP_REL、
        // PM_POLICY_GROUP_ATTR、PM_POLICT_GR_ORDER、PM_POLICY_GR_KPI的数据
        List<PmPolicyGroup> pmPolicyGroupList = pmPolicyGroupRepository.selectByCondition(Condition.builder(PmPolicyGroup.class)
                .andWhere(Sqls.custom().andIn(PmPolicyGroup.FIELD_POLICY_GROUP_ID, pmPolicyGroupIdList))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroup.FIELD_TENANT_ID, tenantId))
                .build());

        List<PmPolicyGroupRel> pmPolicyGroupRelList = pmPolicyGroupRelRepository.selectByCondition(Condition.builder(PmPolicyGroupRel.class)
                .andWhere(Sqls.custom().andIn(PmPolicyGroupRel.FIELD_POLICY_GROUP_ID, pmPolicyGroupIdList))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupRel.FIELD_TENANT_ID, tenantId))
                .build());

        List<PmPolicyGroupAttr> pmPolicyGroupAttrList = pmPolicyGroupAttrRepository.selectByCondition(Condition.builder(PmPolicyGroupAttr.class)
                .andWhere(Sqls.custom().andIn(PmPolicyGroupAttr.FIELD_POLICY_GROUP_ID, pmPolicyGroupIdList))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupAttr.FIELD_TENANT_ID, tenantId))
                .build());

        List<PmPolicyGrOrder> pmPolicyGrOrderList = pmPolicyGrOrderRepository.selectByCondition(Condition.builder(PmPolicyGrOrder.class)
                .andWhere(Sqls.custom().andIn(PmPolicyGrOrder.FIELD_POLICY_GROUP_ID, pmPolicyGroupIdList))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrOrder.FIELD_TENANT_ID, tenantId))
                .build());

        List<PmPolicyGrKpi> pmPolicyGrKpiList = pmPolicyGrKpiRepository.selectByCondition(Condition.builder(PmPolicyGrKpi.class)
                .andWhere(Sqls.custom().andIn(PmPolicyGrKpi.FIELD_POLICY_GROUP_ID, pmPolicyGroupIdList))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrKpi.FIELD_TENANT_ID, tenantId))
                .build());

        pmPolicyGroupRepository.batchDeleteByPrimaryKey(pmPolicyGroupList);
        pmPolicyGroupRelRepository.batchDeleteByPrimaryKey(pmPolicyGroupRelList);
        pmPolicyGroupAttrRepository.batchDeleteByPrimaryKey(pmPolicyGroupAttrList);
        pmPolicyGrOrderRepository.batchDeleteByPrimaryKey(pmPolicyGrOrderList);
        pmPolicyGrKpiRepository.batchDeleteByPrimaryKey(pmPolicyGrKpiList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveData(Long tenantId, PmPolicyGroupResDTO dto){
        // 校验数据
        List<LovValueDTO> lovValueDTOList = lovAdapter.queryLovValue(Constants.LovCode.ORDER_GROUP, tenantId);
        Map<String, String> lovValueDTOMap = new HashMap<>(lovValueDTOList.size());
        if (CollectionUtils.isNotEmpty(lovValueDTOList)) {
            lovValueDTOMap = lovValueDTOList.stream().collect(Collectors.toMap(LovValueDTO::getValue, LovValueDTO::getMeaning));
        }
        if (CollectionUtils.isNotEmpty(dto.getPmPolicyGrOrderList())) {
            // 按照优先级分组
            ImmutableListMultimap<Long, PmPolicyGrOrder> pmPolicyGrOrderMap = Multimaps.index(dto.getPmPolicyGrOrderList(), PmPolicyGrOrder::getPriority);
            for (Long key : pmPolicyGrOrderMap.keySet()) {
                // 按照分度维度分组
                Map<String, List<PmPolicyGrOrder>> policyGrOrderMap = pmPolicyGrOrderMap.get(key).stream().collect(Collectors.groupingBy(PmPolicyGrOrder::getGroupDimension));
                for (Map.Entry<String, List<PmPolicyGrOrder>> entry : policyGrOrderMap.entrySet()) {
                    if (entry.getValue().size() > 1) {
                        throw new CommonException("pm.policy_gr_order_001", key, lovValueDTOMap.get(entry.getKey()));
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(dto.getPmPolicyGrKpiList())) {
            // 评价指标
            ImmutableListMultimap<String, PmPolicyGrKpi> pmPolicyGrKpiMap = Multimaps.index(dto.getPmPolicyGrKpiList(), PmPolicyGrKpi::getKpiType);
            BigDecimal reduce = dto.getPmPolicyGrKpiList().stream().map(PmPolicyGrKpi::getKpiPercent).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (reduce.compareTo(BigDecimal.valueOf(100)) > 0) {
                throw new CommonException("pm.policy_gr_kpi_002", reduce);
            }
            for (String key : pmPolicyGrKpiMap.keySet()) {
              if (pmPolicyGrKpiMap.get(key).size() > 1) {
                  throw new CommonException("pm.policy_gr_kpi_001");
              }
            }
        }
        if (CollectionUtils.isNotEmpty(dto.getPmPolicyGroupAttrList()) && dto.getPmPolicyGroupAttrList().size() > 1) {
            throw new CommonException("pm.policy_group_attr_001");
        }

        dto.getPmPolicyGroup().setTenantId(tenantId);
        if (dto.getPmPolicyGroup().getPolicyGroupId() != null) {
            // 删除原先的tab页数据
              List<PmPolicyGrOrder> pmPolicyGrOrderList = pmPolicyGrOrderRepository.selectByCondition(Condition.builder(PmPolicyGrOrder.class)
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrOrder.FIELD_POLICY_GROUP_ID, dto.getPmPolicyGroup().getPolicyGroupId()))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGrOrder.FIELD_TENANT_ID, tenantId))
                .build());
              pmPolicyGrOrderRepository.batchDeleteByPrimaryKey(pmPolicyGrOrderList);

              List<PmPolicyGroupAttr> pmPolicyGroupAttrList = pmPolicyGroupAttrRepository.selectByCondition(Condition.builder(PmPolicyGroupAttr.class)
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupAttr.FIELD_POLICY_GROUP_ID, dto.getPmPolicyGroup().getPolicyGroupId()))
                .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupAttr.FIELD_TENANT_ID, tenantId))
                .build());
              pmPolicyGroupAttrRepository.batchDeleteByPrimaryKey(pmPolicyGroupAttrList);

            List<PmPolicyGrKpi> pmPolicyGrKpiList = pmPolicyGrKpiRepository.selectByCondition(Condition.builder(PmPolicyGrKpi.class)
                    .andWhere(Sqls.custom().andEqualTo(PmPolicyGrKpi.FIELD_POLICY_GROUP_ID, dto.getPmPolicyGroup().getPolicyGroupId()))
                    .andWhere(Sqls.custom().andEqualTo(PmPolicyGrKpi.FIELD_TENANT_ID, tenantId))
                    .build());
            pmPolicyGrKpiRepository.batchDeleteByPrimaryKey(pmPolicyGrKpiList);

            List<PmPolicyGroupRel> pmPolicyGroupRelList = pmPolicyGroupRelRepository.selectByCondition(Condition.builder(PmPolicyGroupRel.class)
                    .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupRel.FIELD_POLICY_GROUP_ID, dto.getPmPolicyGroup().getPolicyGroupId()))
                    .andWhere(Sqls.custom().andEqualTo(PmPolicyGroupRel.FIELD_TENANT_ID, tenantId))
                    .build());
            pmPolicyGroupRelRepository.batchDeleteByPrimaryKey(pmPolicyGroupRelList);

            // 更新
            pmPolicyGroupRepository.updateByPrimaryKey(dto.getPmPolicyGroup());
        } else {
            // 生成策略组编码
            String policyGroupCode = codeRuleBuilder.generateCode(tenantId, Constants.CodeRule.POLICY_CODE,
                    CodeConstants.CodeRuleLevelCode.GLOBAL, Constants.CodeRule.GLOBAL_LEVEL_VALUE, null);
            dto.getPmPolicyGroup().setPolicyGroupCode(policyGroupCode);
            pmPolicyGroupRepository.insertSelective(dto.getPmPolicyGroup());
        }

        for (PmPolicyGroupRel pmPolicyGroupRel : dto.getPmPolicyGroupRelList()) {
            pmPolicyGroupRel.setPolicyGroupId(dto.getPmPolicyGroup().getPolicyGroupId());
            pmPolicyGroupRel.setTenantId(tenantId);
        }

        for (PmPolicyGrKpi pmPolicyGrKpi : dto.getPmPolicyGrKpiList()) {
            pmPolicyGrKpi.setPolicyGroupId(dto.getPmPolicyGroup().getPolicyGroupId());
            pmPolicyGrKpi.setTenantId(tenantId);
        }

        for (PmPolicyGroupAttr pmPolicyGroupAttr : dto.getPmPolicyGroupAttrList()) {
            pmPolicyGroupAttr.setPolicyGroupId(dto.getPmPolicyGroup().getPolicyGroupId());
            pmPolicyGroupAttr.setTenantId(tenantId);
        }

        for (PmPolicyGrOrder pmPolicyGrOrder : dto.getPmPolicyGrOrderList()) {
            pmPolicyGrOrder.setPolicyGroupId(dto.getPmPolicyGroup().getPolicyGroupId());
            pmPolicyGrOrder.setTenantId(tenantId);
        }

        pmPolicyGroupRelRepository.batchInsertSelective(dto.getPmPolicyGroupRelList());
        pmPolicyGroupAttrRepository.batchInsertSelective(dto.getPmPolicyGroupAttrList());
        pmPolicyGrOrderRepository.batchInsertSelective(dto.getPmPolicyGrOrderList());
        pmPolicyGrKpiRepository.batchInsertSelective(dto.getPmPolicyGrKpiList());
    }
}

