package pwc.taxtech.atms.service.impl;

import org.apache.commons.lang3.BooleanUtils;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import pwc.taxtech.atms.common.CommonConstants;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.common.OperateLogType;
import pwc.taxtech.atms.common.OperationAction;
import pwc.taxtech.atms.common.OperationModule;
import pwc.taxtech.atms.common.message.DimensionMessage;
import pwc.taxtech.atms.common.message.DimensionValueMessage;
import pwc.taxtech.atms.common.message.LogMessage;
import pwc.taxtech.atms.constant.DimensionConstant;
import pwc.taxtech.atms.dpo.DimensionValueOrgDto;
import pwc.taxtech.atms.dpo.StatisticAttributeDisplayDto;
import pwc.taxtech.atms.dto.OperationResultDto;
import pwc.taxtech.atms.dto.UpdateLogParams;
import pwc.taxtech.atms.dto.dimension.DimensinTypeOrgDto;
import pwc.taxtech.atms.dto.dimension.DimensionDto;
import pwc.taxtech.atms.dto.dimension.DimensionTypeEnum;
import pwc.taxtech.atms.dto.dimension.DimensionValueDto;
import pwc.taxtech.atms.dto.navtree.DevTreeDto;
import pwc.taxtech.atms.entity.*;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Comparator.*;
import static java.util.stream.Collectors.toList;

/**
 */
@Service
public class DimensionServiceImpl extends AbstractService {

    @Autowired
    private BusinessUnitServiceImpl businessUnitService;
    @Autowired
    private StatisticAttributeServiceImpl statisticAttributeService;

    public List<DimensionDto> getDimensionStatics() {
        DimensionExample example = new DimensionExample();
        example.setOrderByClause("ORDER_INDEX");
        List<Dimension> dimensionList = dimensionMapper.selectByExample(example);

        DimensionValueExample valueExample = new DimensionValueExample();
        valueExample.createCriteria().andIsActiveEqualTo(true);
        List<DimensionValue> dimensionValueList = dimensionValueMapper.selectByExample(valueExample);
        Assert.notNull(dimensionValueList, "Null list");

        List<DimensionDto> retList = new ArrayList<>();

        for (Dimension item : dimensionList) {
            DimensionDto temp = new DimensionDto();
            CommonUtils.copyProperties(item, temp);
            if (DimensionConstant.BusinessUnitId.equalsIgnoreCase(item.getId())) {
                // 事业部
                temp.setDimensionType(DimensionTypeEnum.BusinessUnit.value());
                int count = countBusinessUnit();
                temp.setDimensionValueCount(count);
            } else if (DimensionConstant.AreaId.equalsIgnoreCase(item.getId())) {
                // 覆盖发区域
                temp.setDimensionType(DimensionTypeEnum.Area.value());
                int count = countArea();
                temp.setDimensionValueCount(count);
            } else if (DimensionConstant.OrganizationStructureId.equalsIgnoreCase(item.getId())) {
                // 覆盖发区域
                temp.setDimensionType(DimensionTypeEnum.OrganizationStructure.value());
                int count = countOrganization();
                temp.setDimensionValueCount(count);
            } else if (DimensionConstant.StockId.equalsIgnoreCase(item.getId())) {
                // stock
                temp.setDimensionType(DimensionTypeEnum.Stock.value());
                int count = countStock();
                temp.setDimensionValueCount(count);
            } else if (DimensionConstant.OrgSubChildrenId.equalsIgnoreCase(item.getId())) {
                // 子分公司
                temp.setDimensionType(DimensionTypeEnum.OrgSubChildren.value());
                int count = countOrganization();
                temp.setDimensionValueCount(count);
            } else {
                // 其他
                temp.setDimensionType(DimensionTypeEnum.SelfDimension.value());
                if (!dimensionValueList.isEmpty() && item.getId() != null) {
                    int count = (int) dimensionValueList.stream().filter(x -> item.getId().equals(x.getDimensionId()))
                            .count();
                    temp.setDimensionValueCount(count);
                }
            }
            retList.add(temp);
        }
        List<DimensionDto> systemDimensionList = retList.stream()
                .filter(x -> x != null && BooleanUtils.toBoolean(x.getIsSystemDimension()))
                .collect(Collectors.toList());

        List<DimensionDto> selfDimensionList = retList.stream()
                .filter(x -> x != null && !BooleanUtils.toBoolean(x.getIsSystemDimension()))
                .collect(Collectors.toList());

        selfDimensionList.sort(comparing(DimensionDto::getIsActive, nullsFirst(naturalOrder())).reversed()
                .thenComparing(comparing(DimensionDto::getOrderIndex, nullsFirst(naturalOrder()))));

        List<DimensionDto> result = new ArrayList<>();
        result.addAll(systemDimensionList);
        result.addAll(selfDimensionList);
        return result;
    }

