package jnpf.qualifications.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jnpf.base.service.SuperServiceImpl;
import jnpf.constants.QualificationsConstant;
import jnpf.cultivate.utils.UserApiV2Util;
import jnpf.entity.qualifications.*;
import jnpf.exception.HandleException;
import jnpf.model.qualifications.dto.PaginationQualificationsDTO;
import jnpf.model.qualifications.dto.SaveQualificationsDTO;
import jnpf.model.qualifications.dto.SaveQualificationsFieldDTO;
import jnpf.model.qualifications.dto.SaveQualificationsFieldItemDTO;
import jnpf.model.qualifications.vo.GradeVOExp;
import jnpf.model.qualifications.vo.QualificationsInfoVO;
import jnpf.model.qualifications.vo.QualificationsStatisticsVO;
import jnpf.permission.vo.v2.grades.GradeVO;
import jnpf.permission.vo.v2.position.PositionAndGradesVO;
import jnpf.permission.vo.v2.position.PositionVO;
import jnpf.qualifications.mapper.QualificationsMapper;
import jnpf.qualifications.service.*;
import jnpf.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 任职资格标准
 *
 * @author Flynn Chan
 * @create 2024-03-04
 */
@Slf4j
@Service
public class QualificationsServiceImpl extends SuperServiceImpl<QualificationsMapper, Qualifications> implements QualificationsService {

    @Resource
    private QualificationsFieldItemRelationService qualificationsFieldItemRelationService;

    @Resource
    private QualificationsFieldService qualificationsFieldService;
    @Resource
    private QualificationsFieldCategoryService qualificationsFieldCategoryService;
    @Resource
    private QualificationsFieldItemService qualificationsFieldItemService;
    @Autowired
    private UserApiV2Util userApiV2Util;

    @Override
    public List<Qualifications> pageList(PaginationQualificationsDTO queryDTO) {
        QueryWrapper<Qualifications> queryWrapper = new QueryWrapper<>();
        if (!StringUtil.isEmpty(queryDTO.getKeyword())) {

            List<PositionAndGradesVO> voList = userApiV2Util.likeQueryPositionForPositionName(queryDTO.getKeyword(), null);
            //null 则return
            if (CollUtil.isEmpty(voList)) {
                return new ArrayList<>();
            }
            queryWrapper.lambda().in(Qualifications::getPositionId, voList.stream().map(PositionAndGradesVO::getId).collect(Collectors.toList()));
        }
        // position grades
        if (StrUtil.isNotBlank(queryDTO.getPositionId())) {
            queryWrapper.lambda().eq(Qualifications::getPositionId, queryDTO.getPositionId());
        }
        if (StrUtil.isNotBlank(queryDTO.getPositionGradesId())) {
            queryWrapper.lambda().eq(Qualifications::getPositionGradesId, queryDTO.getPositionGradesId());
        }
        if (queryDTO.getUpdateDateStart() != null) {
            queryWrapper.lambda().ge(Qualifications::getLastModifyTime, DateUtil.date(queryDTO.getUpdateDateStart()));
        }
        if (queryDTO.getUpdateDateEnd() != null) {
            queryWrapper.lambda().le(Qualifications::getLastModifyTime, DateUtil.date(queryDTO.getUpdateDateEnd()));
        }

        queryWrapper.lambda().orderByAsc(Qualifications::getSortCode).orderByDesc(Qualifications::getPositionId).orderByDesc(Qualifications::getLastModifyTime);
        if (queryDTO.getIsPage()) {
            PageHelper.startPage((int) queryDTO.getCurrentPage(), (int) queryDTO.getPageSize());
            PageHelper.startPage((int) queryDTO.getCurrentPage(), (int) queryDTO.getPageSize());
            PageInfo<Qualifications> page = new PageInfo<>(this.list(queryWrapper));

            return queryDTO.setData(page.getList(), page.getTotal());
        } else {
            return this.list(queryWrapper);
        }
    }

