package com.vetti.hotake.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONUtil;
import com.vetti.common.ai.gpt.ChatGPTClient;
import com.vetti.common.config.RuoYiConfig;
import com.vetti.common.core.service.BaseServiceImpl;
import com.vetti.common.enums.CvOperDataTypeEnum;
import com.vetti.common.enums.FillTypeEnum;
import com.vetti.common.enums.MinioBucketNameEnum;
import com.vetti.common.exception.ServiceException;
import com.vetti.common.utils.*;
import com.vetti.common.utils.readFile.FileContentUtil;
import com.vetti.hotake.domain.HotakeCvInfo;
import com.vetti.hotake.domain.HotakeProblemBaseInfo;
import com.vetti.hotake.domain.HotakeSysFile;
import com.vetti.hotake.domain.dto.HotakeCvInfoDto;
import com.vetti.hotake.domain.dto.HotakeCvOptimizeDto;
import com.vetti.hotake.domain.dto.VcDto.*;
import com.vetti.hotake.domain.vo.HotakeSysFileVo;
import com.vetti.hotake.mapper.HotakeCvInfoMapper;
import com.vetti.hotake.service.IHotakeAiCommonToolsService;
import com.vetti.hotake.service.IHotakeCvInfoService;
import com.vetti.hotake.service.IHotakeProblemBaseInfoService;
import com.vetti.hotake.service.IHotakeSysFileService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * 简历信息Service业务层处理
 *
 * @author wangxiangshun
 * @date 2025-11-02
 */
@Slf4j
@SuppressWarnings("all")
@Service
public class HotakeCvInfoServiceImpl extends BaseServiceImpl implements IHotakeCvInfoService {

    // 系统目录
    private static final String SYSTEM_DIR = "/system_files/";

    /**
     * 问题前缀
     */
    private final String QUESTION_PREFIX = "Question:";

    @Autowired
    private HotakeCvInfoMapper hotakeCvInfoMapper;

    @Autowired
    private ChatGPTClient chatGPTClient;

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private IHotakeProblemBaseInfoService hotakeProblemBaseInfoService;

    @Autowired
    private IHotakeAiCommonToolsService aiCommonToolsService;

    @Autowired
    private IHotakeSysFileService sysFileService;

    /**
     * 查询简历信息
     *
     * @param id 简历信息主键
     * @return 简历信息
     */
    @Transactional(readOnly = true)
    @Override
    public HotakeCvInfo selectHotakeCvInfoById(Long id) {
        HotakeCvInfo cvInfo = hotakeCvInfoMapper.selectHotakeCvInfoById(id);
        if (StrUtil.isNotEmpty(cvInfo.getCvTemplateJson())) {
            HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(cvInfo.getCvTemplateJson(), HotakeCvInfoDto.class);
            cvInfo.setCvInfoDto(cvInfoDto);
        }
        if (StrUtil.isNotEmpty(cvInfo.getCvOptimizeJson())) {
            //解析优化简历
            HotakeCvOptimizeDto cvOptimizeDto = JSONUtil.toBean(cvInfo.getCvOptimizeJson(), HotakeCvOptimizeDto.class);
            if (cvOptimizeDto != null) {
                cvInfo.setCvOptimizeDto(cvOptimizeDto);
                if (cvOptimizeDto.getTextCorrections() != null && CollectionUtil.isNotEmpty(cvOptimizeDto.getTextCorrections().getFormattingIssues())) {
                    cvInfo.setTextCorrectionsNums(cvOptimizeDto.getTextCorrections().getFormattingIssues().size());
                } else {
                    cvInfo.setTextCorrectionsNums(0);
                }
                if (cvOptimizeDto.getLogicCorrections() != null && CollectionUtil.isNotEmpty(cvOptimizeDto.getLogicCorrections().getCareerProgressionDtos())) {
                    cvInfo.setLogicCorrectionsNum(cvOptimizeDto.getTextCorrections().getFormattingIssues().size());
                } else {
                    cvInfo.setLogicCorrectionsNum(0);
                }
            }
        }
        HotakeProblemBaseInfo query = new HotakeProblemBaseInfo();
        query.setCvId(id);
        List<HotakeProblemBaseInfo> problemBaseInfoList = hotakeProblemBaseInfoService.selectHotakeProblemBaseInfoList(query);
        if (CollectionUtil.isNotEmpty(problemBaseInfoList)) {
            cvInfo.setProblemBaseInfo(problemBaseInfoList.get(0));
        }
        return cvInfo;
    }

