package com.microservices.dms.achievementLibrary.service.impl;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.domain.R;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.poi.ExcelUtil;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.dms.achievementLibrary.domain.*;
import com.microservices.dms.behaviorImage.domain.AchievementBehaviorSumVo;
import com.microservices.dms.behaviorImage.domain.AchievementImageVo;
import com.microservices.dms.achievementLibrary.domain.AchievementSourceStatisticVo;
import com.microservices.dms.behaviorImage.service.IBehaviorImageService;
import com.microservices.dms.common.vo.AchievementSysFileVo;
import com.microservices.dms.common.vo.NameCountVo;
import com.microservices.dms.resourceLibrary.domain.*;
import com.microservices.dms.resourceLibrary.domain.vo.KeyValVo;
import com.microservices.dms.resourceLibrary.mapper.ExpertResourceLibraryMapper;
import com.microservices.dms.resourceLibrary.mapper.TaskResourceLibraryMapper;
import com.microservices.dms.utils.CustomMultipartFile;
import com.microservices.dms.utils.DateUtil;
import com.microservices.dms.utils.FileMultipartFile;
import com.microservices.system.api.RemoteDictDataService;
import com.microservices.system.api.RemoteFileService;
import com.microservices.system.api.domain.SysDictData;
import com.microservices.system.api.domain.SysFile;
import com.microservices.system.api.domain.SysFileInfo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.microservices.dms.achievementLibrary.mapper.AchievementsMapper;
import com.microservices.dms.achievementLibrary.service.IAchievementsService;
import org.springframework.web.multipart.MultipartFile;

import javax.activation.FileTypeMap;

import static com.microservices.dms.utils.UrlUtil.getUrlPath;

/**
 * 成果Service业务层处理
 *
 * @author microservices
 * @date 2025-04-02
 */
@Service
@Slf4j
public class AchievementsServiceImpl implements IAchievementsService {

    private static final Logger logger = LoggerFactory.getLogger(AchievementsServiceImpl.class);

    @Autowired
    private AchievementsMapper achievementsMapper;

    @Autowired
    private TaskResourceLibraryMapper taskResourceLibraryMapper;

    @Autowired
    private ExpertResourceLibraryMapper expertResourceLibraryMapper;


    @Autowired
    private IBehaviorImageService behaviorImageService;

    @Autowired
    private RemoteFileService remoteFileService;

    @Autowired
    private RemoteDictDataService remoteDictDataService;

    @Value("${makerSpaceUrl}")
    public String makerSpaceUrl;

    @Value("${http.gitLinkUrl}")
    public String gitLinkUrl;

    @Value("${http.gatewayUrl}")
    public String gatewayUrl;

    /**
     * 查询成果
     *
     * @param id 成果主键
     * @return 成果
     */
    @Override
    public Achievements selectAchievementsById(Long id, Boolean isOpenView) {
        Achievements a = achievementsMapper.selectAchievementsById(id);
        if (StringUtils.isNotNull(a)) {
            String gender = a.getGender();
            String img = "";
            if (StringUtils.isNotEmpty(gender) && gender.equals("1")) {
                img = "images/avatars/User/girl.jpg";
            } else if (StringUtils.isNotEmpty(gender) && gender.equals("0")) {
                img = "images/avatars/User/boy.jpg";
            }
            a.setUserImg(img);
            if (StringUtils.isNotEmpty(a.getField1()) && !a.getSource().equals("5")) {
                String field1Name = achievementsMapper.getField1NameByParam(a.getSource(), a.getId());
                if (StringUtils.isNotNull(field1Name)) {
                    a.setField1Name(field1Name);
                }
            }
            a.setUserImg(img);
            a.setImages( a.getImages() == null ? null : a.getImages().replace("/api/file/common/downloadByIdentifier/", "/api/file/open/downloadByIdentifier/"));
            if (isOpenView){
                a.setAttachments(buildFileInfoByIdents(a.getAttachments(), a.getSource()));
            }
            //拼接对接的用户信息
            List<Map<String,Object>> dockingUserInfo =  achievementsMapper.getDockingUserInfoList(a.getId());
            a.setDockingUserInfo(dockingUserInfo);
        }
        return a;
    }

    /**
     * 查询成果列表
     *
     * @param achQueryVo 成果
     * @return 成果
     */
    @Override
    public List<Achievements> selectAchievementsList(AchQueryVo achQueryVo) {
        return getAllResult(achQueryVo);
    }


    @Override
    public List<Achievements> selectAchievementsFrontList(Achievements achievements) {
        List<Achievements> list = achievementsMapper.selectAchievementsList(achievements);
        for (Achievements a : list) {
            a.setDetails(null);
            a.setImages(buildFileInfoByIdents(a.getImages(), a.getSource()));
            a.setAttachments(buildFileInfoByIdents(a.getAttachments(), a.getSource()));
        }
        return list;
    }

    /**
     * 新增成果
     *
     * @param achievements 成果
     * @return 结果
     */
    @Override
    public int insertAchievements(Achievements achievements) {
        achievements.setCreateTime(DateUtils.getNowDate());
        achievements.setCreateBy(SecurityUtils.getUsername());
        return achievementsMapper.insertAchievements(achievements);
    }

    /**
     * 修改成果
     *
     * @param achievements 成果
     * @return 结果
     */
    @Override
    public int updateAchievements(Achievements achievements) {
        achievements.setUpdateTime(DateUtils.getNowDate());
        achievements.setUpdateBy(SecurityUtils.getUsername());
        return achievementsMapper.updateAchievements(achievements);
    }