    /**
     * 根据职级查询
     * @param gradeId 职级id
     * @return
     */
    @Override
    public List<Qualifications> selectByGradeId(String gradeId) {
        return baseMapper.selectList(new LambdaQueryWrapper<Qualifications>().eq(Qualifications::getPositionGradesId, gradeId).eq(Qualifications::getDeleteMark, 0));
    }

    @Override
    public List<Qualifications> selectByGradeIdAndPositionId(String positionId, String gradeId) {
        return baseMapper.selectList(new LambdaQueryWrapper<Qualifications>().eq(Qualifications::getPositionId, positionId).eq(Qualifications::getPositionGradesId, gradeId).eq(Qualifications::getDeleteMark, 0));
    }

    @Override
    public QualificationsInfoVO info(String id) throws Exception {
        Qualifications qualifications = this.getById(id);
        if (qualifications == null) {
            throw new HandleException("该任职资格信息不存在");
        }
        QualificationsInfoVO qualificationsInfoVO = new QualificationsInfoVO();
        qualificationsInfoVO.setId(qualifications.getId());
        qualificationsInfoVO.setPositionId(qualifications.getPositionId());
        qualificationsInfoVO.setPositionEncode(qualifications.getPositionEncode());
        qualificationsInfoVO.setPositionGradesId(qualifications.getPositionGradesId());
        //position and glades
//        PositionEntity position = positionApi.queryInfoById(qualificationsInfoVO.getPositionId());
        PositionVO position = userApiV2Util.infoPosition(qualificationsInfoVO.getPositionId(), null);
        if (position != null) {
            qualificationsInfoVO.setPositionName(position.getFullName());
        }
        List<GradeVO> gradeVOS = userApiV2Util.listGradeByIds(List.of(qualificationsInfoVO.getPositionGradesId().split(",")), null);
        if (CollUtil.isNotEmpty(gradeVOS)) {
            qualificationsInfoVO.setPositionGradesName(gradeVOS.get(0).getFullName());
        }

        List<QualificationsFieldItemRelation> qualificationsFieldItemRelations = qualificationsFieldItemRelationService.list(
                Wrappers.<QualificationsFieldItemRelation>lambdaQuery()
                        .eq(QualificationsFieldItemRelation::getQualificationsId, qualifications.getId())
        );
        List<SaveQualificationsFieldDTO> qualificationsFieldDTOS = new ArrayList<>();
        Map<String, List<QualificationsFieldItemRelation>> dataList = qualificationsFieldItemRelations.stream()
                .collect(Collectors.groupingBy(QualificationsFieldItemRelation::getFieldId));
        for (Map.Entry<String, List<QualificationsFieldItemRelation>> entry : dataList.entrySet()) {
            String fieldId = entry.getKey();
            SaveQualificationsFieldDTO saveQualificationsFieldDTO = new SaveQualificationsFieldDTO();
            saveQualificationsFieldDTO.setFieldId(fieldId);
            QualificationsField qualificationsField = qualificationsFieldService.getById(fieldId);
            saveQualificationsFieldDTO.setFieldName(qualificationsField == null ? QualificationsConstant.NONE_FIELD : qualificationsField.getName());
            if (qualificationsField == null) {
                saveQualificationsFieldDTO.setCategoryId(QualificationsConstant.NONE_FIELD_CATEGORY);
                saveQualificationsFieldDTO.setCategoryName(QualificationsConstant.NONE_FIELD_CATEGORY);
            } else {
                QualificationsFieldCategory qualificationsFieldCategory = qualificationsFieldCategoryService.getCategoryById(qualificationsField.getCategoryId());
                saveQualificationsFieldDTO.setCategoryId(qualificationsFieldCategory == null ? QualificationsConstant.NONE_FIELD_CATEGORY : qualificationsFieldCategory.getId());
                saveQualificationsFieldDTO.setCategoryName(qualificationsFieldCategory == null ? QualificationsConstant.NONE_FIELD_CATEGORY : qualificationsFieldCategory.getName());
            }

            List<QualificationsFieldItemRelation> subList = entry.getValue();
            List<SaveQualificationsFieldItemDTO> saveQualificationsFieldItemDTOS = new ArrayList<>();
            for (QualificationsFieldItemRelation itemRelation : subList) {
                SaveQualificationsFieldItemDTO saveQualificationsFieldItemDTO = new SaveQualificationsFieldItemDTO();
                QualificationsFieldItem qualificationsFieldItem = qualificationsFieldItemService.getById(itemRelation.getItemId());

                saveQualificationsFieldItemDTO.setItemId(itemRelation.getItemId());
                saveQualificationsFieldItemDTO.setContent(itemRelation.getContent());
                saveQualificationsFieldItemDTO.setId(itemRelation.getId());
                //none
                saveQualificationsFieldItemDTO.setItemName(qualificationsFieldItem == null ? QualificationsConstant.NONE_ITEM : qualificationsFieldItem.getName());

                saveQualificationsFieldItemDTOS.add(saveQualificationsFieldItemDTO);
            }

            saveQualificationsFieldDTO.setQualificationsFieldItems(saveQualificationsFieldItemDTOS);
            qualificationsFieldDTOS.add(saveQualificationsFieldDTO);
        }

        qualificationsInfoVO.setQualificationsFields(qualificationsFieldDTOS);

        return qualificationsInfoVO;
    }