    private int countStock() {
        return (int) stockMapper.countByExample(null);
    }

    private int countArea() {
        AreaExample tmpExample = new AreaExample();
        tmpExample.createCriteria().andIsActiveEqualTo(true).andParentIdIsNull();
        return (int) areaMapper.countByExample(tmpExample);
    }

    private int countOrganization() {
        OrganizationExample tmpExample = new OrganizationExample();
        tmpExample.createCriteria().andIsActiveEqualTo(true);
        return (int) organizationMapper.countByExample(tmpExample);
    }

    private int countBusinessUnit() {
        BusinessUnitExample businessUnitExample = new BusinessUnitExample();
        businessUnitExample.createCriteria().andIsActiveEqualTo(true);
        return (int) businessUnitMapper.countByExample(businessUnitExample);
    }

    public List<DimensionDto> getAllDimensionList() {
        List<Dimension> dimensionList = findByIsActiveTrue();

        List<DimensionDto> resultList = convertToDimensionList(dimensionList);

        if (!CollectionUtils.isEmpty(dimensionList)) {
            for (DimensionDto dimensionDto : resultList) {
                List<DimensionValue> dimensionValueList = findDimensionValueByDimensionIdAndIsActiveTrue(
                        dimensionDto.getId());
                dimensionDto.setDimensionValueCount(dimensionValueList.size());
                List<DimensionValueDto> dimensionValueDtoList = dimensionValueList.stream()
                        .map(x -> CommonUtils.copyProperties(x, new DimensionValueDto())).collect(Collectors.toList());
                dimensionDto.setDimensionValueList(dimensionValueDtoList);

                DimensionTypeEnum dimensionTypeEnum = getDimensionType(dimensionDto.getId());
                dimensionDto.setDimensionType(dimensionTypeEnum.value());
            }
        }
        return resultList.stream().filter(x -> !Strings.equals(x.getId(), DimensionConstant.OrgSubChildrenId)).collect(Collectors.toList());
    }

    private List<DimensionValue> findDimensionValueByDimensionIdAndIsActiveTrue(String dimensionId) {
        DimensionValueExample dimensionValueExample = new DimensionValueExample();
        dimensionValueExample.createCriteria().andIsActiveEqualTo(true).andDimensionIdEqualTo(dimensionId);
        return dimensionValueMapper.selectByExample(dimensionValueExample);
    }

    public DimensionDto toDimensionDto(Dimension dimension) {
        DimensionDto result = CommonUtils.copyProperties(dimension, new DimensionDto());
        result.setDimensionType(1);
        return result;
    }

    public DimensionTypeEnum getDimensionType(String id) {
        if (id == null) {
            return DimensionTypeEnum.Unknown;
        }
        String lowerId = id.toLowerCase();
        Map<String, DimensionTypeEnum> map = new HashMap<>();
        map.put(DimensionConstant.BusinessUnitId, DimensionTypeEnum.BusinessUnit);
        map.put(DimensionConstant.AreaId, DimensionTypeEnum.Area);
        map.put(DimensionConstant.OrganizationStructureId, DimensionTypeEnum.OrganizationStructure);
        map.put(DimensionConstant.IndustryId, DimensionTypeEnum.Industry);
        if (map.containsKey(lowerId)) {
            return map.get(lowerId);
        }
        return DimensionTypeEnum.SelfDimension;
    }

    public DimensionTypeEnum getDimensionTypeMore(String id) {
        if (id == null) {
            return DimensionTypeEnum.SelfDimension;
        }
        String lowerId = id.toLowerCase();

        Map<String, DimensionTypeEnum> map = new HashMap<>();

        map.put(DimensionConstant.BusinessUnitId, DimensionTypeEnum.BusinessUnit);
        map.put(DimensionConstant.AreaId, DimensionTypeEnum.Area);
        map.put(DimensionConstant.IndustryId, DimensionTypeEnum.Industry);
        map.put(DimensionConstant.UserId, DimensionTypeEnum.User);
        map.put(DimensionConstant.OrgSubChildrenId, DimensionTypeEnum.OrgSubChildren);
        map.put(DimensionConstant.StockId, DimensionTypeEnum.Stock);
        if (map.containsKey(lowerId)) {
            return map.get(lowerId);
        }
        return DimensionTypeEnum.SelfDimension;
    }