    /**
     * 批量删除成果
     *
     * @param ids 需要删除的成果主键
     * @return 结果
     */
    @Override
    public int deleteAchievementsByIds(Long[] ids) {
        return achievementsMapper.deleteAchievementsByIds(ids);
    }

    /**
     * 删除成果信息
     *
     * @param id 成果主键
     * @return 结果
     */
    @Override
    public int deleteAchievementsById(Long id) {
        //根据id，获取数据仓库该数据信息
        Achievements achievements = achievementsMapper.selectAchievementsById(id);
        if(achievements != null){
            String source = achievements.getSource();
            if(StringUtils.isNotEmpty(source) && !source.equals("5")) {
                achievementsMapper.updateRelationAchievements(source,achievements.getSourceId());
            }
        }
        return achievementsMapper.deleteAchievementsById(id);
    }

    @Override
    public String buildFileInfoByIdents(String aStr, String source) {
        if (StringUtils.isEmpty(aStr) || StringUtils.isEmpty(source)) {
            return aStr;
        }

        List<Map<String, String>> list = JSON.parseObject(aStr, new TypeReference<List<Map<String, String>>>() {
        });
        List<Map<String, String>> filterList = list.stream()
                .filter(item -> !item.getOrDefault("name","").contains("入驻承诺书"))
                .collect(Collectors.toList());
        return JSON.toJSONString(filterList);
    }

    private void concatUrl(List<Map<String, String>> list, String url) {
        for (Map<String, String> map : list) {
            String v = map.getOrDefault("v", "");
            String urlPath = getUrlPath(v);
            map.put("v", url + urlPath);
        }
    }


    @Override
    public List<Achievements> getChoiceImport() {
        return achievementsMapper.getChoiceImport();
    }

    @Override
    public List<KeyValueVo> getTjBySources() {
        return achievementsMapper.getTjBySources();
    }

    @Override
    public List<KeyValueVo> getTjByAreas() {
        return achievementsMapper.getTjByAreas();
    }

    @Override
    public List<Achievements> getAllResult(AchQueryVo achQueryVo) {
        //根据查询条件获取所有的成果数据
        logger.info("getAllResult USERID======={},user={}", SecurityUtils.getGitlinkUserId(),SecurityUtils.getUsername());
        if (achQueryVo.getUserSelf() && SecurityUtils.getGitlinkUserId() != null) {
            achQueryVo.setUserId(SecurityUtils.getGitlinkUserId().toString());
            achQueryVo.setAllStatus(true);
        }
        List<Achievements> list = achievementsMapper.selectAchievementsByParamNew(achQueryVo);
        //遍历成果数据，获取对应成果的点击数
        for (Achievements a : list) {
            String gender = a.getGender();
            String img = "images/avatars/User/boy.jpg";
            if (StringUtils.isNotEmpty(gender) && gender.equals("1")) {
                img = "images/avatars/User/girl.jpg";
            } else if (StringUtils.isNotEmpty(gender) && gender.equals("0")) {
                img = "images/avatars/User/boy.jpg";
            }
            a.setUserImg(img);
            Long clickSum = achievementsMapper.getAchievementClickSum(a.getId());
            a.setClickSum(clickSum);
            a.setImages( a.getImages() == null ? null : a.getImages().replace("/api/file/common/downloadByIdentifier/", "/api/file/open/downloadByIdentifier/"));
            //拼接对接的用户信息
            List<Map<String,Object>> dockingUserInfo =  achievementsMapper.getDockingUserInfoList(a.getId());
            a.setDockingUserInfo(dockingUserInfo);
        }
        return list;
    }

    @Override
    public Map<String, Object> getUerActionData() {
        Date[] days = DateUtil.getDays(0, 6);
        Map<String, Long> w = achievementsMapper.getaWatcher(days[0], days[1], "Achievements")
                .stream().collect(Collectors.toMap(KeyValVo::getK, KeyValVo::getV));

        Map<String, Long> g = achievementsMapper.getFavorite(days[0], days[1], "Achievements")
                .stream().collect(Collectors.toMap(KeyValVo::getK, KeyValVo::getV));

        List<String> dateStr = DateUtil.getDateStrMMDD(days[0], days[1]);
        List<KeyValVo<String, Long>> wRes = new ArrayList<>();
        List<KeyValVo<String, Long>> gRes = new ArrayList<>();
        for (String s : dateStr) {
            Long a = w.getOrDefault(s, 0L);
            Long b = g.getOrDefault(s, 0L);
            KeyValVo<String, Long> k1 = new KeyValVo<>();
            k1.setK(s);
            k1.setV(a);
            KeyValVo<String, Long> k2 = new KeyValVo<>();
            k2.setK(s);
            k2.setV(b);

            wRes.add(k1);
            gRes.add(k2);
        }
        Map<String, Object> res = new HashMap<>();
        res.put("watcher", wRes);
        res.put("favorite", gRes);
        return res;
    }