    /**
     * 查询简历信息列表
     *
     * @param hotakeCvInfo 简历信息
     * @return 简历信息
     */
    @Transactional(readOnly = true)
    @Override
    public List<HotakeCvInfo> selectHotakeCvInfoList(HotakeCvInfo hotakeCvInfo) {
        List<HotakeCvInfo> cvInfoList = hotakeCvInfoMapper.selectHotakeCvInfoList(hotakeCvInfo);
        if (CollectionUtil.isNotEmpty(cvInfoList)) {
            for (HotakeCvInfo cvInfo : cvInfoList) {
                HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(cvInfo.getCvTemplateJson(), HotakeCvInfoDto.class);
                cvInfo.setCvInfoDto(cvInfoDto);
                //返回问题记录
            }
        }
        return cvInfoList;
    }

    /**
     * 新增简历信息
     *
     * @param hotakeCvInfo 简历信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public HotakeCvInfo insertHotakeCvInfo(HotakeCvInfo hotakeCvInfo) {
        if ("cv".equals(hotakeCvInfo.getCvFileType())) {
            //删除原先的CV简历信息
            hotakeCvInfoMapper.deleteHotakeCvInfoByUserIdAndType(SecurityUtils.getUserId(), "cv");
        }
        fill(FillTypeEnum.INSERT.getCode(), hotakeCvInfo);
        String fileSuffix = FileUtil.getSuffix(hotakeCvInfo.getCvUrl());
        if (StrUtil.isNotEmpty(fileSuffix)) {
            fileSuffix = fileSuffix.toLowerCase();
        }
        hotakeCvInfo.setCvFileSuffix(fileSuffix);
        if (!"cv".equals(hotakeCvInfo.getCvFileType())) {
            //对附件进行基础数据的解析
            String resultStr = handleAnalyzedAttachment(hotakeCvInfo.getCvUrl(), fileSuffix);
            hotakeCvInfo.setAnalyzedAttachmentJson(resultStr);
        }
        if("cv".equals(hotakeCvInfo.getCvFileType())) {
            hotakeCvInfo.setCvTemplateJson(JSONUtil.toJsonStr(hotakeCvInfo.getCvInfoDto()));

            //如果是手动创建的简历要生成简历的附件数据
            if(CvOperDataTypeEnum.MANUAL.getCode().equals(hotakeCvInfo.getDataType())){
                if(StrUtil.isNotEmpty(hotakeCvInfo.getCvTemplateJson())){
                    HotakeSysFile sysFile = createCvFile(hotakeCvInfo.getCvTemplateJson());
                    hotakeCvInfo.setCvName(sysFile.getFileName());
                    hotakeCvInfo.setFileSizeShow(sysFile.getFileSizeShow());
                    hotakeCvInfo.setCvUrl(sysFile.getStoragePath());
                }
            }
        }

        hotakeCvInfoMapper.insertHotakeCvInfo(hotakeCvInfo);
        return hotakeCvInfo;
    }

    /**
     * 处理简历信息
     *
     * @param hotakeCvInfo 简历信息
     * @return
     */
    @Override
    public HotakeProblemBaseInfo handleHotakeCvInfo(HotakeCvInfoDto cvInfoDto, Long cvId) {
        log.info("处理简历信息");
        HotakeProblemBaseInfo problemBaseInfo = new HotakeProblemBaseInfo();
        try {
            //调用AI大模型
            List<Map<String, String>> list = new LinkedList();
            Map<String, String> mapEntity = new HashMap<>();
            mapEntity.put("role", "system");
            mapEntity.put("content", "You are an experienced interviewer for construction management positions. Generate targeted interview questions based on candidate resumes.");
            list.add(mapEntity);
            Map<String, String> mapEntityOne = new HashMap<>();
            mapEntityOne.put("role", "user");
            mapEntityOne.put("content", "Position: Construction Labourer" +
                    "\\nCandidate: " + cvInfoDto.getName() +
                    "\\nKey Skills: " + JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()) +
                    "\\nExperience: " + JSONUtil.toJsonStr(cvInfoDto.getExperience()) +
                    "\\nStrengths: Professional certifications, Relevant experience" +
                    "\\nConcerns: " + JSONUtil.toJsonStr(cvInfoDto.getAbout()));
            list.add(mapEntityOne);
            String promptText = JSONUtil.toJsonStr(list);
            String resultMsg = chatGPTClient.handleAiChat(promptText, "CV");
            log.info("返回简历问题数据:{}", resultMsg);
            resultMsg = resultMsg.replaceAll("\n", "#AA#");
            String question = "";
            Integer questionNums = 0;
            if (StrUtil.isNotEmpty(resultMsg)) {
                resultMsg = resultMsg.replaceAll(QUESTION_PREFIX, "");
                questionNums = resultMsg.split("#AA#").length;
            }
            //生成预设问题记录
            //先删除该用户的预设问题
            hotakeProblemBaseInfoService.deleteHotakeProblemBaseInfoByUserId(SecurityUtils.getUserId(), cvId);
            problemBaseInfo.setUserId(SecurityUtils.getUserId());
            problemBaseInfo.setContents(resultMsg);
            problemBaseInfo.setQuestionNums(questionNums);
            problemBaseInfo.setCvId(cvId);
            hotakeProblemBaseInfoService.insertHotakeProblemBaseInfo(problemBaseInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return problemBaseInfo;
    }


    /**
     * 修改简历信息
     *
     * @param hotakeCvInfo 简历信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public HotakeCvInfo updateHotakeCvInfo(HotakeCvInfo hotakeCvInfo) {
        fill(FillTypeEnum.UPDATE.getCode(), hotakeCvInfo);

        hotakeCvInfo.setCvTemplateJson(JSONUtil.toJsonStr(hotakeCvInfo.getCvInfoDto()));
        //创建简历
        if("cv".equals(hotakeCvInfo.getCvFileType())) {
            //如果是手动创建的简历要生成简历的附件数据
            if(CvOperDataTypeEnum.MANUAL.getCode().equals(hotakeCvInfo.getDataType())){
                if(StrUtil.isNotEmpty(hotakeCvInfo.getCvTemplateJson())){
                    HotakeSysFile sysFile = createCvFile(hotakeCvInfo.getCvTemplateJson());
                    hotakeCvInfo.setCvName(sysFile.getFileName());
                    hotakeCvInfo.setFileSizeShow(sysFile.getFileSizeShow());
                    hotakeCvInfo.setCvUrl(sysFile.getStoragePath());
                }
            }
        }
        hotakeCvInfoMapper.updateHotakeCvInfo(hotakeCvInfo);
        return hotakeCvInfo;
    }

    /**
     * 批量删除简历信息
     *
     * @param ids 需要删除的简历信息主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteHotakeCvInfoByIds(Long[] ids) {
        return hotakeCvInfoMapper.deleteHotakeCvInfoByIds(ids);
    }

    /**
     * 删除简历信息信息
     *
     * @param id 简历信息主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteHotakeCvInfoById(Long id) {
        return hotakeCvInfoMapper.deleteHotakeCvInfoById(id);
    }

    /**
     * 批量新增简历信息
     *
     * @param hotakeCvInfoList 简历信息列表
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int batchInsertHotakeCvInfo(List<HotakeCvInfo> hotakeCvInfoList) {
        return hotakeCvInfoMapper.batchInsertHotakeCvInfo(hotakeCvInfoList);
    }

    /**
     * 简历解析以及生成问题和评分
     *
     * @param hotakeCvInfo 简历信息
     * @return
     */
    @Override
    public HotakeCvInfo handleCvAnalysis(HotakeCvInfo hotakeCvInfo) {
        HotakeCvInfo cvInfo = selectHotakeCvInfoById(hotakeCvInfo.getId());
        if ("cv".equals(cvInfo.getCvFileType())) {
            log.info("开始处理简历");
            try {
                InputStream inputStream = minioClient.getObject(
                        GetObjectArgs.builder()
                                .bucket(MinioBucketNameEnum.CV.getCode())
                                .object(cvInfo.getCvUrl())
                                .build());
                String contents = FileContentUtil.readFileContent(inputStream, cvInfo.getCvFileSuffix());
                log.info("简历信息:{}", contents);
                //验证文件内容是否改变,如果未改变不进行模型解析直接返回原有结果
                String md5Hash = MD5.create().digestHex16(contents);
                if (StrUtil.isNotEmpty(md5Hash) && md5Hash.equals(cvInfo.getCvMd5())) {
                    //直接返回简历结果
                    return cvInfo;
                }
                cvInfo.setCvMd5(md5Hash);
                //生成简历模版数据信息
                HotakeCvInfoDto cvInfoDto = handleAnalysisCvInfo(contents);
                cvInfo.setCvInfoDto(cvInfoDto);
                //对简历数据进行处理生成相应的题库数据
                HotakeProblemBaseInfo problemBaseInfo = handleHotakeCvInfo(cvInfoDto, hotakeCvInfo.getId());
                cvInfo.setProblemBaseInfo(problemBaseInfo);
                //解析优化简历
                HotakeCvOptimizeDto cvOptimizeDto = aiCommonToolsService.getResumeAnalysisOptimizer(contents);

                if (cvOptimizeDto != null) {
                    cvInfo.setCvOptimizeJson(JSONUtil.toJsonStr(cvOptimizeDto));
                    if (cvOptimizeDto.getTextCorrections() != null && CollectionUtil.isNotEmpty(cvOptimizeDto.getTextCorrections().getFormattingIssues())) {
                        cvInfo.setTextCorrectionsNums(cvOptimizeDto.getTextCorrections().getFormattingIssues().size());
                    } else {
                        cvInfo.setTextCorrectionsNums(0);
                    }
                    if (cvOptimizeDto.getLogicCorrections() != null && CollectionUtil.isNotEmpty(cvOptimizeDto.getLogicCorrections().getCareerProgressionDtos())) {
                        cvInfo.setLogicCorrectionsNum(cvOptimizeDto.getTextCorrections().getFormattingIssues().size());
                    } else {
                        cvInfo.setLogicCorrectionsNum(0);
                    }
                    cvInfo.setCvOptimizeDto(cvOptimizeDto);
                }

//                //生成对应的简历评分
//                String resultMsg = handleHotakeCvInfoScore(cvInfoDto);
//                cvInfo.setCvScore(resultMsg);
                cvInfo.setExperience(cvInfoDto.getExperienceYear());
                //分数解析
//                String[] strs = resultMsg.split("\n");
//                if(strs != null && strs.length > 0){
//                    String score = strs[0].replaceAll("Score:","").trim();
//                    String[] scores = score.split("/");
//                    if(scores != null && scores.length > 0){
//                        cvInfo.setAiMatchScore(scores[0]);
//                        try{
//                            cvInfo.setAiMatchScorePercentage(String.valueOf(new BigDecimal(scores[0]).
//                                    divide(new BigDecimal(5)).setScale(2,4)));
//                        }catch (Exception e){e.printStackTrace();}
//
//                    }
//                }
                cvInfo.setCvTemplateJson(JSONUtil.toJsonStr(cvInfoDto));
                fill(FillTypeEnum.UPDATE.getCode(), cvInfo);
                hotakeCvInfoMapper.updateHotakeCvInfo(cvInfo);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return cvInfo;
    }

    /**
     * 根据其他的附件信息生成个人简历
     *
     * @return
     */
    @Override
    public HotakeCvInfo getGenerateResume() {
        //根据候选人登陆信息查询所有的附件信息
        HotakeCvInfo queryCv = new HotakeCvInfo();
        queryCv.setUserId(SecurityUtils.getUserId());
        List<HotakeCvInfo> cvInfoList = hotakeCvInfoMapper.selectHotakeCvInfoList(queryCv);

        //基础数据信息,从推荐信中过去
        String basicInformation = "";
        //其他的附件信息集合
        String attachmentContent = "";
        if (CollectionUtil.isNotEmpty(cvInfoList)) {
            List<HotakeCvInfo> cvInfos = cvInfoList.stream().filter(e -> "letter".equals(e.getCvFileType())).toList();
            if (CollectionUtil.isNotEmpty(cvInfos)) {
                basicInformation = cvInfos.get(0).getAnalyzedAttachmentJson();
            }
            List<HotakeCvInfo> cvInfoOnes = cvInfoList.stream().filter(e -> !"letter".equals(e.getCvFileType())
                    && !"cv".equals(e.getCvFileType())).toList();
            if (CollectionUtil.isNotEmpty(cvInfoOnes)) {
                List<Map> attachmentContentList = new ArrayList<>();
                for (HotakeCvInfo hotakeCvInfo : cvInfoOnes) {
                    if (StrUtil.isNotEmpty(hotakeCvInfo.getAnalyzedAttachmentJson())) {
                        Map map = JSONUtil.toBean(hotakeCvInfo.getAnalyzedAttachmentJson(), Map.class);
                        attachmentContentList.add(map);
                    }
                }
                if (CollectionUtil.isNotEmpty(attachmentContentList)) {
                    attachmentContent = JSONUtil.toJsonStr(attachmentContentList);
                }
            }
        }
        String cvData = aiCommonToolsService.handleAttachmentResultMerging(basicInformation, attachmentContent);
        //进行简历数据组合
        Map dataMap = JSONUtil.toBean(cvData, Map.class);
        HotakeCvInfoDto cvInfoDto = new HotakeCvInfoDto();
        //个人基本信息
        Map personalInfoMap = (Map) dataMap.get("personal_info");
        if (personalInfoMap != null) {
            cvInfoDto.setName(StringUtils.getObjectStr(personalInfoMap.get("full_name")));
            Map contactDetailsMap = (Map) personalInfoMap.get("contact_details");
            if (contactDetailsMap != null) {
                cvInfoDto.setPhone(StringUtils.getObjectStr(contactDetailsMap.get("phone")));
                cvInfoDto.setEmail(StringUtils.getObjectStr(contactDetailsMap.get("email")));
                cvInfoDto.setLocation(StringUtils.getObjectStr(contactDetailsMap.get("address")));
            } else {
                cvInfoDto.setPhone(StringUtils.getObjectStr(personalInfoMap.get("phone")));
                cvInfoDto.setEmail(StringUtils.getObjectStr(personalInfoMap.get("email")));
                cvInfoDto.setLocation(StringUtils.getObjectStr(personalInfoMap.get("address")));
            }
        }

        //个人介绍
        cvInfoDto.setAbout(StringUtils.getObjectStr(dataMap.get("professional_summary")));

        try {
            //技能工具
            List<Map> skillsList = (List<Map>) dataMap.get("skills_certificates");
            if (CollectionUtil.isNotEmpty(skillsList)) {
                Map map = skillsList.get(0);
                if (map != null) {
                    List<String> skillsAllList = (List<String>) map.get("skills");
                    //技能工具
                    List<VcSkillsToolsDto> skillsTools = new ArrayList<>();
                    if (CollectionUtil.isNotEmpty(skillsAllList)) {
                        for (String skill : skillsAllList) {
                            VcSkillsToolsDto toolsDto = new VcSkillsToolsDto();
                            toolsDto.setContent(skill);
                            skillsTools.add(toolsDto);
                        }
                    }
                    cvInfoDto.setSkillsTools(skillsTools);
                }

            }
        } catch (Exception e) {
            //技能工具
            List<String> skillsList = (List<String>) dataMap.get("skills_certificates");
            if (CollectionUtil.isNotEmpty(skillsList)) {
                //技能工具
                List<VcSkillsToolsDto> skillsTools = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(skillsList)) {
                    for (String skill : skillsList) {
                        VcSkillsToolsDto toolsDto = new VcSkillsToolsDto();
                        toolsDto.setContent(skill);
                        skillsTools.add(toolsDto);
                    }
                }
                cvInfoDto.setSkillsTools(skillsTools);
            }
        }


        //工作经验集合
        List<VcExperienceDto> experience = new ArrayList<>();
        List<Map> workExperienceMapList = (List<Map>) dataMap.get("work_experience");
        if (CollectionUtil.isNotEmpty(workExperienceMapList)) {
            for (Map map : workExperienceMapList) {
                VcExperienceDto experienceDto = new VcExperienceDto();

                experienceDto.setCompany(StringUtils.getObjectStr(map.get("company")));
                experienceDto.setTitle(StringUtils.getObjectStr(map.get("job_title")));
                experienceDto.setLocation(StringUtils.getObjectStr(map.get("location")));
                String startDate = StringUtils.getObjectStr(map.get("start_date"));
                experienceDto.setDurationStart(startDate);
                String endDate = StringUtils.getObjectStr(map.get("end_date"));
                experienceDto.setDurationEnd(endDate);
                List<VcExperienceDescriptionDto> description = new ArrayList<>();
                List<String> responsibilitiesList = (List<String>) map.get("responsibilities");
                if (CollectionUtil.isNotEmpty(responsibilitiesList)) {
                    for (String responsibility : responsibilitiesList) {
                        VcExperienceDescriptionDto descriptionDto = new VcExperienceDescriptionDto();
                        descriptionDto.setContent(responsibility);
                        description.add(descriptionDto);
                    }
                    experienceDto.setDescription(description);
                }
                experience.add(experienceDto);
            }
            cvInfoDto.setExperience(experience);
        }
        //教育经历
        List<VcEducationDto> educationList = new ArrayList<>();
        List<Map> educationMapList = (List<Map>) dataMap.get("education");
        if (CollectionUtil.isNotEmpty(educationMapList)) {
            for (Map map : educationMapList) {
                VcEducationDto educationDto = new VcEducationDto();
                educationDto.setDegree(StringUtils.getObjectStr(map.get("degree")));
                educationDto.setInstitution(StringUtils.getObjectStr(map.get("institution")));
                String time_period = StringUtils.getObjectStr(map.get("graduation_date"));
                if (StrUtil.isNotEmpty(time_period)) {
                    String[] times = time_period.split("–");
                    educationDto.setDurationStart(times[0]);
                    if (times.length > 1) {
                        educationDto.setDurationEnd(times[1]);
                    }
                }
                educationList.add(educationDto);
            }
        }
        cvInfoDto.setEducation(educationList);
        //创建简历信息
        HotakeCvInfo cvInfo = new HotakeCvInfo();
        cvInfo.setUserId(SecurityUtils.getUserId());
        cvInfo.setCvInfoDto(cvInfoDto);
        cvInfo.setCvTemplateJson(JSONUtil.toJsonStr(cvInfoDto));
        cvInfo.setCvFileType("cv");
        cvInfo.setCvFileSuffix("pdf");
        cvInfo.setStatus("1");
        //生成简历PDF数据
        HotakeSysFile sysFile = createCvFile(cvData);
        cvInfo.setCvName(sysFile.getFileName());
        cvInfo.setFileSizeShow(sysFile.getFileSizeShow());
        cvInfo.setCvUrl(sysFile.getStoragePath());
        //创建简历对象数据
        insertHotakeCvInfo(cvInfo);
        return cvInfo;
    }


    /**
     * 简历解析数据
     *
     * @param contents
     * @return
     */
    private HotakeCvInfoDto handleAnalysisCvInfo(String contents) {
        log.info("开始简历解析");
        try {
            List<Map<String, String>> list = new LinkedList();
            Map<String, String> entity = new HashMap<>();
            entity.put("role", "user");
            // TODO: 修复工作年限计算错误 - Bug修复说明
            // 问题：之前的提示词中"experienceYear（根据工作经验计算出来的工作年限）"描述不够明确，
            // 导致AI可能会将教育时间也计算在内，或者简单地用最早年份到最新年份的差值，
            // 例如：2006年上大学到2025年工作 = 19年（错误），实际应该是2010年毕业后开始工作约15年
            // 
            // 修复方案：在提示词中明确工作年限的计算规则：
            // 1. 只计算experience（工作经历）中的时间段，不包括education（教育经历）
            // 2. 累加所有工作经历的实际工作时长（年）
            // 3. 如果工作结束时间是"Present"、"Current"、"至今"等，使用当前年份(2026)计算
            // 4. 计算公式：总工作年限 = Σ(每段工作的结束年份 - 开始年份)
            // 5. 结果保留整数，向下取整
            // 
            // 修改日期：2026-02-04
            // 修改人：sxc
            entity.put("content", "从下面提供的文本中提取所有能识别到的简历信息，只提取原文中存在的内容，不要补充、不推测、不总结。需要提取的字段包括：name（姓名或人名）、phone（电话号码）、email（电子邮件地址）、experienceYear（工作年限，重要：只计算experience工作经历中的实际工作时长，不包括education教育时间。计算方法：累加所有工作经历的年数，如果结束时间是Present/Current/至今则用2026年计算，例如：2018-01到2020-06工作2年+2021-03到Present工作5年=总共7年工作经验）、position（岗位或者简历中自己期望的职位等）、location（地点或者地址、家庭住址）、links（所有链接地址）、currentWork(当前工作公司)、about（关于我/自我介绍）、skills_tools（关键资格（许可证、注册/会员资格、认证））、languages（语言能力,主要就是Languages下面的语言）、experience（工作经历,除了title、company、location、durationStart、durationEnd,其他的都放到description里面,并且description里面要根据换行符分成不同的content),日期要拆分成开始时间(durationStart)和结束时间(durationEnd)）、education（教育经历,日期要拆分成开始时间(durationStart)和结束时间(durationEnd)）。请将提取结果以结构化 JSON 格式返回，格式如下：{ \\\"name\\\": \\\"\\\", \\\"phone\\\": \\\"\\\", \\\"currentWork\\\": \\\"\\\", \\\"position\\\": \\\"\\\", \\\"location\\\": \\\"\\\", \\\"email\\\": \\\"\\\", \\\"experienceYear\\\": \\\"\\\", \\\"links\\\": [{\\\"content\\\":\\\"\\\"}], \\\"about\\\": \\\"\\\", \\\"skillsTools\\\": [{\\\"content\\\":\\\"\\\"}], \\\"languages\\\": [{\\\"content\\\":\\\"\\\"}], \\\"experience\\\": [{\\\"title\\\": \\\"\\\", \\\"company\\\": \\\"\\\",\\\"location\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\",\\\"description\\\": [{\\\"content\\\":\\\"\\\"}]}], \\\"education\\\": [{\\\"degree\\\": \\\"\\\",\\\"institution\\\": \\\"\\\",\\\"durationStart\\\": \\\"\\\",\\\"durationEnd\\\": \\\"\\\"}] }。字段不存在则返回 null 或空数组。只返回标准可解析的 JSON结构 ,不要多余的```json等信息，" +
                    "不要解释说明，不要改写内容,其中日期字段要转换格式为:yyyy-MM，例如 Apr 2016,要转换成 2016-04,并且只有年要补充固定月份01月，例如2025，要转换成2025-01。以下为待处理文本：" + contents);
            //根据AI做
            list.add(entity);
            String resultCv = chatGPTClient.handleAiChat(JSONUtil.toJsonStr(list), "JX");
            log.info("开始返回简历解析结果:{}", resultCv);
            HotakeCvInfoDto cvInfoDto = JSONUtil.toBean(resultCv, HotakeCvInfoDto.class);
            //数据添加默认值
            if (cvInfoDto != null) {
                if (StrUtil.isEmpty(cvInfoDto.getName())) {
                    cvInfoDto.setName("-");
                }
                if (StrUtil.isEmpty(cvInfoDto.getPhone())) {
                    cvInfoDto.setPhone("-");
                }
                if (StrUtil.isEmpty(cvInfoDto.getEmail())) {
                    cvInfoDto.setEmail("-");
                }
                if (StrUtil.isEmpty(cvInfoDto.getPosition())) {
                    cvInfoDto.setPosition("-");
                }
                if (StrUtil.isEmpty(cvInfoDto.getLocation())) {
                    cvInfoDto.setLocation("-");
                }
                if (StrUtil.isEmpty(cvInfoDto.getAbout())) {
                    cvInfoDto.setAbout("-");
                }
                if (StrUtil.isEmpty(cvInfoDto.getCurrentWork())) {
                    cvInfoDto.setCurrentWork("-");
                }
                if (CollectionUtil.isNotEmpty(cvInfoDto.getSkillsTools())) {
                    for (VcSkillsToolsDto toolsDto : cvInfoDto.getSkillsTools()) {
                        if (StrUtil.isEmpty(toolsDto.getContent())) {
                            toolsDto.setContent("-");
                        }
                    }
                }
                if (CollectionUtil.isNotEmpty(cvInfoDto.getLinks())) {
                    for (VcLinksDto linksDto : cvInfoDto.getLinks()) {
                        if (StrUtil.isEmpty(linksDto.getContent())) {
                            linksDto.setContent("-");
                        }
                    }
                }

                if (CollectionUtil.isNotEmpty(cvInfoDto.getLanguages())) {
                    for (VcLanguagesDto languagesDto : cvInfoDto.getLanguages()) {
                        if (StrUtil.isEmpty(languagesDto.getContent())) {
                            languagesDto.setContent("-");
                        }
                    }
                }

                if (CollectionUtil.isNotEmpty(cvInfoDto.getExperience())) {
                    for (VcExperienceDto experienceDto : cvInfoDto.getExperience()) {
                        if (StrUtil.isEmpty(experienceDto.getTitle())) {
                            experienceDto.setTitle("-");
                        }
                        if (StrUtil.isEmpty(experienceDto.getCompany())) {
                            experienceDto.setCompany("-");
                        }
                        if (StrUtil.isEmpty(experienceDto.getLocation())) {
                            experienceDto.setLocation("-");
                        }
                        if (StrUtil.isEmpty(experienceDto.getDurationStart())) {
                            experienceDto.setDurationStart("-");
                        }
                        if (StrUtil.isEmpty(experienceDto.getDurationEnd())) {
                            experienceDto.setDurationEnd("-");
                        }
                        if (CollectionUtil.isNotEmpty(experienceDto.getDescription())) {
                            for (VcExperienceDescriptionDto descriptionDto : experienceDto.getDescription()) {
                                if (StrUtil.isEmpty(descriptionDto.getContent())) {
                                    descriptionDto.setContent("-");
                                }

                            }
                        }
                    }
                }

                if (CollectionUtil.isNotEmpty(cvInfoDto.getEducation())) {
                    for (VcEducationDto educationDto : cvInfoDto.getEducation()) {
                        if (StrUtil.isEmpty(educationDto.getDegree())) {
                            educationDto.setDegree("-");
                        }
                        if (StrUtil.isEmpty(educationDto.getInstitution())) {
                            educationDto.setInstitution("-");
                        }
                        if (StrUtil.isEmpty(educationDto.getDurationStart())) {
                            educationDto.setDurationStart("-");
                        }
                        if (StrUtil.isEmpty(educationDto.getDurationEnd())) {
                            educationDto.setDurationEnd("-");
                        }
                        if (educationDto.getCertificate() != null) {
                            if (StrUtil.isEmpty(educationDto.getCertificate().getFileName())) {
                                educationDto.getCertificate().setFileName("-");
                            }
                            if (StrUtil.isEmpty(educationDto.getCertificate().getFileSuffix())) {
                                educationDto.getCertificate().setFileSuffix("-");
                            }
                            if (StrUtil.isEmpty(educationDto.getCertificate().getFileUrl())) {
                                educationDto.getCertificate().setFileUrl("-");
                            }
                            if (StrUtil.isEmpty(educationDto.getCertificate().getFileSizeShow())) {
                                educationDto.getCertificate().setFileSizeShow("-");
                            }
                        }
                    }
                }
            }

            return cvInfoDto;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HotakeCvInfoDto();
    }


    /**
     * 处理简历信息
     *
     * @param hotakeCvInfo 简历信息
     * @return
     */
    private String handleHotakeCvInfoScore(HotakeCvInfoDto cvInfoDto) {
        String resultMsg = "";
        try {
            //调用AI大模型
            List<Map<String, String>> list = new LinkedList();
            Map<String, String> mapEntity = new HashMap<>();
            mapEntity.put("role", "system");
            mapEntity.put("content", "You are a construction industry HR expert. Evaluate resumes and provide scores and recommendations for construction management positions.");
            list.add(mapEntity);
            Map<String, String> mapEntityOne = new HashMap<>();
            mapEntityOne.put("role", "user");
            mapEntityOne.put("content", "Position: Construction Labourer" +
                    "\\nCandidate: " + cvInfoDto.getName() +
                    "\\nResume Summary: " + JSONUtil.toJsonStr(cvInfoDto.getAbout()) +
                    "\\nSkills: " + JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()) +
                    "\\nExperience: " + JSONUtil.toJsonStr(cvInfoDto.getExperience()) +
                    "\\nEducation: " + JSONUtil.toJsonStr(cvInfoDto.getEducation()) +
                    "\\nCertifications: " + JSONUtil.toJsonStr(cvInfoDto.getSkillsTools()));
            list.add(mapEntityOne);
            String promptText = JSONUtil.toJsonStr(list);
            resultMsg = chatGPTClient.handleAiChat(promptText, "CV");
            log.info("返回简历评分数据:{}", resultMsg);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultMsg;
    }


    public static void main(String[] args) {
        String str = "Score: 4.8/5\n" +
                "Recommendation: Highly recommended candidate - strong match for the role\n" +
                "Strengths: Extensive relevant experience, Professional certifications, Strong skill set alignment\n" +
                "Concerns: -";

        String[] strs = str.split("\n");
        System.out.println(strs[0].replaceAll("Score:", "").trim().split("/")[0]);
    }

    /**
     * 处理分析附件返回对应的json 内容
     *
     * @return
     */
    private String handleAnalyzedAttachment(String fileUrl, String fileSuffix) {
        log.info("开始处理附件,对附件进行解析");
        try {
            InputStream inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(MinioBucketNameEnum.CV.getCode())
                            .object(fileUrl)
                            .build());
            String contents = FileContentUtil.readFileContent(inputStream, fileSuffix);
            String resultStr = aiCommonToolsService.handleAnalyzedAttachment(contents);
            log.info("返回的分析附件结果数据为:{}", resultStr);
            return resultStr;
        } catch (Exception e) {
        }
        return "";
    }

    /**
     * 创建简历附件信息
     *
     * @param connect 简历内容
     */
    private HotakeSysFile createCvFile(String connect) {

        try {
            String markdown = aiCommonToolsService.handleGenerateMarkdown(connect);
            markdown = markdown.replaceAll("markdown", "");
            String html = MarkdownUtil.markdownToHtml(markdown);
            // 可注入 CSS
            html = """
                    <html>
                    <head>
                        <style>
                            body { font-family: SimSun; }
                            h1 { color: #2c3e50; }
                        </style>
                    </head>
                    <body>
                    """ + html + """
                    </body>
                    </html>
                    """;
            //生成PDF文件
            String resultFileName = SecurityUtils.getUsername() + "_" + System.currentTimeMillis() + ".pdf";
            String resultPathUrl = RuoYiConfig.getProfile() + SYSTEM_DIR + resultFileName;
            HtmlToPdfUtil.htmlToPdf(html, resultPathUrl);
            //上传到minio中
            File pdf = new File(resultPathUrl);
            MultipartFile multipartFile =
                    MultipartFileUtil.fileToMultipartFile(pdf);
            HotakeSysFileVo fileVo = new HotakeSysFileVo();
            fileVo.setMinioBucketName("cv-fs");
            HotakeSysFile sysFile = sysFileService.insertHotakeSysFile(multipartFile, fileVo);
            return sysFile;
        } catch (Exception e) {
            throw new ServiceException("Resume creation exception, please contact the administrator");
        }
    }

}