    public List<DimensionDto> getDimensionList() {
        DimensionExample example = new DimensionExample();
        example.setOrderByClause("IS_ACTIVE desc, ORDER_INDEX asc");
        List<Dimension> dimensionList = dimensionMapper.selectByExample(example);
        return convertToDimensionList(dimensionList);
    }

    private List<DimensionDto> convertToDimensionList(List<Dimension> dimensionList) {
        Assert.notNull(dimensionList, "Null list");
        return dimensionList.stream().filter(Objects::nonNull)
                .map(x -> CommonUtils.copyProperties(x, new DimensionDto())).collect(Collectors.toList());
    }

    public DimensinTypeOrgDto getDimensionById(final String id) {
        Assert.hasText(id, "Empty dimensionId");
        Dimension record = findByIdAndIsActiveTrue(id);
        DimensinTypeOrgDto result = new DimensinTypeOrgDto();
        if (record != null) {
            result.setId(record.getId());
            result.setName(record.getName());
        }
        DimensionTypeEnum dimensionTypeEnum = getDimensionTypeMore(id);
        Assert.notNull(dimensionTypeEnum, "Null DimensionTypeEnum");
        result.setDimensionType(dimensionTypeEnum.value());
        return result;
    }

    private Dimension findByIdAndIsActiveTrue(String id) {
        DimensionExample example = new DimensionExample();
        example.createCriteria().andIdEqualTo(id).andIsActiveEqualTo(true);
        example.setOrderByClause("ORDER_INDEX asc");

        return dimensionMapper.selectByExample(example).stream().findFirst().orElse(null);
    }

    public List<Dimension> findByIsActiveTrue() {
        DimensionExample example = new DimensionExample();
        example.createCriteria().andIsActiveEqualTo(true);
        return dimensionMapper.selectByExample(example);
    }

    private List<Dimension> findDimensionOrderByIsActiveDescAndOrderIndexAsc() {
        DimensionExample example = new DimensionExample();
        example.setOrderByClause("IS_ACTIVE desc, ORDER_INDEX asc");
        return dimensionMapper.selectByExample(example);
    }

    public List<DimensionValueOrgDto> getAllDimensionOrgList() {
        List<Dimension> dimensionList = dimensionMapper.selectByExample(null);
        List<DimensionValue> dimensionValueList = dimensionValueMapper.selectByExample(null);
        List<DimensionValueOrg> dimensionValueOrgList = dimensionValueOrgMapper.selectByExample(null);

        List<DimensionValueOrgDto> retList = new ArrayList<>();
        for (Dimension item : dimensionList) {
            List<DimensionValue> whereDimensionValueList = dimensionValueList.stream()
                    .filter(x -> x.getDimensionId() != null && x.getDimensionId().equals(item.getId()))
                    .collect(Collectors.toList());
            if (!Lang.isEmpty(whereDimensionValueList)) {
                for (DimensionValue value : whereDimensionValueList) {
                    List<DimensionValueOrg> whereDimensionValueOrgList = dimensionValueOrgList.stream().filter(
                            x -> x.getDimensionValueId() != null && x.getDimensionValueId().equals(value.getId()))
                            .collect(Collectors.toList());
                    if (!Lang.isEmpty(whereDimensionValueOrgList)) {
                        for (DimensionValueOrg valueOrg : whereDimensionValueOrgList) {
                            DimensionValueOrgDto dimensionValueOrgDto = new DimensionValueOrgDto();
                            dimensionValueOrgDto.setDimensionValue(value.getName());
                            dimensionValueOrgDto.setDimensionId(value.getDimensionId());
                            dimensionValueOrgDto.setDimensionValueId(value.getId());
                            dimensionValueOrgDto.setId(valueOrg.getId());
                            dimensionValueOrgDto.setOrganizationId(valueOrg.getOrganizationId());
                            dimensionValueOrgDto.setDimensionName(item.getName());
                            retList.add(dimensionValueOrgDto);
                        }
                    }
                    if (Lang.isEmpty(whereDimensionValueOrgList)) {
                        DimensionValueOrgDto dimensionValueOrgDto = new DimensionValueOrgDto();
                        dimensionValueOrgDto.setDimensionValue(value.getName());
                        dimensionValueOrgDto.setDimensionId(value.getDimensionId());
                        dimensionValueOrgDto.setDimensionValueId(value.getId());
                        dimensionValueOrgDto.setId("");
                        dimensionValueOrgDto.setOrganizationId("");
                        dimensionValueOrgDto.setDimensionName(item.getName());
                        retList.add(dimensionValueOrgDto);
                    }
                }
            }
            // "进入一条数据,保证纬度是有的"
            if (Lang.isEmpty(whereDimensionValueList)) {
                DimensionValueOrgDto dimensionValueOrgDto = new DimensionValueOrgDto();
                dimensionValueOrgDto.setDimensionValue("");
                dimensionValueOrgDto.setDimensionId(item.getId());
                dimensionValueOrgDto.setDimensionValueId("");
                dimensionValueOrgDto.setId("");
                dimensionValueOrgDto.setOrganizationId("");
                dimensionValueOrgDto.setDimensionName(item.getName());
                retList.add(dimensionValueOrgDto);
            }
        }
        return retList;
    }

