package com.hz.pm.api.expert.assembler;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.hz.pm.api.common.helper.RegionCacheHelper;
import com.hz.pm.api.common.model.FileBasicInfo;
import com.hz.pm.api.expert.constant.ExpertApplyTypeEnum;
import com.hz.pm.api.expert.entity.*;
import com.hz.pm.api.expert.model.*;
import com.hz.pm.api.expert.model.dto.*;
import com.hz.pm.api.expert.model.vo.ExpertFullInfoVO;
import com.hz.pm.api.gov.model.vo.GovBusinessStripVO;
import com.hz.pm.api.meta.constant.ExpertDictTypeEnum;
import com.hz.pm.api.meta.constant.ExpertTagEnum;
import com.hz.pm.api.meta.helper.DictionaryCache;
import com.hz.pm.api.meta.helper.TagCache;
import com.hz.pm.api.meta.model.ExpertRegionInfo;
import com.hz.pm.api.meta.model.dto.DictionaryDTO;
import com.hz.pm.api.meta.model.dto.TagDTO;
import com.hz.pm.api.meta.model.entity.ExpertDictionary;
import com.hz.pm.api.meta.model.entity.ExpertTag;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.file.entity.vo.result.AttachFileVo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author liuxinxin
 * @date 2022/7/27 上午10:46
 */
@Component
@RequiredArgsConstructor
public class ExpertUserInfoAssembler {

    private final TagCache tagCache;
    private final DictionaryCache dictionaryCache;
    private final RegionCacheHelper regionCacheHelper;

    public ExpertFullInfoVO buildExpertDetail(List<AttachFileVo> attachFiles, ExpertFullInfoAllDTO expertFullInfoAll) {
        ExpertUserFullInfoDTO expertUserInfo = expertFullInfoAll.getExpertUserInfoDTO();
        // 字典字典段map
        Map<String, List<DictFieldInfoDTO>> dictMap = buildDictInfoMap(expertFullInfoAll.getExpertDictionaryList());
        // 专家文件资料map
        Map<Long, FileBasicInfo> fileMap = buildFileBasicInfoMap(attachFiles);
        // 专家标签字段map
        Map<String, List<TagFieldInfo>> tagMap = buildTagFieldInfoMap(expertFullInfoAll.getExpertTagList());
        // 专家履职意向地
        List<ExpertRegionDTO> intentionWorkRegions = expertFullInfoAll.getExpertIntentionWorkRegionInfo();
        // 专家回避单位列表
        List<ExpertAvoidCompanyDTO> avoidCompanies = expertFullInfoAll.getExpertAvoidCompanyList();
        // 基本信息
        ExpertBasicInfo basicInfo = convert(expertUserInfo, dictMap, tagMap, intentionWorkRegions);
        // 学历信息
        ExpertEduInfo eduInfo = buildExpertEduInfo(expertUserInfo, dictMap);
        // 职业信息
        ExpertJobInfo jobInfo = buildExpertJobInfo(expertUserInfo, dictMap);
        jobInfo.setBusinessStrips(expertFullInfoAll.getBusinessStrips());
        // 专业信息
        ExpertProfessionalInfo profession = buildExpertProfessionalInfo(expertUserInfo, dictMap, tagMap, fileMap, avoidCompanies);
        // 推荐信息
        ExpertRecommendInfo recommendInfo = new ExpertRecommendInfo();
        recommendInfo.setRecommendedWay(dictMap.get(ExpertDictTypeEnum.RECOMMENDED_WAY.getKey()));
        recommendInfo.setRecommendFile(expertUserInfo.getRecommendFile());
        // 其他信息
        ExpertOtherInfo otherInfo = new ExpertOtherInfo();
        otherInfo.setOther(tagMap.get(ExpertTagEnum.OTHER.getKey()));
        otherInfo.setRemark(expertUserInfo.getRemark());

        // 专家申请履职意向展示列表
        List<ExpertRegionInfo> applyIntentionWorkRegions = expertFullInfoAll.getExpertApplyIntentionWorkRegionInfo().stream().map(r -> {
            ExpertRegionInfo intentionWorkRegion = new ExpertRegionInfo();
            intentionWorkRegion.setRegionLevel(r.getRegionLevel());
            intentionWorkRegion.setRegionCode(r.getRegionCode());
            intentionWorkRegion.setRegionName(regionCacheHelper.getUnionPath(r.getRegionCode(), r.getRegionLevel()));
            return intentionWorkRegion;
        }).collect(Collectors.toList());

        if (CollUtil.isEmpty(basicInfo.getExpertIntentionWorkRegions())) {
            basicInfo.setExpertIntentionWorkRegions(applyIntentionWorkRegions);
        }
        ExpertFullInfoVO resExpertFullInfo = new ExpertFullInfoVO();
        resExpertFullInfo.setUserId(expertUserInfo.getUserId());
        resExpertFullInfo.setBasicInfo(basicInfo);
        resExpertFullInfo.setEduInfo(eduInfo);
        resExpertFullInfo.setJobInfo(jobInfo);
        resExpertFullInfo.setProfessionalInfo(profession);
        resExpertFullInfo.setRecommendInfo(recommendInfo);
        resExpertFullInfo.setExpertOtherInfo(otherInfo);
        resExpertFullInfo.setExpertApplyIntentionWorkRegions(applyIntentionWorkRegions);
        return resExpertFullInfo;
    }