    @Override
    public List<HotAchVo> getHotAchievement() {
        //根据查询条件获取所有的成果数据
        List<HotAchVo> resultList = achievementsMapper.getHotAchievement();
        //遍历成果数据，获取对应成果的点击数
        for (HotAchVo a : resultList) {
            String gender = a.getGender();
            String img = "";
            if (StringUtils.isNotEmpty(gender) && gender.equals("1")) {
                img = "images/avatars/User/girl.jpg";
            } else if (StringUtils.isNotEmpty(gender) && gender.equals("0")) {
                img = "images/avatars/User/boy.jpg";
            }
            a.setUserImg(img);
        }
        return resultList;
    }

    @Override
    public List<KeyValVo<String, Long>> get7DayAdd(AchQueryVo achQueryVo) {
        Date[] days = DateUtil.getDays(0, 6);
        Map<String, Long> w = achievementsMapper.getAchievement(days[0], days[1], achQueryVo.getSource())
                .stream().collect(Collectors.toMap(KeyValVo::getK, KeyValVo::getV));

        List<String> dateStr = DateUtil.getDateStrMMDD(days[0], days[1]);
        List<KeyValVo<String, Long>> res = new ArrayList<>();

        for (String s : dateStr) {
            Long a = w.getOrDefault(s, 0L);
            KeyValVo<String, Long> k1 = new KeyValVo<>();
            k1.setK(s);
            k1.setV(a);
            res.add(k1);
        }
        return res;
    }

    @Override
    public List<KeyValVo<String, Long>> get7DayAddExport(AchQueryVo achQueryVo) {
        Date[] days = DateUtil.getDays(0, 6);
        Map<String, Long> w = achievementsMapper.getExperts(days[0], days[1])
                .stream().collect(Collectors.toMap(KeyValVo::getK, KeyValVo::getV));

        List<String> dateStr = DateUtil.getDateStrMMDD(days[0], days[1]);
        List<KeyValVo<String, Long>> res = new ArrayList<>();

        for (String s : dateStr) {
            Long a = w.getOrDefault(s, 0L);
            KeyValVo<String, Long> k1 = new KeyValVo<>();
            k1.setK(s);
            k1.setV(a);
            res.add(k1);
        }
        return res;
    }
    @Override
    public Map<String, Long> indexProjectStatistic() {
        Map<String, Long> res = achievementsMapper.indexProjectStatistic();
        return res;
    }

    @Override
    public Map<String, Object> indexTaskStatistic() {
        Map<String, Object> res = achievementsMapper.indexTaskStatistic();
        double convertedTaskAmount = taskResourceLibraryMapper.getConvertedTaskAmount2();
        res.put("convertedTaskAmount", convertedTaskAmount);
        return res;
    }

    @Override
    public Map<String, Long> indexCompetitionStatistic() {
        Map<String, Long> res = achievementsMapper.indexCompetitionStatistic();
        return res;
    }

    @Override
    public Map<String, Long> indexSchoolEnterpriseStatistic() {
        Map<String, Long> res = new HashMap<>();
        Long schoolEnterpriseCount = achievementsMapper.indexSchoolEnterpriseStatistic("4", "");
        res.put("schoolEnterpriseCount", schoolEnterpriseCount);
        Long schoolCount = achievementsMapper.indexSchoolEnterpriseStatistic("4", "1");
        res.put("schoolCount", schoolCount);
        Long enterpriseCount = achievementsMapper.indexSchoolEnterpriseStatistic("4", "2");
        res.put("enterpriseCount", enterpriseCount);
        Clicker clicker = new Clicker();
        clicker.setClickType("Achievements");
        long clickCount = taskResourceLibraryMapper.countClicker(clicker);
        res.put("clickCount", clickCount);
        return res;
    }

    /**
     * 首页专家数据统计
     * @return
     */
    @Override
    public Map<String, Long> indexExpertStatistic() {
        Map<String, Long> res = new HashMap<>();
        Long expertResourceCount = expertResourceLibraryMapper.expertResourceCount();
        res.put("expertResourceCount", expertResourceCount);
        Long auditTaskAuditExpertCount = expertResourceLibraryMapper.auditTaskAuditExpertCount();
        res.put("auditTaskAuditExpertCount", auditTaskAuditExpertCount);
        Long auditCompetitionAuditExpertCount = expertResourceLibraryMapper.auditCompetitionAuditExpertCount();
        res.put("auditCompetitionAuditExpertCount", auditCompetitionAuditExpertCount);
        Clicker clicker = new Clicker();
        clicker.setClickType("Experts");
        long clickCount = taskResourceLibraryMapper.countClickerSimple(clicker);
        res.put("clickCount", clickCount);
        return res;
    }

    @Override
    public List<KeyValueVo> getAreasByName(String areaName) {
        return achievementsMapper.getAreasByName(areaName);
    }

    @Override
    public AchievementBehaviorSumVo getActDataStatisticById(Long id) {
        return achievementsMapper.getActDataStatisticById(id);
    }

    @Override
    public List<KeyValVo<String, Long>> get7AddClickById(String id, String clickType) {

        if (StringUtils.isEmpty(clickType)) {
            clickType = "Achievements";
        }
        Date[] days = DateUtil.getDays(0, 6);
        Map<String, Long> w = achievementsMapper.get7AddClickById(days[0], days[1], clickType, id)
                .stream().collect(Collectors.toMap(KeyValVo::getK, KeyValVo::getV));

        List<String> dateStr = DateUtil.getDateStrMMDD(days[0], days[1]);
        List<KeyValVo<String, Long>> res = new ArrayList<>();

        for (String s : dateStr) {
            Long a = w.getOrDefault(s, 0L);
            KeyValVo<String, Long> k1 = new KeyValVo<>();
            k1.setK(s);
            k1.setV(a);
            res.add(k1);
        }
        return res;
    }