    @Override
    @Transactional
    public String insert(SaveQualificationsDTO qualificationsDTO) throws HandleException {
        //position
        PositionVO position = userApiV2Util.infoPosition(qualificationsDTO.getPositionId(), null);
        if (position == null) {
            throw new HandleException("该岗位信息不存在,请检查");
        }
        Qualifications qualifications = new Qualifications(
                position.getId(),
                position.getEnCode(),
                qualificationsDTO.getPositionGradesId()
        );
        //check Only
        if (!checkQualificationsOnly(qualifications.getPositionId(), qualifications.getPositionGradesId())) {
            throw new HandleException("该岗位职等的任职资格标准已存在");
        }
        qualifications.setCreatorTime(new Date());
        qualifications.setLastModifyTime(new Date());
        this.save(qualifications);

        if (CollUtil.isEmpty(qualificationsDTO.getQualificationsFields())) {
            throw new HandleException("必须绑定一个标准字段");
        }
        List<QualificationsFieldItemRelation> qualificationsFieldItemRelations = new ArrayList<>();
        qualificationsDTO.getQualificationsFields().forEach(qualificationsField -> {
            if (CollUtil.isNotEmpty(qualificationsField.getQualificationsFieldItems())) {
                qualificationsField.getQualificationsFieldItems().forEach(item -> {
                    QualificationsFieldItemRelation qualificationsFieldItemRelation = new QualificationsFieldItemRelation(
                            qualifications.getId(),
                            qualificationsField.getFieldId(),
                            item.getItemId(),
                            item.getContent()
                    );

                    qualificationsFieldItemRelation.setCreatorTime(new Date());
                    qualificationsFieldItemRelation.setLastModifyTime(new Date());
                    qualificationsFieldItemRelations.add(qualificationsFieldItemRelation);
                });
            }

        });
        qualificationsFieldItemRelationService.saveBatch(qualificationsFieldItemRelations);

        return qualifications.getId();
    }