    public static Map<Long, FileBasicInfo> buildFileBasicInfoMap(List<AttachFileVo> attachFiles) {
        return attachFiles.stream().map(r -> {
            FileBasicInfo fileBasicInfo = new FileBasicInfo();
            fileBasicInfo.setFileId(r.getFileId());
            fileBasicInfo.setFileName(r.getOriginalFileName());
            return fileBasicInfo;
        }).collect(Collectors.toMap(FileBasicInfo::getFileId, Function.identity()));
    }

    public Map<String, List<TagFieldInfo>> buildTagFieldInfoMap(List<ExpertTagDTO> expertTagList) {
        return expertTagList.stream().map(r -> {
            TagFieldInfo tagFieldInfo = new TagFieldInfo();
            tagFieldInfo.setTagCode(r.getTagCode());
            tagFieldInfo.setTagFieldName(r.getExpertInfoField());
            TagDTO tagDTO = tagCache.getByTagCode(r.getTagCode());
            if (Objects.nonNull(tagDTO)) {
                tagFieldInfo.setTagName(tagDTO.getTagName());
            }
            return tagFieldInfo;
        }).collect(Collectors.groupingBy(TagFieldInfo::getTagFieldName));
    }

    public Map<String, List<DictFieldInfoDTO>> buildDictInfoMap(List<ExpertDictionaryDTO> expertDictList) {
        return expertDictList.stream().map(r -> {
            DictFieldInfoDTO dictionaryFieldInfo = new DictFieldInfoDTO();
            dictionaryFieldInfo.setDictionaryFieldName(r.getExpertInfoField());
            dictionaryFieldInfo.setDictionaryCode(r.getDictionaryCode());
            Optional<DictionaryDTO> dictionaryDTO = dictionaryCache.getByCode(r.getDictionaryCode());
            dictionaryDTO.ifPresent(dictDTO -> dictionaryFieldInfo.setDictionaryName(dictDTO.getName()));
            return dictionaryFieldInfo;
        }).collect(Collectors.groupingBy(DictFieldInfoDTO::getDictionaryFieldName));
    }

    public static ExpertProfessionalInfo buildExpertProfessionalInfo(ExpertUserFullInfoDTO expertUserInfoDTO,
                                                                     Map<String, List<DictFieldInfoDTO>> dictInfoMap,
                                                                     Map<String, List<TagFieldInfo>> tagFieldInfoMap,
                                                                     Map<Long, FileBasicInfo> fileInfoMap,
                                                                     List<ExpertAvoidCompanyDTO> expertAvoidCompanyList) {
        ExpertProfessionalInfo professionalInfo = new ExpertProfessionalInfo();
        professionalInfo.setTechnicalTitles(expertUserInfoDTO.getTechnicalTitles());
        professionalInfo.setTitleLevel(dictInfoMap.get(ExpertDictTypeEnum.TITLE_LEVEL.getKey()));
        professionalInfo.setTitleCertificateFile(getFileBasicInfoList(fileInfoMap, expertUserInfoDTO.getTitleCertificateFileIdList()));
        professionalInfo.setGoodAt(tagFieldInfoMap.get(ExpertTagEnum.GOOD_AT.getKey()));
        professionalInfo.setTechnicalExpertise(tagFieldInfoMap.get(ExpertTagEnum.TECHNICAL_EXPERTISE.getKey()));
        professionalInfo.setIndustrySector(tagFieldInfoMap.get(ExpertTagEnum.INDUSTRY_SECTOR.getKey()));
        professionalInfo.setAvoidCompanyList(expertAvoidCompanyList.stream().map(r -> {
            ExpertAvoidCompanyInfo avoidCompanyInfo = new ExpertAvoidCompanyInfo();
            avoidCompanyInfo.setCompanyName(r.getCompanyName());
            avoidCompanyInfo.setCompanyUniqCode(r.getCompanyUniqCode());
            return avoidCompanyInfo;
        }).collect(Collectors.toList()));
        return professionalInfo;
    }