    @Override
    public AchievementBehaviorSumVo getWatchFavoriteStatusById(Long id, Long userId) {
        return achievementsMapper.getWatchFavoriteStatusById(id, userId);
    }


    @Scheduled(cron = "${cron.calculateHotRank}")
    public void timingCalcHotRank() {
        List<Long> ids = achievementsMapper.getAllId();
        for (Long id : ids) {
            AchievementImageVo image = behaviorImageService.getAchievementImageById(id);
            float score = image.getScore();
            Achievements u = new Achievements();
            u.setId(id);
            u.setHotRank(score);
            achievementsMapper.updateAchievements(u);
        }
    }

    @Override
    public List<AreaStatisticVo> getAreaStatistic(String areaKey) {
        List<AreaStatisticVo> areaStatisticVoList = new ArrayList<>();
        if(StringUtils.isNotEmpty(areaKey)) {
            //根据逗号进行分割
            String[] res =areaKey.split(",");
            for (String s : res) {
                String[] ss = s.split("_");
                List<AreaStatisticVo>  tmpList = achievementsMapper.getAreaStatistic(ss[1],ss[0]);
                areaStatisticVoList.addAll(tmpList);
            }
            return areaStatisticVoList;
        }else{
            return achievementsMapper.getAreaStatistic(null,areaKey);
        }
    }

    @Override
    public List<AchRelatedResult> getRelatedAch(Long id, Long sourceId) {
        List<AchRelatedResult> relatedResultList = new ArrayList<>();
        //想根据开源项目id，获取对应的年度信息
        List<Long> allSourceId = achievementsMapper.getAllSourceId(id, sourceId);
        if(allSourceId != null && allSourceId.size() > 0) {
            List<String> allYear = achievementsMapper.getDistinctYear(id, allSourceId);
            if (StringUtils.isNotNull(allYear)) {
                //遍历年度信息，获取年度成果数据
                for (String paramYear : allYear) {
                    AchRelatedResult relatedResult = new AchRelatedResult();
                    relatedResult.setYear(paramYear);
                    List<AchRelatedVo> tmpList = achievementsMapper.getRelatedAch(id, allSourceId, paramYear);
                    relatedResult.setAchRelatedVoList(tmpList);
                    relatedResultList.add(relatedResult);
                }
            }
        }
        return relatedResultList;
    }

    @Override
    public List<AchRelatedResult> getRelatedAchCompetition(Long id, Long sourceId) {
        List<AchRelatedResult> relatedResultList = new ArrayList<>();
        if (sourceId !=null){
            //想根据开源项目id，获取对应的年度信息
            List<Long> allSourceId = achievementsMapper.getAllSourceIdCompetition(id, sourceId);
            List<String> allYear = achievementsMapper.getDistinctYear(id, allSourceId);
            if (StringUtils.isNotNull(allYear)) {
                //遍历年度信息，获取年度成果数据
                for (String paramYear : allYear) {
                    AchRelatedResult relatedResult = new AchRelatedResult();
                    relatedResult.setYear(paramYear);
                    List<AchRelatedVo> tmpList = achievementsMapper.getRelatedAch(id, allSourceId, paramYear);
                    relatedResult.setAchRelatedVoList(tmpList);
                    relatedResultList.add(relatedResult);
                }
            }
        }
        return relatedResultList;
    }

    @Override
    public List<AchRelatedResult> getRelatedAchTask(Long id, Long sourceId) {
        List<AchRelatedResult> relatedResultList = new ArrayList<>();
        if (sourceId !=null){
            //想根据开源项目id，获取对应的年度信息
            List<Long> allSourceId = achievementsMapper.getAllSourceIdTask(id, sourceId);
            List<String> allYear = achievementsMapper.getDistinctYear(id, allSourceId);
            if (StringUtils.isNotNull(allYear)) {
                //遍历年度信息，获取年度成果数据
                for (String paramYear : allYear) {
                    AchRelatedResult relatedResult = new AchRelatedResult();
                    relatedResult.setYear(paramYear);
                    List<AchRelatedVo> tmpList = achievementsMapper.getRelatedAch(id, allSourceId, paramYear);
                    relatedResult.setAchRelatedVoList(tmpList);
                    relatedResultList.add(relatedResult);
                }
            }
        }
        return relatedResultList;
    }

    @Override
    public List<TaskResourceLibrary> getRelatedAchTaskOfExpert(Long id) {
        return achievementsMapper.getRelatedAchTaskOfExpert(id);
    }

    @Override
    public List<CompetitionResourceLibrary> getRelatedAchCompetitionOfExpert(Long id) {
        return achievementsMapper.getRelatedAchCompetitionOfExpert(id);
    }


    /**
     * 根据查询内容，调用搜索行为接口
     *
     * @param achName
     * @param userId
     */
    @Override
    public int getSearchResult(String achName, Long userId) {
        int num = 0;
        if (StringUtils.isEmpty(achName)) {
            return num;
        }
        List<Long> idList = achievementsMapper.selectAchievementsByName(achName);
        if (StringUtils.isNotNull(idList)) {
            for (Long searchId : idList) {
                Searcher e = new Searcher();
                e.setCreatedAt(DateUtils.getNowDate());
                e.setUserId(userId);
                e.setSearchId(searchId);
                e.setExtInfo(achName);
                e.setSearchType("Achievements");
                num = taskResourceLibraryMapper.insertSearcher(e);
                num++;
            }
        }
        return num;
    }