    @SuppressWarnings("rawtypes")
    public OperationResultDto updateDimension(DimensionDto model) {
        Assert.notNull(model, "Null model");
        final String modelName = model.getName();
        Assert.hasText(modelName, "Empty name");
        Assert.hasText(model.getId(), "Empty id");
        DimensionExample example = new DimensionExample();
        example.createCriteria().andIdNotEqualTo(model.getId()).andNameEqualTo(model.getName());
        long existCount = dimensionMapper.countByExample(example);
        if (existCount > 0) {
            return new OperationResultDto<>(false, DimensionMessage.DimensionRepeate);
        }
        Dimension entity = dimensionMapper.selectByPrimaryKey(model.getId());
        Assert.notNull(entity, "Cannot find record by id:" + model.getId());
        Dimension copy = CommonUtils.copyProperties(entity, new Dimension());

        if (!modelName.equals(entity.getName()) && StringUtils.hasText(entity.getAttributeId())) {
            // 同步更新属性名
            updateStatisticAttributeName(modelName, entity.getAttributeId());
        }

        entity.setName(modelName);
        entity.setIsActive(BooleanUtils.isTrue(model.getIsActive()));
        entity.setIsMandatory(BooleanUtils.isTrue(model.getIsMandatory()));
        entity.setUpdateBy(authUserHelper.getCurrentUserId());
        entity.setUpdateTime(new Date());
        dimensionMapper.updateByPrimaryKey(entity);

        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setOperateLogType(OperateLogType.OperationLogBasicData.value());
        updateLogParams.setComment("");
        updateLogParams.setOperationModule(OperationModule.BasicDataDimension.value());
        updateLogParams.setOperationContent("");
        updateLogParams.setOriginalState(copy);
        updateLogParams.setUpdateState(entity);
        updateLogParams.setOperationObject(entity.getName());
        updateLogParams.setOperationAction(OperationAction.Update.value());
        operationLogService.updateDataAddLog(updateLogParams);

        return new OperationResultDto<>(true);
    }

    private void updateStatisticAttributeName(String modelName, String entityAttributeId) {
        StatisticAttribute record = new StatisticAttribute();
        record.setName(modelName);
        StatisticAttributeExample example1 = new StatisticAttributeExample();
        example1.createCriteria().andIdEqualTo(entityAttributeId);
        statisticAttributeMapper.updateByExampleSelective(record, example1);
    }