    public static ExpertJobInfo buildExpertJobInfo(ExpertUserFullInfoDTO expertUserInfoDTO,
                                                   Map<String, List<DictFieldInfoDTO>> dictInfoMap) {
        ExpertJobInfo jobInfo = new ExpertJobInfo();
        jobInfo.setJobStatus(dictInfoMap.get(ExpertDictTypeEnum.JOB_STATUS.getKey()));
        jobInfo.setCompany(expertUserInfoDTO.getCompany());
        jobInfo.setCompanyUniqCode(expertUserInfoDTO.getCompanyUniqCode());
        jobInfo.setAdministrativeDuties(expertUserInfoDTO.getAdministrativeDuties());
        jobInfo.setStartWorkAt(expertUserInfoDTO.getStartWorkAt());
        jobInfo.setAdministrativeRank(dictInfoMap.get(ExpertDictTypeEnum.ADMINISTRATIVE_RANK.getKey()));
        jobInfo.setCompanyAttribute(dictInfoMap.get(ExpertDictTypeEnum.COMPANY_ATTRIBUTE.getKey()));
        jobInfo.setAddress(expertUserInfoDTO.getAddress());
        jobInfo.setExperience(expertUserInfoDTO.getExperience());
        return jobInfo;
    }

    public static ExpertEduInfo buildExpertEduInfo(ExpertUserFullInfoDTO expertFullInfo,
                                                   Map<String, List<DictFieldInfoDTO>> dictInfoMap) {
        // 学历信息
        ExpertEduInfo eduInfo = new ExpertEduInfo();
        eduInfo.setSchool(expertFullInfo.getSchoolMajor());
        eduInfo.setGraduatedAt(expertFullInfo.getGraduatedAt());
        eduInfo.setAcademicTitle(expertFullInfo.getAcademicTitle());
        eduInfo.setEdu(dictInfoMap.get(ExpertDictTypeEnum.EDU.getKey()));
        eduInfo.setGraduationCertFile(expertFullInfo.getGraduationCertFile());
        eduInfo.setDegree(dictInfoMap.get(ExpertDictTypeEnum.DEGREE.getKey()));
        eduInfo.setDegreeCertFile(expertFullInfo.getDegreeCertFile());
        return eduInfo;
    }

    private static List<FileBasicInfo> getFileBasicInfoList(Map<Long, FileBasicInfo> fileBasicInfoMap, List<Long> fileIdList) {
        if (CollUtil.isEmpty(fileIdList)) {
            return new ArrayList<>();
        }
        List<FileBasicInfo> fileBasicInfoList = new ArrayList<>();
        for (Long fileId : fileIdList) {
            FileBasicInfo fileBasicInfo = fileBasicInfoMap.get(fileId);
            if (Objects.nonNull(fileBasicInfo)) {
                fileBasicInfoList.add(fileBasicInfo);
            }
        }
        return fileBasicInfoList;
    }