    @Override
    @Transactional
    public Boolean update(SaveQualificationsDTO qualificationsDTO) throws HandleException {
        Qualifications qualifications = this.getById(qualificationsDTO.getId());
        if (qualifications == null) {
            throw new HandleException("该任职资格信息不存在");
        }
        qualifications.setId(qualificationsDTO.getId());
        qualifications.setPositionId(qualificationsDTO.getPositionId());
        qualifications.setPositionEncode(qualificationsDTO.getPositionEncode());
        qualifications.setPositionGradesId(qualificationsDTO.getPositionGradesId());

        this.saveOrUpdate(qualifications);

        if (CollUtil.isEmpty(qualificationsDTO.getQualificationsFields())) {
            throw new HandleException("必须绑定一个标准字段");
        }
        List<QualificationsFieldItemRelation> qualificationsFieldItemRelations = new ArrayList<>();
        qualificationsDTO.getQualificationsFields().forEach(qualificationsField -> {
            if (CollUtil.isNotEmpty(qualificationsField.getQualificationsFieldItems())) {
                qualificationsField.getQualificationsFieldItems().forEach(item -> {
                    QualificationsFieldItemRelation qualificationsFieldItemRelation = new QualificationsFieldItemRelation(
                            qualifications.getId(),
                            qualificationsField.getFieldId(),
                            item.getItemId(),
                            item.getContent()
                    );
                    qualificationsFieldItemRelation.setId(item.getId());

                    qualificationsFieldItemRelations.add(qualificationsFieldItemRelation);
                });
            }

        });
        //delete all
        qualificationsFieldItemRelationService.remove(Wrappers.<QualificationsFieldItemRelation>lambdaQuery()
                .eq(QualificationsFieldItemRelation::getQualificationsId, qualifications.getId())
        );

        return qualificationsFieldItemRelationService.saveBatch(qualificationsFieldItemRelations);
    }

    @Override
    @Transactional
    public Boolean delete(String id) throws HandleException {
        Qualifications qualifications = this.getById(id);
        if (qualifications == null) {
            throw new HandleException("该任职资格信息不存在");
        }
        //delete all
        this.deleteAllItemRelation(id);

        return this.removeById(id);
    }

    @Override
    @Transactional
    public Boolean deleteAllItemRelation(String qualificationsId) {
        return qualificationsFieldItemRelationService.remove(Wrappers.<QualificationsFieldItemRelation>lambdaQuery()
                .eq(QualificationsFieldItemRelation::getQualificationsId, qualificationsId)
        );
    }

    @Override
    @Transactional
    public Boolean deleteAllItemRelationByFieldId(String fieldId) {
        return qualificationsFieldItemRelationService.remove(Wrappers.<QualificationsFieldItemRelation>lambdaQuery()
                .eq(QualificationsFieldItemRelation::getFieldId, fieldId)
        );
    }

    @Override
    @Transactional
    public Boolean deleteAllItemRelationByItemIds(List<String> itemIds) {
        return qualificationsFieldItemRelationService.remove(Wrappers.<QualificationsFieldItemRelation>lambdaQuery()
                .in(QualificationsFieldItemRelation::getItemId, itemIds)
        );
    }

    @Override
    public QualificationsStatisticsVO statistics(String organizeId) {
        List<PositionAndGradesVO> positionInfoNewVOList = new ArrayList<>();
        QualificationsStatisticsVO statisticsVO = new QualificationsStatisticsVO(
                organizeId,
                0, 0, 0
        );
        if (StrUtil.isNotBlank(organizeId)) {
            //position
//            positionInfoNewVOList = positionApi.getListByOrganizeIds(organizeId).getData();
            positionInfoNewVOList = userApiV2Util.listPositionAndGradesByPositionNameForOrgIds(organizeId, null);
        } else {
            //all
//            positionInfoNewVOList = positionApi.allInfoList().getData();
            positionInfoNewVOList = userApiV2Util.listAllPositionAndGradesByPositionName(null);
        }

        List<String> gradesIds = new ArrayList<>();

        if (CollUtil.isNotEmpty(positionInfoNewVOList)) {
            statisticsVO.setPositionNum(positionInfoNewVOList.size());
            AtomicReference<Integer> gradesNum = new AtomicReference<>(0);
            positionInfoNewVOList.forEach(positionInfoNewVO -> {
                if (CollUtil.isNotEmpty(positionInfoNewVO.getList())) {
                    gradesNum.getAndSet(gradesNum.get() + positionInfoNewVO.getList().size());
                    positionInfoNewVO.getList().forEach(grades -> {
                        gradesIds.add(grades.getId());
                    });
                }
            });
            //org relation
            if (CollUtil.isNotEmpty(gradesIds)) {
                //grades num
                statisticsVO.setPositionGradesNum(gradesIds.size());
                List<Qualifications> qualificationsList = this.list(Wrappers.<Qualifications>lambdaQuery()
                        .in(Qualifications::getPositionGradesId, gradesIds)
                );
                // link num
                statisticsVO.setQualificationsLinkPositionGradesNum(qualificationsList.size());
            }
        }

        return statisticsVO;
    }