    @Override
    public AchievementSourceStatisticVo getSource5Statistic(String name) {
        AchievementSourceStatisticVo ronbanVo = achievementsMapper.getSource5Field2(name);
        AchievementSourceStatisticVo statisticVo = achievementsMapper.getSource5Statistic(name);
        ronbanVo.setClickSum(statisticVo.getClickSum());
        ronbanVo.setAchievementSum(statisticVo.getAchievementSum());
        return ronbanVo;
    }

    @Override
    public List<KeyValueVo> getProjectAreasByName(String areaName) {
        return achievementsMapper.getProjectAreasByName(areaName);
    }

    @Override
    public List<String> getExpertAreasByName(String areaName) {
        return achievementsMapper.getExpertAreasByName(areaName);
    }

    @Override
    public AchDetailVo getAreaDetail(String areaKey,String kyxmSum, String source) {
        AchDetailVo achDetailVo = new AchDetailVo();
        AchQueryVo achQueryVo = new AchQueryVo();
        achQueryVo.setAreaQuery(areaKey);
        achQueryVo.setSource(source);
        //根据kye,和source,查询领域描述
        String remark = achievementsMapper.getField1RemarkByParam(source,areaKey);
        achDetailVo.setRemark(remark);
        List<Achievements> achievementsList = achievementsMapper.selectAchievementsByArea(achQueryVo);
        if(achievementsList!=null && achievementsList.size()>0) {
            achDetailVo.setAchievementsList(achievementsList);
            long clickSum = achievementsList.stream().mapToLong(Achievements::getClickSum).sum();
            achDetailVo.setClickSum(clickSum);
            long dockSum = achievementsList.stream().mapToLong(Achievements::getDockSum).sum();
            achDetailVo.setDockSum(dockSum);
            long favoriteSum = achievementsList.stream().mapToLong(Achievements::getFavoriteSum).sum();
            achDetailVo.setFavoriteSum(favoriteSum);
            long watcherSum = achievementsList.stream().mapToLong(Achievements::getWatcherSum).sum();
            achDetailVo.setWatcherSum(watcherSum);
        }
        return achDetailVo;
    }



    @Override
    public List<KeyValueVo> getAllAreas(String areaName) {
        List<KeyValueVo> resultVal = achievementsMapper.getAllAreas(areaName);
        return resultVal;
    }

    @Override
    public List<KeyValueVo> getAllField2() {
        List<KeyValueVo> resultVal = achievementsMapper.getAllField2();
        return resultVal;
    }

    @Override
    public List<AchievementTypeDictVo> achievementsTypeStatistic() {
        List<NameCountVo> nameCountVos = achievementsMapper.groupByAchievementsType();
        R<List<SysDictData>> feignResult = remoteDictDataService.dictType("dms_achievement_type");
        return Optional.ofNullable(feignResult.getData()).orElse(Collections.emptyList())
                .stream().map(sysDictData -> {
                    AchievementTypeDictVo dictVo = new AchievementTypeDictVo();
                    BeanUtils.copyProperties(sysDictData, dictVo);
                    dictVo.setCnt(nameCountVos.isEmpty() ? 0 : nameCountVos.stream().filter(dict -> sysDictData.getDictValue().equals(dict.getName()))
                            .mapToLong(NameCountVo::getCnt).sum());
                    return dictVo;
                }).collect(Collectors.toList());
    }

    @Override
    public List<AchievementSourceDictVo>  achievementsSourceStatistic() {
        List<NameCountVo> nameCountVos = achievementsMapper.groupByAchievementsSource();
        R<List<SysDictData>> feignResult = remoteDictDataService.dictType("dms_achievement_source");
        return Optional.ofNullable(feignResult.getData()).orElse(Collections.emptyList())
                .stream().map(sysDictData -> {
                    AchievementSourceDictVo dictVo = new AchievementSourceDictVo();
                    BeanUtils.copyProperties(sysDictData, dictVo);
                    dictVo.setCnt(nameCountVos.isEmpty() ? 0 : nameCountVos.stream().filter(dict -> dict.getName().equals(sysDictData.getDictValue()))
                            .mapToLong(NameCountVo::getCnt).sum());
                    return dictVo;
                }).collect(Collectors.toList());
    }