    public ExpertBasicInfo convert(ExpertUserFullInfoDTO expertUserInfoDTO
            , Map<String, List<DictFieldInfoDTO>> dictionaryFieldInfoMap
            , Map<String, List<TagFieldInfo>> tagFieldInfoMap
            , List<ExpertRegionDTO> expertIntentionWorkRegionInfo) {
        //专家层级
        ExpertRegionInfo expertRegionInfo = new ExpertRegionInfo();
        expertRegionInfo.setRegionLevel(expertUserInfoDTO.getRegionLevel());
        expertRegionInfo.setRegionCode(expertUserInfoDTO.getRegionCode());

        // 基本信息
        ExpertBasicInfo basicInfo = new ExpertBasicInfo();
        basicInfo.setIsDingUser(expertUserInfoDTO.getIsDingUser());
        basicInfo.setPhoneNo(expertUserInfoDTO.getPhoneNo());
        basicInfo.setName(expertUserInfoDTO.getName());
        basicInfo.setAvatarFile(expertUserInfoDTO.getAvatarFile());
        basicInfo.setGender(expertUserInfoDTO.getGender());
        basicInfo.setPolitical(dictionaryFieldInfoMap.get(ExpertDictTypeEnum.POLITICAL.getKey()));
        basicInfo.setIdCard(expertUserInfoDTO.getIdCard());
        basicInfo.setOfficePhone(expertUserInfoDTO.getPhoneNo());
        basicInfo.setBirthday(expertUserInfoDTO.getBirthday());
        basicInfo.setBank(expertUserInfoDTO.getBank());
        basicInfo.setBankNo(expertUserInfoDTO.getBankNo());
        basicInfo.setEmail(expertUserInfoDTO.getEmail());
        basicInfo.setHometown(expertUserInfoDTO.getHometown());
        basicInfo.setNationality(expertUserInfoDTO.getNationality());
        basicInfo.setExpertSource(tagFieldInfoMap.get(ExpertTagEnum.EXPERT_SOURCE.getKey()));
        expertRegionInfo.setRegionName(regionCacheHelper.getUnionPath(expertRegionInfo.getRegionCode(), expertRegionInfo.getRegionLevel()));
        basicInfo.setExpertRegionInfo(expertRegionInfo);

        basicInfo.setExpertIntentionWorkRegions(expertIntentionWorkRegionInfo.stream().map(r -> {
            ExpertRegionInfo expertIntentionWorkRegion = new ExpertRegionInfo();
            expertIntentionWorkRegion.setRegionCode(r.getRegionCode());
            expertIntentionWorkRegion.setRegionLevel(r.getRegionLevel());
            expertIntentionWorkRegion.setRegionName(regionCacheHelper.getUnionPath(r.getRegionCode(), r.getRegionLevel()));
            return expertIntentionWorkRegion;
        }).collect(Collectors.toList()));
        basicInfo.setExpertType(dictionaryFieldInfoMap.get(ExpertDictTypeEnum.EXPERT_TYPE.getKey()));
        return basicInfo;
    }

    public static ExpertFullInfoAllDTO convert(ExpertUserFullInfo expertUserFullInfo,
                                               List<ExpertTag> expertTagList,
                                               List<ExpertDictionary> expertDictionaryList,
                                               List<ExpertIntentionWorkRegion> intentionWorkRegionList,
                                               List<ExpertMetaApply> expertMetaApplyList,
                                               List<ExpertAvoidCompany> expertAvoidCompanyList,
                                               List<ExpertGovBusinessStrip> businessStrips) {
        ExpertUserFullInfoDTO expertFullInfoDto = convert(expertUserFullInfo);
        List<ExpertDictionaryDTO> expertDicts = buildExpertDictionaryDTOList(expertDictionaryList);
        List<ExpertTagDTO> expertTags = buildExpertTagDTOList(expertTagList);
        List<ExpertRegionDTO> intentionWorkRegions = buildExpertIntentionWorkRegionInfo(intentionWorkRegionList);

        // 专家申请履职意向展示列表
        List<ExpertRegionDTO> applyIntentionWorkRegions = buildExpertApplyIntentionWorkRegionInfo(intentionWorkRegionList, expertMetaApplyList);
        List<ExpertAvoidCompanyDTO> expertAvoidCompanyDTOList = buildExpertAvoidCompanyDTOList(expertAvoidCompanyList);
        ExpertFullInfoAllDTO expertFullInfoAll = new ExpertFullInfoAllDTO();
        expertFullInfoAll.setUserId(expertUserFullInfo.getUserId());
        expertFullInfoAll.setExpertUserInfoDTO(expertFullInfoDto);
        expertFullInfoAll.setExpertDictionaryList(expertDicts);
        expertFullInfoAll.setExpertTagList(expertTags);
        expertFullInfoAll.setExpertIntentionWorkRegionInfo(intentionWorkRegions);
        expertFullInfoAll.setExpertApplyIntentionWorkRegionInfo(applyIntentionWorkRegions);
        expertFullInfoAll.setExpertAvoidCompanyList(expertAvoidCompanyDTOList);
        expertFullInfoAll.setBusinessStrips(BeanUtil.copyToList(businessStrips, GovBusinessStripVO.class));
        return expertFullInfoAll;
    }