    @Override
    public Boolean checkExistByField(String fieldId) {
        List<QualificationsFieldItemRelation> qualificationsFieldItemRelations = qualificationsFieldItemRelationService.list(Wrappers.<QualificationsFieldItemRelation>lambdaQuery()
                .eq(QualificationsFieldItemRelation::getFieldId, fieldId)
        );

        return CollUtil.isNotEmpty(qualificationsFieldItemRelations);
    }

    @Override
    public Boolean checkExistByItem(String fieldId, String itemId) {
        List<QualificationsFieldItemRelation> qualificationsFieldItemRelations = qualificationsFieldItemRelationService.list(Wrappers.<QualificationsFieldItemRelation>lambdaQuery()
                .eq(QualificationsFieldItemRelation::getFieldId, fieldId)
                .eq(QualificationsFieldItemRelation::getItemId, itemId)
        );

        return CollUtil.isNotEmpty(qualificationsFieldItemRelations);
    }

    @Override
    public List<GradeVOExp> rankList(String id) {
        List<GradeVO> gradeVOS = userApiV2Util.listGrades(id, null);
        if (CollUtil.isEmpty(gradeVOS)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<Qualifications> wrapper = Wrappers.<Qualifications>lambdaQuery()
                .eq(Qualifications::getPositionId, id);
        List<Qualifications> qualificationsList = baseMapper.selectList(wrapper);
        Map<String, Qualifications> map = new HashMap<>();
        if (CollUtil.isNotEmpty(qualificationsList)) {
            for (Qualifications qualifications : qualificationsList) {
                map.put(id + "-" + qualifications.getPositionGradesId(), qualifications);
            }
        }
        List<GradeVOExp> gradeVOExps = BeanUtil.copyToList(gradeVOS, GradeVOExp.class);
        for (GradeVOExp gradeVO : gradeVOExps) {
            Qualifications qualifications = map.get(id + "-" + gradeVO.getId());
            if (qualifications == null) {
                gradeVO.setIsHave(false);
            } else {
                gradeVO.setIsHave(true);
            }
        }


        return gradeVOExps;
    }

    @Override
    public Map<String, Qualifications> rankAllSetList() {
        LambdaQueryWrapper<Qualifications> wrapper = Wrappers.<Qualifications>lambdaQuery();
        List<Qualifications> qualificationsList = baseMapper.selectList(wrapper);
        Map<String, Qualifications> map = new HashMap<>();
        if (CollUtil.isNotEmpty(qualificationsList)) {
            for (Qualifications qualifications : qualificationsList) {
                map.put(qualifications.getPositionId() + "-" + qualifications.getPositionGradesId(), qualifications);
            }
        }
        return map;
    }

    private Boolean checkQualificationsOnly(String positionId, String positionGradesId) {
        List<Qualifications> qualifications = this.list(Wrappers.<Qualifications>lambdaQuery()
                .eq(Qualifications::getPositionId, positionId)
                .eq(Qualifications::getPositionGradesId, positionGradesId)
        );

        return !CollUtil.isNotEmpty(qualifications);
    }
}