    public List<DimensionValueDto> getDimensionValueList(String dimensionId) {
        Assert.hasText(dimensionId, "Empty dimensionId");
        List<DimensionValueDto> list;
        if (DimensionConstant.BusinessUnitId.equals(dimensionId)) {
            List<BusinessUnit> tmpList = businessUnitService.findByIsActiveTrue();
            list = tmpList.stream().map(x -> {
                DimensionValueDto item = new DimensionValueDto();
                item.setDimensionId(dimensionId);
                item.setIsActive(true);
                item.setName(x.getName());
                item.setId(x.getId());
                return item;
            }).collect(Collectors.toList());
        } else {
            List<DimensionValue> tmpList = findDimensionValueByDimensionIdAndIsActiveTrue(dimensionId);
            list = tmpList.stream().map(x -> CommonUtils.copyProperties(x, new DimensionValueDto()))
                    .collect(Collectors.toList());
        }
        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public List<DevTreeDto> getDevDimensionTreeList() {
        List<DevTreeDto> devTreeList = new ArrayList<>();
        List<Dimension> query = findDimensionOrderByIsActiveDescAndOrderIndexAsc();
        List<DimensionValueDto> list = query.stream().map(x -> CommonUtils.copyProperties(x, new DimensionValueDto()))
                .collect(Collectors.toList());
        list.forEach(item -> {
            DevTreeDto dto = new DevTreeDto<Object>();
            dto.setId(item.getId());
            dto.setText(item.getName());
            dto.setExpanded(false);
            List<DimensionValueDto> dimensionValueList = getDimensionValueList(item.getId());
            List<DevTreeDto> children = dimensionValueList.stream().map((DimensionValueDto x) -> {
                DevTreeDto tmp = new DevTreeDto<>();
                tmp.setId(x.getId());
                tmp.setText(x.getName());
                tmp.setParentId(item.getId());
                tmp.setExpanded(false);
                return tmp;
            }).collect(Collectors.toList());
            dto.setItems(children);
            devTreeList.add(dto);
        });

        return devTreeList;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public OperationResultDto addDimension(DimensionDto model) {
        Assert.notNull(model, "Null model");
        Assert.hasText(model.getName(), "Empty name");
        if (existByName(model.getName())) {
            return new OperationResultDto(false, DimensionMessage.DimensionRepeate);
        }
        Dimension entity = new Dimension();
        CommonUtils.copyProperties(model, entity);
        entity.setId(CommonUtils.getUUID());
        Short orderIndex = dimensionMapper.selectByExample(null).stream().map(Dimension::getOrderIndex)
                .filter(Objects::nonNull).max(Comparator.naturalOrder()).orElse(Short.valueOf("0"));

        entity.setOrderIndex(orderIndex);
        entity.setIsSystemDimension(false);
        // Boolean字段不能为空
        entity.setIsMandatory(BooleanUtils.isTrue(entity.getIsMandatory()));
        // Boolean字段不能为空
        // 推断出IsActive的值需要前端指定为True
        entity.setIsActive(BooleanUtils.isTrue(entity.getIsActive()));
        String currentUserId = authUserHelper.getCurrentUserId();
        entity.setCreateBy(currentUserId);
        entity.setUpdateBy(currentUserId);
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());

        StatisticAttribute attr = new StatisticAttribute();
        attr.setCreateTime(new Date());
        attr.setUpdateTime(new Date());
        attr.setId(CommonUtils.getUUID());
        attr.setIsActive(true);
        attr.setName(entity.getName());

        entity.setAttributeId(attr.getId());

        statisticAttributeMapper.insert(attr);
        dimensionMapper.insert(entity);

        // 默认添加自定义显示三个系统维度
        List<StatisticAttributeDisplayDto> attributeList = new ArrayList<>();
        {
            StatisticAttributeDisplayDto element = new StatisticAttributeDisplayDto();
            element.setAttributeId(DimensionConstant.OrgSubChildrenId);
            element.setDimensionId(entity.getId());
            attributeList.add(element);
        }
        {
            StatisticAttributeDisplayDto element = new StatisticAttributeDisplayDto();
            element.setAttributeId(DimensionConstant.UserId);
            element.setDimensionId(entity.getId());
            attributeList.add(element);
        }
        {
            StatisticAttributeDisplayDto element = new StatisticAttributeDisplayDto();
            element.setAttributeId(DimensionConstant.AreaId);
            element.setDimensionId(entity.getId());
            attributeList.add(element);
        }

        statisticAttributeService.updateStatisticAttribute(attributeList);

        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setComment("");
        updateLogParams.setOperateLogType(OperateLogType.OperationLogBasicData.value());
        updateLogParams.setOperationModule(OperationModule.BasicDataDimension.value());
        updateLogParams.setOperationContent("");
        updateLogParams.setOperationAction(OperationAction.New.value());
        updateLogParams.setOperationObject(model.getName());
        updateLogParams.setUpdateState("");
        updateLogParams.setOriginalState("");
        operationLogService.addOrDeleteDataAddLog(updateLogParams);

        DimensionDto dto = new DimensionDto();
        dto.setDimensionType(DimensionTypeEnum.SelfDimension.value());
        return new OperationResultDto(true, null, dto);
    }

    private boolean existByName(String name) {
        DimensionExample example = new DimensionExample();
        example.createCriteria().andNameEqualTo(name);
        return dimensionMapper.countByExample(example) > 0;
    }

    @SuppressWarnings("rawtypes")
    public OperationResultDto addDimensionValue(DimensionValueDto model) {
        Assert.notNull(model, "Null model");
        Assert.hasText(model.getName(), "Empty name");
        Assert.hasText(model.getDimensionId(), "Empty dimensionId");
        if (existDimensionValueByNameAndDimensionId(model.getName(), model.getDimensionId())) {
            return new OperationResultDto(false, DimensionValueMessage.DimenDimensionValueRepeat);
        }
        DimensionValue entity = new DimensionValue();
        CommonUtils.copyProperties(model, entity);
        entity.setId(CommonUtils.getUUID());
        // Boolean字段不能为空
        // 推断出IsActive的值需要前端指定为True
        entity.setIsActive(BooleanUtils.isTrue(entity.getIsActive()));
        entity.setDimensionId(model.getDimensionId());
        String currentUserId = authUserHelper.getCurrentUserId();
        entity.setCreateBy(currentUserId);
        entity.setUpdateBy(currentUserId);
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        dimensionValueMapper.insert(entity);

        String dimensionName = getDimensionById(model.getDimensionId()).getName();

        // 添加日志

        List<UpdateLogParams> logList = Stream
                .of(OperateLogType.OperationLogOrganization.value(), OperateLogType.OperationLogBasicData.value())
                .map(logType -> {
                    UpdateLogParams updateLogParams = new UpdateLogParams();
                    updateLogParams.setComment(LogMessage.AddDimensionValue);
                    updateLogParams.setOperateLogType(logType);
                    updateLogParams.setOperationModule(OperationModule.BasicDataDimensionValue.value());
                    updateLogParams.setOperationContent("");
                    updateLogParams.setOperationAction(OperationAction.New.value());
                    updateLogParams
                            .setOperationObject(dimensionName + CommonConstants.DashSignSeparator + model.getName()); // 维度名称-维度值名称
                    updateLogParams.setUpdateState("");
                    updateLogParams.setOriginalState("");
                    return updateLogParams;
                }).collect(toList());

        operationLogService.addOrDeleteDataAddLog(logList);

        return new OperationResultDto(true);
    }

    private boolean existDimensionValueByNameAndDimensionId(String name, String dimensionId) {
        DimensionValueExample example = new DimensionValueExample();
        example.createCriteria().andNameEqualTo(name).andDimensionIdEqualTo(dimensionId);
        return dimensionValueMapper.countByExample(example) > 0;
    }

    @SuppressWarnings("rawtypes")
    public OperationResultDto updateDimensionValue(DimensionValueDto model) {
        Assert.notNull(model, "Null model");
        Assert.hasText(model.getName(), "Empty name");
        Assert.hasText(model.getDimensionId(), "Empty dimensionId");
        if (existDimensionValueByNameAndDimensionIdNotEqualTo(model.getName(), model.getDimensionId())) {
            return new OperationResultDto(false, DimensionValueMessage.DimenDimensionValueRepeat);
        }
        DimensionValue entity = dimensionValueMapper.selectByPrimaryKey(model.getId());
        Assert.notNull(entity, "Cannot find record by id:" + model.getId());
        DimensionValue copy = CommonUtils.copyProperties(entity, new DimensionValue());
        entity.setName(model.getName());
        entity.setIsActive(BooleanUtils.isTrue(model.getIsActive()));
        entity.setUpdateBy(authUserHelper.getCurrentUserId());
        entity.setUpdateTime(new Date());
        dimensionValueMapper.updateByPrimaryKey(entity);

        String dimensionName = getDimensionById(model.getDimensionId()).getName();

        List<UpdateLogParams> logList = Stream
                .of(OperateLogType.OperationLogOrganization.value(), OperateLogType.OperationLogBasicData.value())
                .map(logType -> {
                    UpdateLogParams updateLogParams = new UpdateLogParams();
                    updateLogParams.setOperateLogType(logType);
                    updateLogParams.setComment(LogMessage.UpdateDimensionValue);
                    updateLogParams.setOperationModule(OperationModule.BasicDataDimensionValue.value());
                    updateLogParams.setOperationContent("");
                    updateLogParams.setOriginalState(copy);
                    updateLogParams.setUpdateState(entity);
                    updateLogParams
                            .setOperationObject(dimensionName + CommonConstants.DashSignSeparator + model.getName());
                    updateLogParams.setOperationAction(OperationAction.Update.value());
                    return updateLogParams;
                }).collect(toList());

        operationLogService.updateDataAddLog(logList);

        return new OperationResultDto(true);
    }

    private boolean existDimensionValueByNameAndDimensionIdNotEqualTo(String name, String dimensionId) {
        DimensionValueExample example = new DimensionValueExample();
        example.createCriteria().andNameEqualTo(name).andDimensionIdNotEqualTo(dimensionId);
        return dimensionValueMapper.countByExample(example) > 0;
    }

    public List<DimensionValueOrgDto> getAllDimensionOrgListByOrgId(String orgid) {
        List<Dimension> dimensionList = dimensionMapper.selectByExample(null);
        List<DimensionValue> dimensionValueList = dimensionValueMapper.selectByExample(null);
        List<DimensionValueOrg> dimensionValueOrgList = dimensionValueOrgMapper.selectByExample(null);

        List<DimensionValueOrgDto> retList = new ArrayList<>();
        for (Dimension item : dimensionList) {
            List<DimensionValue> whereDimensionValueList = dimensionValueList.stream()
                    .filter(x -> x.getDimensionId() != null && x.getDimensionId().equals(item.getId()))
                    .collect(Collectors.toList());
            if (!Lang.isEmpty(whereDimensionValueList)) {
                for (DimensionValue value : whereDimensionValueList) {
                    List<DimensionValueOrg> whereDimensionValueOrgList = dimensionValueOrgList.stream()
                            .filter(x -> x.getDimensionValueId() != null
                                    && x.getDimensionValueId().equals(value.getId())
                                    && Objects.equals(orgid, x.getOrganizationId()))
                            .collect(Collectors.toList());
                    if (!Lang.isEmpty(whereDimensionValueOrgList)) {
                        for (DimensionValueOrg valueOrg : whereDimensionValueOrgList) {
                            DimensionValueOrgDto dimensionValueOrgDto = new DimensionValueOrgDto();
                            dimensionValueOrgDto.setDimensionValue(value.getName());
                            dimensionValueOrgDto.setDimensionId(value.getDimensionId());
                            dimensionValueOrgDto.setDimensionValueId(value.getId());
                            dimensionValueOrgDto.setId(valueOrg.getId());
                            dimensionValueOrgDto.setOrganizationId(valueOrg.getOrganizationId());
                            dimensionValueOrgDto.setDimensionName(item.getName());
                            retList.add(dimensionValueOrgDto);
                        }
                    }
                    if (Lang.isEmpty(whereDimensionValueOrgList)) {
                        DimensionValueOrgDto dimensionValueOrgDto = new DimensionValueOrgDto();
                        dimensionValueOrgDto.setDimensionValue(value.getName());
                        dimensionValueOrgDto.setDimensionId(value.getDimensionId());
                        dimensionValueOrgDto.setDimensionValueId(value.getId());
                        dimensionValueOrgDto.setId("");
                        dimensionValueOrgDto.setOrganizationId("");
                        dimensionValueOrgDto.setDimensionName(item.getName());
                        retList.add(dimensionValueOrgDto);
                    }
                }
            }
            // "进入一条数据,保证纬度是有的"
            if (Lang.isEmpty(whereDimensionValueList)) {
                DimensionValueOrgDto dimensionValueOrgDto = new DimensionValueOrgDto();
                dimensionValueOrgDto.setDimensionValue("");
                dimensionValueOrgDto.setDimensionId(item.getId());
                dimensionValueOrgDto.setDimensionValueId("");
                dimensionValueOrgDto.setId("");
                dimensionValueOrgDto.setOrganizationId("");
                dimensionValueOrgDto.setDimensionName(item.getName());
                retList.add(dimensionValueOrgDto);
            }
        }
        return retList;
    }
}