    private static List<ExpertRegionDTO> buildExpertApplyIntentionWorkRegionInfo(List<ExpertIntentionWorkRegion> expertIntentionWorkRegionList,
                                                                                 List<ExpertMetaApply> expertMetaApplyList) {
        Set<RegionDtoMapKey> set = new HashSet<>();
        for (ExpertIntentionWorkRegion expertIntentionWorkRegion : expertIntentionWorkRegionList) {
            RegionDtoMapKey regionDtoMapKey = new RegionDtoMapKey();
            regionDtoMapKey.setRegionCode(expertIntentionWorkRegion.getRegionCode());
            regionDtoMapKey.setRegionLevel(expertIntentionWorkRegion.getRegionLevel());
            set.add(regionDtoMapKey);
        }

        for (ExpertMetaApply expertMetaApply : expertMetaApplyList) {
            String regionCode = expertMetaApply.getRegionCode();
            Integer regionLevel = expertMetaApply.getRegionLevel();
            if (Objects.nonNull(regionLevel) && StringUtils.isNotBlank(regionCode)) {
                String applyType = expertMetaApply.getApplyType();
                RegionDtoMapKey regionDtoMapKey = new RegionDtoMapKey();
                regionDtoMapKey.setRegionCode(regionCode);
                regionDtoMapKey.setRegionLevel(regionLevel);
                ExpertApplyTypeEnum typeEnum = ExpertApplyTypeEnum.of(applyType);
                switch (typeEnum) {
                    case EXPERT_INTENTION_LEAVE: {
                        set.remove(regionDtoMapKey);
                    }
                    break;
                    case EXPERT_INTENTION_JOIN: {
                        set.add(regionDtoMapKey);
                    }
                    break;
                    default:
                        break;
                }
            }
        }
        return set.stream().map(r -> {
            ExpertRegionDTO expertRegionDTO = new ExpertRegionDTO();
            expertRegionDTO.setRegionCode(r.getRegionCode());
            expertRegionDTO.setRegionLevel(r.getRegionLevel());
            return expertRegionDTO;
        }).collect(Collectors.toList());
    }

    private static List<ExpertAvoidCompanyDTO> buildExpertAvoidCompanyDTOList(List<ExpertAvoidCompany> expertAvoidCompanyList) {
        return expertAvoidCompanyList.stream().map(r -> {
            ExpertAvoidCompanyDTO expertAvoidCompanyDTO = new ExpertAvoidCompanyDTO();
            expertAvoidCompanyDTO.setCompanyUniqCode(r.getCompanyUniqCode());
            expertAvoidCompanyDTO.setCompanyName(r.getCompanyName());
            return expertAvoidCompanyDTO;
        }).collect(Collectors.toList());
    }

    private static List<ExpertRegionDTO> buildExpertIntentionWorkRegionInfo(List<ExpertIntentionWorkRegion> expertIntentionWorkRegionList) {
        return expertIntentionWorkRegionList.stream().map(r -> {
            ExpertRegionDTO expertRegionDTO = new ExpertRegionDTO();
            expertRegionDTO.setRegionLevel(r.getRegionLevel());
            expertRegionDTO.setRegionCode(r.getRegionCode());
            return expertRegionDTO;
        }).collect(Collectors.toList());
    }

    private static List<ExpertTagDTO> buildExpertTagDTOList(List<ExpertTag> expertTagList) {
        return expertTagList.stream().map(r -> {
            ExpertTagDTO expertTagDTO = new ExpertTagDTO();
            expertTagDTO.setExpertInfoField(r.getExpertInfoField());
            expertTagDTO.setTagCode(r.getTagCode());
            return expertTagDTO;
        }).collect(Collectors.toList());
    }

