package pwc.taxtech.atms.service.impl;

import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
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.constant.DimensionConstant;
import pwc.taxtech.atms.dpo.StatisticAttributeDisplayDto;
import pwc.taxtech.atms.dto.OperationLogDto;
import pwc.taxtech.atms.dto.OperationResultDto;
import pwc.taxtech.atms.dto.StatisticAttributeDimensionDto;
import pwc.taxtech.atms.dto.StatisticAttributeDto;
import pwc.taxtech.atms.dto.dimension.AttributeTypeEnum;
import pwc.taxtech.atms.entity.Dimension;
import pwc.taxtech.atms.entity.StatisticAttribute;
import pwc.taxtech.atms.entity.StatisticAttributeDimension;
import pwc.taxtech.atms.entity.StatisticAttributeDimensionExample;
import pwc.taxtech.atms.entity.StatisticAttributeExample;
import pwc.taxtech.atms.exception.ApplicationException;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Comparator.*;
import static java.util.stream.Collectors.toList;
import static org.springframework.util.StringUtils.hasText;
import static pwc.taxtech.atms.common.CommonUtils.copyProperties;

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

    @Autowired
    private DimensionServiceImpl dimensionService;
    @Autowired
    private DictionaryServiceImpl dictionaryService;

    public List<StatisticAttributeDisplayDto> getStatisticAttributeListByDimensionId(String parentDimensionId,
                                                                                     List<StatisticAttributeDisplayDto> rawAttrList) {
        // parentDimensionId = "c61a5bd6-a996-4952-9869-d053995237e5";
        List<StatisticAttributeDisplayDto> list = myStatisticAttributeMapper
                .selectByParentDimensionId(parentDimensionId);
        logger.debug("list size:{}", list.size());

        if (DimensionConstant.OrgSubChildrenId.equalsIgnoreCase(parentDimensionId)) {
            List<StatisticAttributeDisplayDto> orgList = myStatisticAttributeMapper
                    .selectByOrgSubChildrenId(parentDimensionId);
            list.addAll(orgList);
            list.sort(comparing(StatisticAttributeDisplayDto::getOrderIndex, nullsFirst(naturalOrder())));
        }

        List<Dimension> dimensionList = dimensionService.findByIsActiveTrue();
        for (StatisticAttributeDisplayDto attr : list) {
            // 事业部
            if (DimensionConstant.Attribute.BusinessUnitId.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.BusinessUnit.value());
            } // 机构代码
            else if (DimensionConstant.Attribute.OrgCode.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.OrgCode.value());
            } // 纳税人识别号
            else if (DimensionConstant.Attribute.TaxPayerNumber.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.TaxPayerNumber.value());
            } // 行政区域
            else if (DimensionConstant.Attribute.RegionId.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.RegionId.value());
            } // 所属行业
            else if (DimensionConstant.Attribute.IndustryId.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.Industry.value());
            } // 子分公司,机构
            else if (DimensionConstant.Attribute.OrgSubChildrenId.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.OrgSubChildren.value());
            } // //如果是机构层级
            else if (DimensionConstant.Attribute.OrganizationStructureId.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.OrganizationStructure.value());
            } // 覆盖区域
            else if (DimensionConstant.Attribute.AreaId.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.Area.value());
            } // 用户数
            else if (DimensionConstant.Attribute.UserId.equalsIgnoreCase(attr.getAttributeId())) {
                attr.setAttributeType(AttributeTypeEnum.User.value());
            } else // 如果是自定义属性,维度值的列表,多少维度,如产品维度,值为产品1,产品2,产品3 等
            {
                attr.setAttributeType(AttributeTypeEnum.SelfDimension.value());
            }
            Optional<Dimension> d = dimensionList.stream()
                    .filter(x -> (x.getAttributeId() != null) && x.getAttributeId().equals(attr.getAttributeId()))
                    .findFirst();
            d.ifPresent(x -> attr.setBelongDimensionId(Strings.sBlank(x.getId())));
        }

        if (rawAttrList != null) {
            // 未经任何筛选的属性
            rawAttrList.addAll(list);
        }
        List<StatisticAttributeDisplayDto> result;
        if (DimensionConstant.OrgSubChildrenId.equalsIgnoreCase(parentDimensionId)) {
            result = list.stream().filter(x -> x.getOrderIndex() != null && x.getOrderIndex() >= 2)
                    .collect(Collectors.toList());
        } else {
            result = list;
        }
        return result;
    }

    @SuppressWarnings("rawtypes")
    public OperationResultDto updateStatisticAttribute(List<StatisticAttributeDisplayDto> modelList) {
        if (!Lang.isEmpty(modelList)) {
            doUpdateStatisticAttribute(modelList);
        }
        return new OperationResultDto(true);
    }

    private void doUpdateStatisticAttribute(List<StatisticAttributeDisplayDto> modelList) {
        List<StatisticAttributeDimensionDto> attrList = new ArrayList<>();
        String dimensionId = modelList.stream().findFirst().map(StatisticAttributeDisplayDto::getDimensionId)
                .orElseThrow(ApplicationException::new);

        StatisticAttributeDimensionExample example = new StatisticAttributeDimensionExample();
        example.createCriteria().andDimensionIdEqualTo(dimensionId);
        List<StatisticAttributeDimension> oldData = statisticAttributeDimensionMapper.selectByExample(example);
        oldData.stream().map(StatisticAttributeDimension::getId).filter(Objects::nonNull)
                .forEach(statisticAttributeDimensionMapper::deleteByPrimaryKey);

        Dimension dimensionObject = dimensionMapper.selectByPrimaryKey(dimensionId);
        String dimensionName = Optional.ofNullable(dimensionObject).map(Dimension::getName).orElse("");

        List<OperationLogDto> logList = new ArrayList<>();

        oldData.stream().forEach(r -> {
            // C# 的代码如下,会导致attrubuteName的值为空,这里改正
            // var attrubuteObject =
            // this._dbContext.Set<StatisticAttribute>().FirstOrDefault(s => s.id == r.id);
            //
            StatisticAttribute attrubuteObject = statisticAttributeMapper
                    .selectByPrimaryKey(r.getStatisticsAttributeId());
            String attrubuteName = Optional.ofNullable(attrubuteObject).map(StatisticAttribute::getName).orElse("");
            OperationLogDto log = new OperationLogDto();
            log.setLogType(OperateLogType.OperationLogBasicData.value());
            log.setModule(OperationModule.BasicDataStatisticAttribute.value());
            log.setOperationContent(dimensionName);
            log.setAction(OperationAction.Delete.value());
            log.setOperationObject(dimensionName + CommonConstants.DashSignSeparator + attrubuteName);
            log.setOriginalState("");
            log.setUpdateState("");
            logList.add(log);
        });

        short orderIndex = 0;
        for (StatisticAttributeDisplayDto model : modelList) {
            StatisticAttributeDimensionDto dto = new StatisticAttributeDimensionDto();
            dto.setId(CommonUtils.getUUID());
            dto.setDimensionId(dimensionId);
            dto.setStatisticsAttributeId(model.getAttributeId());
            dto.setOrderIndex(orderIndex++);
            attrList.add(dto);

            StatisticAttribute attrubuteObject = statisticAttributeMapper.selectByPrimaryKey(model.getAttributeId());
            String attrubuteName = Optional.ofNullable(attrubuteObject).map(StatisticAttribute::getName).orElse("");

            OperationLogDto log = new OperationLogDto();
            log.setLogType(OperateLogType.OperationLogBasicData.value());
            log.setModule(OperationModule.BasicDataStatisticAttribute.value());
            log.setOperationContent(dimensionName);
            log.setAction(OperationAction.New.value());
            log.setOperationObject(dimensionName + CommonConstants.DashSignSeparator + attrubuteName);
            log.setOriginalState("");
            log.setUpdateState("");
            logList.add(log);
        }

        attrList.stream().map(dto -> CommonUtils.copyProperties(dto, new StatisticAttributeDimension()))
                .forEach(entity -> {
                    statisticAttributeDimensionMapper.insert(entity);
                });

        operationLogService.addOperationLogList(logList);
    }

    public List<StatisticAttributeDto> getStatisticAttributeList(String dictionaryCode) {
        StatisticAttributeExample example = new StatisticAttributeExample();
        example.createCriteria().andIsActiveEqualTo(true);
        List<StatisticAttributeDto> list = statisticAttributeMapper.selectByExample(example).stream()
                .map(x -> copyProperties(x, new StatisticAttributeDto())).collect(toList());
        if (hasText(dictionaryCode)) {
            List<StatisticAttributeDto> convertedList = dictionaryService.getDictionaryByCode(dictionaryCode).stream()
                    .map(dictionary -> {
                        StatisticAttributeDto item = new StatisticAttributeDto();
                        item.setId(dictionary.getId());
                        item.setName(dictionary.getDictValue());
                        item.setIsActive(true);
                        item.setIsOrgSelfProperty(true);
                        return item;
                    }).collect(toList());

            // union两个list,需要去重复
            list = Stream.concat(convertedList.stream(), list.stream()).distinct().collect(toList());
        }
        return list;
    }

    public List<StatisticAttributeDisplayDto> getOrgSubChildrenStatAttributeList(String parentDimensionId) {
        List<StatisticAttributeDisplayDto> query = myStatisticAttributeMapper
                .selectByParentDimensionId(parentDimensionId);
        if (DimensionConstant.OrgSubChildrenId.equals(parentDimensionId)) {
            List<StatisticAttributeDisplayDto> orgQuery = myStatisticAttributeMapper
                    .selectByOrgSubChildrenId(parentDimensionId);
            query.addAll(orgQuery);
        }
        query.sort(comparing(StatisticAttributeDisplayDto::getOrderIndex, nullsLast(naturalOrder())));
        return query;
    }
}