    @Override
    public Map<String, Object> batchInsertAchievements(List<Achievements> list, boolean updateSupport, String operName) {
        if (list == null || list.isEmpty()) {
            throw new RuntimeException("导入项目资源数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<Achievements> successList = new ArrayList<>();

        for (Achievements achievements : list) {
            try {
                // 查重：根据项目名称查询
                Achievements exist = achievementsMapper.selectAchievementsByAchievementName(achievements.getAchievementName());
                Long gitlinkUserId=SecurityUtils.getGitlinkUserId();
                Boolean gitlinkUserAdmin=achievementsMapper.isGitlinkAdminUser(gitlinkUserId) == 1;
                achievements.setStatus(gitlinkUserAdmin ? "1" : "0");
                achievements.setOwnerId(gitlinkUserId.toString());
                if (null == exist) {
                    achievements.setCreateBy(operName);
                    achievements.setCreateTime(new Date());
                    achievements.setUpdateBy(operName);
                    achievements.setUpdateTime(new Date());
                    achievementsMapper.insertAchievements(achievements);
                    successNum++;
                    successList.add(achievements);
                    successMsg.append("<br/>").append(successNum).append("、成果 ").append(achievements.getAchievementName()).append(" 导入成功");
                } else {
                    if (updateSupport && exist.getOwnerId() != null && exist.getOwnerId().equals(gitlinkUserId.toString())) {
                        achievements.setId(exist.getId());
                        achievements.setCreateBy(exist.getCreateBy());
                        achievements.setCreateTime(exist.getCreateTime());
                        achievements.setUpdateBy(operName);
                        achievements.setUpdateTime(new Date());
                        achievementsMapper.updateAchievements(achievements);
                        successNum++;
                        successList.add(achievements);
                        successMsg.append("<br/>").append(successNum).append("、成果 ").append(achievements.getAchievementName()).append(" 更新成功");
                    } else if (!updateSupport && exist.getOwnerId() != null && exist.getOwnerId().equals(gitlinkUserId.toString())) {
                        failureNum++;
                        failureMsg.append("<br/>").append(failureNum).append("、成果 ").append(achievements.getAchievementName()).append(" 已存在（未开启成果重名时覆盖更新）");
                    } else {
                        failureNum++;
                        failureMsg.append("<br/>").append(failureNum).append("、成果 ").append(achievements.getAchievementName()).append(" 其他用户已使用");
                    }
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、项目 " + achievements.getAchievementName() + " 导入失败：";
                failureMsg.append(msg).append(e.getMessage());
            }
        }

        // 组装最终提示信息
        StringBuilder finalMsg = new StringBuilder();
        if (successNum > 0) {
            finalMsg.append("共 ").append(successNum).append(" 条数据导入/更新成功：").append(successMsg);
            finalMsg.append("<br/>***压缩包共读取到 ").append(successList.stream().mapToInt(Achievements::getAttachmentCount).sum()).append(" 个文件");
        }
        if (failureNum > 0) {
            finalMsg.append("<br/>共 ").append(failureNum).append(" 条数据导入失败：").append(failureMsg);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("successNum", successNum);
        result.put("failureNum", failureNum);
        result.put("message", finalMsg);
        return result;
    }

    @Override
    public String batchImportAchievementsZip(MultipartFile file, boolean updateSupport) {
        // 尝试多种编码
        Charset[] charsets = {
                StandardCharsets.UTF_8,
                Charset.forName("GBK"),
                Charset.forName("GB2312"),
                Charset.forName("ISO-8859-1")
        };

        Map<String, Object> result = new HashMap<>();
        List<Achievements> excelDataList = new ArrayList<>();
        Map<String, AchievementSysFileVo> mp4ImagesExt1 = new HashMap<>();
        Map<String, AchievementSysFileVo> mp4ImagesExt2 = new HashMap<>();
        Map<String, AchievementSysFileVo> attachmentMap = new HashMap<>();
        Map<String, AchievementSysFileVo> coveImages = new HashMap<>();

        for (Charset charset : charsets) {
            ZipInputStream zipInputStream = null;
            try {
                zipInputStream = new ZipInputStream(file.getInputStream(), charset);
                ZipEntry entry;
                while ((entry = zipInputStream.getNextEntry()) != null) {
                    String entryName = entry.getName();

                    // 跳过目录条目
                    if (entry.isDirectory()) {
                        continue;
                    }

                    // 统一路径分隔符（处理Windows和Unix）
                    String normalizedPath = entryName.replace('\\', '/');
                    String fileName = getFileName(normalizedPath);
                    String parentPath = getParentPath(normalizedPath);

                    // 1. 处理 Excel 文件
                    if (!entryName.endsWith("附件") && (entryName.endsWith(".xlsx") || entryName.endsWith(".xls"))) {
                        byte[] content = readZipEntryContent(zipInputStream);
                        try (InputStream excelStream = new ByteArrayInputStream(content)) {
                            ExcelUtil<Achievements> util = new ExcelUtil<>(Achievements.class);
                            List<Achievements> dataList = util.importExcel(excelStream);
                            excelDataList.addAll(dataList);
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                    // 2. 处理 MP4 - 大文件建议保存到临时文件

                    else if (parentPath.endsWith("成果图片视频") && entryName.endsWith(".mp4")) {
                        File tempFile = saveToTempFile(zipInputStream, fileName);
                        String contentType = "video/mp4";
                        // 转换为MultipartFile并存储
                        MultipartFile videoFile = new FileMultipartFile(tempFile, fileName, contentType);
                        // 上传视频...
                        R<SysFile> fileResult = remoteFileService.upload(videoFile, "dms", "import", SecurityConstants.INNER);
                        if (R.SUCCESS == fileResult.getCode()) {
                            SysFile sysFile = fileResult.getData();
                            AchievementSysFileVo transferVo = new AchievementSysFileVo();
                            BeanUtils.copyProperties(sysFile, transferVo);
                            transferVo.setK(videoFile.getOriginalFilename());
                            transferVo.setV(sysFile.getUrl());
                            mp4ImagesExt1.put(fileName,  transferVo);
                        }
                        // 清理临时文件
                        tempFile.delete();
                    } else if (parentPath.endsWith("应用图片视频") && entryName.endsWith(".mp4")) {
                        File tempFile = saveToTempFile(zipInputStream, fileName);
                        String contentType = "video/mp4";
                        // 转换为MultipartFile并存储
                        MultipartFile videoFile = new FileMultipartFile(tempFile, fileName, contentType);
                        // 上传视频...
                        R<SysFile> fileResult = remoteFileService.upload(videoFile, "dms", "import", SecurityConstants.INNER);
                        if (R.SUCCESS == fileResult.getCode()) {
                            SysFile sysFile = fileResult.getData();
                            AchievementSysFileVo transferVo = new AchievementSysFileVo();
                            BeanUtils.copyProperties(sysFile, transferVo);
                            transferVo.setName(videoFile.getOriginalFilename());
                            transferVo.setK(videoFile.getOriginalFilename());
                            transferVo.setV(sysFile.getUrl());
                            mp4ImagesExt2.put(fileName,  transferVo);
                        }
                        // 清理临时文件
                        tempFile.delete();
                    }

                    // 3. 处理图片文件
                    else if (parentPath.endsWith("成果图片视频") && isImageFile(fileName)) {
                        byte[] content = readZipEntryContent(zipInputStream);
                        String suffix = "png";
                        if (entryName != null && entryName.contains(".")) {
                            suffix = entryName.substring(entryName.lastIndexOf(".") + 1);
                        }
                        String contentType = "image/" + suffix;
                        // 转换为MultipartFile并存储
                        MultipartFile imageFile = new CustomMultipartFile(content, fileName, contentType);
                        R<SysFile> fileResult = remoteFileService.upload(imageFile, "dms-open", "import", SecurityConstants.INNER);
                        if (R.SUCCESS == fileResult.getCode()) {
                            SysFile sysFile = fileResult.getData();
                            AchievementSysFileVo transferVo = new AchievementSysFileVo();
                            BeanUtils.copyProperties(sysFile, transferVo);
                            transferVo.setName(imageFile.getOriginalFilename());
                            transferVo.setK(imageFile.getOriginalFilename());
                            transferVo.setV(sysFile.getUrl());
                            mp4ImagesExt1.put(fileName,  transferVo);
                        }
                    }
                    // 3. 处理图片文件
                    else if (parentPath.endsWith("应用图片视频") && isImageFile(fileName)) {
                        byte[] content = readZipEntryContent(zipInputStream);
                        String suffix = "png";
                        if (entryName != null && entryName.contains(".")) {
                            suffix = entryName.substring(entryName.lastIndexOf(".") + 1);
                        }
                        String contentType = "image/" + suffix;
                        // 转换为MultipartFile并存储
                        MultipartFile imageFile = new CustomMultipartFile(content, fileName, contentType);
                        R<SysFile> fileResult = remoteFileService.upload(imageFile, "dms-open", "import", SecurityConstants.INNER);
                        if (R.SUCCESS == fileResult.getCode()) {
                            SysFile sysFile = fileResult.getData();
                            AchievementSysFileVo transferVo = new AchievementSysFileVo();
                            BeanUtils.copyProperties(sysFile, transferVo);
                            transferVo.setName(imageFile.getOriginalFilename());
                            transferVo.setK(imageFile.getOriginalFilename());
                            transferVo.setV(sysFile.getUrl());
                            mp4ImagesExt2.put(fileName,  transferVo);
                        }
                    }
                    else if (parentPath.endsWith("附件")) {
                        File tempFile = saveToTempFile(zipInputStream, fileName);
                        String contentType = FileTypeMap.getDefaultFileTypeMap().getContentType(fileName);
                        // 转换为MultipartFile并存储
                        MultipartFile attachmentFile = new FileMultipartFile(tempFile, fileName, contentType);
                        // 上传视频...
                        R<SysFile> fileResult = remoteFileService.upload(attachmentFile, "dms-open", "import", SecurityConstants.INNER);
                        if (R.SUCCESS == fileResult.getCode()) {
                            SysFile sysFile = fileResult.getData();
                            AchievementSysFileVo transferVo = new AchievementSysFileVo();
                            BeanUtils.copyProperties(sysFile, transferVo);
                            transferVo.setName(attachmentFile.getOriginalFilename());
                            transferVo.setK(attachmentFile.getOriginalFilename());
                            transferVo.setV(sysFile.getUrl());
                            attachmentMap.put(fileName,  transferVo);
                        }
                        // 清理临时文件
                        tempFile.delete();
                    }// 3. 处理图片文件
                    else if (parentPath.endsWith("封面图") && isImageFile(fileName)) {
                        byte[] content = readZipEntryContent(zipInputStream);
                        String suffix = "png";
                        if (entryName != null && entryName.contains(".")) {
                            suffix = entryName.substring(entryName.lastIndexOf(".") + 1);
                        }
                        String contentType = "image/" + suffix;
                        // 转换为MultipartFile并存储
                        MultipartFile imageFile = new CustomMultipartFile(content, fileName, contentType);
                        R<SysFile> fileResult = remoteFileService.upload(imageFile, "dms-open", "import", SecurityConstants.INNER);
                        if (R.SUCCESS == fileResult.getCode()) {
                            SysFile sysFile = fileResult.getData();
                            AchievementSysFileVo transferVo = new AchievementSysFileVo();
                            BeanUtils.copyProperties(sysFile, transferVo);
                            transferVo.setName(imageFile.getOriginalFilename());
                            transferVo.setK(imageFile.getOriginalFilename());
                            transferVo.setV(sysFile.getUrl());
                            coveImages.put(fileName,  transferVo);
                        }
                    }

                    zipInputStream.closeEntry();
                }
                logger.info("✅ 使用 " + charset.displayName() + " 编码成功读取 ZIP");
                List<Achievements> saveDataList = excelDataList.stream()
                        .filter(item -> StringUtils.isNotEmpty(item.getSource()) && StringUtils.isNotEmpty(item.getAchievementName()))
                        .collect(Collectors.toList());

                saveDataList.forEach(achievements -> {
                    List<Object> mp4ImagesExt1List = mp4ImagesExt1.entrySet().stream()
                            .filter(item -> item.getKey().contains(achievements.getAchievementName()))
                            .map(Map.Entry::getValue)
                            .collect(Collectors.toList());
                    List<Object> mp4ImagesExt2List = mp4ImagesExt2.entrySet().stream()
                            .filter(item -> item.getKey().contains(achievements.getAchievementName()))
                            .map(Map.Entry::getValue)
                            .collect(Collectors.toList());
                    List<Object> filterAttachmentList = attachmentMap.entrySet().stream()
                            .filter(item -> item.getKey().contains("入驻承诺书") || item.getKey().contains(achievements.getAchievementName()))
                            .map(Map.Entry::getValue)
                            .collect(Collectors.toList());
                    List<Object> coveImagesList = coveImages.entrySet().stream()
                            .filter(item -> item.getKey().contains(achievements.getAchievementName()))
                            .map(Map.Entry::getValue)
                            .collect(Collectors.toList());
                    if (!mp4ImagesExt1List.isEmpty()){
                        achievements.setExt1(JSONObject.toJSONString(mp4ImagesExt1List));
                        achievements.setAttachmentCount(achievements.getAttachmentCount() + mp4ImagesExt1List.size());
                    }
                    if (!mp4ImagesExt2List.isEmpty()){
                        achievements.setExt2(JSONObject.toJSONString(mp4ImagesExt2List));
                        achievements.setAttachmentCount(achievements.getAttachmentCount() + mp4ImagesExt2List.size());
                    }
                    if (!filterAttachmentList.isEmpty()){
                        achievements.setAttachments(JSONObject.toJSONString(filterAttachmentList));
                        achievements.setAttachmentCount(achievements.getAttachmentCount() + filterAttachmentList.size());
                    }
                    if (!coveImagesList.isEmpty()){
                        achievements.setImages(JSONObject.toJSONString(coveImagesList));
                        achievements.setAttachmentCount(achievements.getAttachmentCount() + coveImagesList.size());
                    }
                });

                // 保存 Excel 数据到数据库
                String operName = SecurityUtils.getUsername();
                Map<String, Object> resultMap = saveDataList.isEmpty() ? new HashMap<>() : batchInsertAchievements(saveDataList, updateSupport, operName);
//
                return resultMap.get("message") ==null ? "未去读取到数据，请确认文件压缩目录是否正确" : resultMap.get("message").toString();
            } catch (IOException e) {
                logger.error("读取文件失败: " + e.getMessage());
            } catch (IllegalArgumentException ex) {
                logger.error("使用 " + charset.displayName() + " 编码失败: " + ex.getMessage());
            } finally {
                if (zipInputStream != null) {
                    try {
                        zipInputStream.close();
                    }catch (IOException exc){
                        exc.printStackTrace();
                    }

                }
            }
        }
        return "";
    }

    /**
     * 保存流内容到临时文件
     */
    private File saveToTempFile(ZipInputStream zipInputStream, String fileName) throws IOException {
        Path tempFile = Files.createTempFile("temp_", "_" + fileName);
        try (FileOutputStream fos = new FileOutputStream(tempFile.toFile())) {
            byte[] buffer = new byte[8192];
            int len;
            while ((len = zipInputStream.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
        }
        return tempFile.toFile();
    }

    /**
     * 读取 ZipEntry 的内容到字节数组（Java 8 兼容）
     */
    private byte[] readZipEntryContent(ZipInputStream zipInputStream) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[8192]; // 8KB 缓冲区
        int len;
        while ((len = zipInputStream.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        return baos.toByteArray();
    }

    // 辅助方法：判断是否为图片
    private boolean isImageFile(String fileName) {
        String lower = fileName.toLowerCase();
        return lower.endsWith(".jpg") || lower.endsWith(".jpeg") ||
                lower.endsWith(".png") || lower.endsWith(".gif") || lower.endsWith(".bmp");
    }

    /**
     * 获取文件名（去掉路径）
     */
    private String getFileName(String path) {
        if (path == null || path.isEmpty()) return "";
        int lastSlash = path.lastIndexOf('/');
        if (lastSlash >= 0) {
            return path.substring(lastSlash + 1);
        }
        return path;
    }

    /**
     * 获取父路径（去掉文件名）
     */
    private String getParentPath(String path) {
        if (path == null || path.isEmpty()) return "";
        int lastSlash = path.lastIndexOf('/');
        if (lastSlash >= 0) {
            return path.substring(0, lastSlash);
        }
        return "";
    }

    private String buildFileInfoByIdentifiers(String identifiers) {
        if (StringUtils.isEmpty(identifiers)) {
            return identifiers;
        }
        R<List<SysFileInfo>> result = remoteFileService.getFileListByIdentifier(identifiers);
        return JSON.toJSONString(result.getData());
    }

}