    private static List<ExpertDictionaryDTO> buildExpertDictionaryDTOList(List<ExpertDictionary> expertDictionaryList) {
        return expertDictionaryList.stream().map(r -> {
            ExpertDictionaryDTO expertDictionaryDTO = new ExpertDictionaryDTO();
            expertDictionaryDTO.setExpertInfoField(r.getExpertInfoField());
            expertDictionaryDTO.setDictionaryCode(r.getDictionaryCode());
            return expertDictionaryDTO;
        }).collect(Collectors.toList());
    }

    public static ExpertUserFullInfoDTO convert(ExpertUserFullInfo expertFullInfo) {
        ExpertUserFullInfoDTO expert = new ExpertUserFullInfoDTO();
        expert.setIsDingUser(expertFullInfo.getIsDingUser());
        expert.setPhoneNo(expertFullInfo.getPhoneNo());
        expert.setGender(expertFullInfo.getGender());
        expert.setName(expertFullInfo.getExpertName());
        expert.setAvatarFile(expertFullInfo.getAvatarFile());
        expert.setIdCard(expertFullInfo.getIdCard());
        expert.setOfficePhone(expertFullInfo.getOfficePhone());
        expert.setBirthday(expertFullInfo.getBirthday());
        expert.setBankNo(expertFullInfo.getBankNo());
        expert.setBank(expertFullInfo.getBank());
        expert.setEmail(expertFullInfo.getEmail());
        expert.setHometown(expertFullInfo.getHometown());
        expert.setNationality(expertFullInfo.getNationality());
        expert.setSchoolMajor(expertFullInfo.getSchoolMajor());
        expert.setGraduatedAt(expertFullInfo.getGraduatedAt());
        expert.setAcademicTitle(expertFullInfo.getAcademicTitle());
        expert.setGraduationCertFile(expertFullInfo.getGraduationCertFile());
        expert.setDegreeCertFile(expertFullInfo.getDegreeCertFile());
        expert.setCompany(expertFullInfo.getCompany());
        expert.setCompanyUniqCode(expertFullInfo.getCompanyUniqCode());
        expert.setStartWorkAt(expertFullInfo.getStartWorkAt());
        expert.setAddress(expertFullInfo.getAddress());
        expert.setExperience(expertFullInfo.getExperience());
        expert.setAcademicTitle(expertFullInfo.getAcademicTitle());
        expert.setRecommendFile(expertFullInfo.getRecommendFile());
        return expert;
    }

    public static ExpertAdminExpertListDTO convert(ExpertUserFullInfo eui,
                                                   Map<Long, List<ExpertDictionary>> expertDictMap) {
        ExpertAdminExpertListDTO item = new ExpertAdminExpertListDTO();
        item.setUserId(eui.getUserId());
        item.setExpertName(eui.getExpertName());
        item.setPhoneNo(eui.getPhoneNo());
        item.setCompany(eui.getCompany());
        Long userId = eui.getUserId();
        // 装配字典数据
        List<ExpertDictionary> currUserDicts = expertDictMap.get(userId);
        if (CollUtil.isNotEmpty(currUserDicts)) {
            Map<String, List<ExpertDictionary>> currDictMap = CollUtils.group(currUserDicts, ExpertDictionary::getExpertInfoField);
            item.setExpertType(DictAssembler.convert(currDictMap.get(ExpertDictTypeEnum.EXPERT_TYPE.getKey())));
            item.setExpertSpecialty(DictAssembler.convert(currDictMap.get(ExpertDictTypeEnum.EXPERT_SPECIALTY.getKey())));
            item.setExpertSource(DictAssembler.convert(currDictMap.get(ExpertDictTypeEnum.EXPERT_SOURCE.getKey())));
            item.setExpertLibrary(DictAssembler.convert(currDictMap.get(ExpertDictTypeEnum.EXPERT_LIBRARY.getKey())));
        }
        // 以下数据为专家excel导出使用
        item.setGender(eui.getGender());
        item.setInPutTime(eui.getInPutTime());
        item.setCreateTime(eui.getCreateOn());
        return item;
    }


}
