package com.ruoyi.cms.service.impl;

import com.alibaba.fastjson.JSON;
import com.ruoyi.cms.domain.vo.CompanyVo;
import com.ruoyi.cms.service.ICompanyService;
import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.cms.domain.ESJobDocument;
import com.ruoyi.cms.domain.Job;
import com.ruoyi.cms.domain.query.ESJobSearch;
import com.ruoyi.cms.mapper.es.EsJobDocumentMapper;
import com.ruoyi.cms.mapper.JobMapper;
import com.ruoyi.cms.service.IESJobSearchService;
import com.ruoyi.cms.util.ListUtil;
import com.ruoyi.cms.util.StringUtil;
import com.ruoyi.common.core.domain.entity.Company;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.SiteSecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.dromara.easyes.core.biz.EsPageInfo;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.dromara.easyes.core.conditions.update.LambdaEsUpdateWrapper;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 实体模板Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class ESJobSearchImpl implements IESJobSearchService
{
    @Autowired
    private EsJobDocumentMapper esJobDocumentMapper;

    @Autowired
    private JobMapper jobMapper;

    @Autowired
    private AppUserServiceImpl appUserService;
    @Autowired
    private ICompanyService iCompanyService;

    @Autowired
    private BussinessDictDataServiceImpl bussinessDictDataServicel;
    Logger logger = LoggerFactory.getLogger(JobServiceImpl.class);
    /**
     * 项目启动时，初始化索引及数据
     */
//   @PostConstruct
    public void init()
    {
        resetTextCache();
    }

    @Override
    public void checkEsAndFix() {
        try {
            esJobDocumentMapper.getIndex();
        }catch (Exception e){
            logger.warn("es索引丢失，正在重新刷新");
            this.init();
        }
    }

    /**
     * 重置全文检索数据
     */
    //todo 定时任务
    @Override
    public void resetTextCache() {
        logger.info("正在重新刷新es");
        // 删除并重新创建索引
        esJobDocumentMapper.deleteIndex("job_document");
        esJobDocumentMapper.createIndex();

        // 分批次处理数据
        int batchSize = 1000; // 每批次处理的数据量
        int offset = 0; // 起始偏移量
        boolean hasMoreData = true; // 是否还有更多数据

        while (hasMoreData) {
            // 分页查询数据
            Map<String, Object> params = new HashMap<>();
            params.put("batchSize", batchSize);
            params.put("offset", offset*batchSize);
            List<Job> jobList = jobMapper.selectAllJob(params);

            if (jobList.isEmpty()) {
                hasMoreData = false; // 没有更多数据，退出循环
            } else {
                // 转换数据并插入到 Elasticsearch
                List<ESJobDocument> esJobDocumentList = new ArrayList<>();
                for (Job job : jobList) {
                    ESJobDocument esJobDocument = new ESJobDocument();
                    BeanUtils.copyBeanProp(esJobDocument, job);
                    CompanyVo vo=job.getCompanyVo();
                    esJobDocument.setCompanyVoJson(JSON.toJSONString(vo));
                    esJobDocument.setAppJobUrl("https://qd.zhaopinzao8dian.com/app#/packageA/pages/post/post?jobId="+ Base64.getEncoder().encodeToString(String.valueOf(job.getJobId()).getBytes()));
                    if(!StringUtil.isEmptyOrNull(job.getScale())){
                        esJobDocument.setScale(Integer.valueOf(job.getScale()));
                    }else {
                        esJobDocument.setScale(8);
                    }
                    if(!StringUtil.isEmptyOrNull(job.getExperience())){
                        esJobDocument.setExperience_int(Integer.valueOf(job.getExperience()));
                    }else {
                        esJobDocument.setExperience("0");
                        esJobDocument.setEducation_int(0);
                    }
                    if(!StringUtil.isEmptyOrNull(job.getEducation())){
                        esJobDocument.setEducation_int(Integer.valueOf(job.getEducation()));
                    }else {
                        esJobDocument.setEducation("-1");
                        esJobDocument.setExperience_int(-1);
                    }
                    if (esJobDocument.getLatitude() != null) {
                        esJobDocument.setLatAndLon(esJobDocument.getLatitude().toString() + "," + esJobDocument.getLongitude().toString());
                    }
                    if(StringUtil.isEmptyOrNull(job.getCompanyNature())){
                        esJobDocument.setCompanyNature("6");
                    }
                    esJobDocumentList.add(esJobDocument);
                }

                // 批量插入当前批次的数据
                esJobDocumentMapper.insertBatch(esJobDocumentList);

                // 更新偏移量
                offset = offset+1;
            }
        }
    }

    @Override
    public List<ESJobDocument> selectTextListExceptJobId(ESJobSearch esJobSearch, List<Long> jobIds) {

        ESJobSearch newSearch = new ESJobSearch();
        BeanUtils.copyProperties(esJobSearch,newSearch);
        //查询
        if(SiteSecurityUtils.isLogin()){
            AppUser appUser = appUserService.selectAppUserByUserId(SiteSecurityUtils.getUserId());
            if(!ListUtil.isEmptyOrNull(appUser.getJobTitle())){
                List<String> jobTitle = appUser.getJobTitle();
                newSearch.setJobTitle(String.join(",", jobTitle));
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getJobTitle())){
                newSearch.setJobTitle(esJobSearch.getJobTitle());
            }
            if(!StringUtil.isEmptyOrNull(appUser.getEducation())){
                newSearch.setEducation(appUser.getEducation());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getEducation())){
                newSearch.setEducation(esJobSearch.getEducation());
            }

            if(!StringUtil.isEmptyOrNull(appUser.getArea())){
                newSearch.setArea(appUser.getArea());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getArea())){
                newSearch.setArea(esJobSearch.getArea());
            }
            if(!StringUtil.isEmptyOrNull(appUser.getWorkExperience())){
                newSearch.setExperience(appUser.getWorkExperience());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getExperience())){
                newSearch.setExperience(esJobSearch.getExperience());
            }
            if(!StringUtil.isEmptyOrNull(appUser.getSalaryMax())){
                newSearch.setMaxSalary(Long.valueOf(appUser.getSalaryMax()));
            }
            if(!StringUtil.isEmptyOrNull(appUser.getSalaryMin())){
                newSearch.setMinSalary(Long.valueOf(appUser.getSalaryMin()));
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getJobType())){
                newSearch.setJobType(esJobSearch.getJobType());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getType())){
                newSearch.setType(esJobSearch.getType());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getDescription())){
                newSearch.setDescription(esJobSearch.getDescription());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getCompanyNature())){
                newSearch.setCompanyNature(esJobSearch.getCompanyNature());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getCode())){
                newSearch.setCode(esJobSearch.getCode());
            }
        }

        LambdaEsQueryWrapper<ESJobDocument> wrapper = getWrapper(newSearch,jobIds);

        //todo 暂时
        wrapper.limit(esJobSearch.getPageSize());
        List<ESJobDocument> esJobDocuments = esJobDocumentMapper.selectList(wrapper);

        if (esJobDocuments.size() < esJobSearch.getPageSize()) {
            // 定义要逐步放宽的搜索条件字段
            List<Runnable> relaxConditions = new ArrayList<>();
            relaxConditions.add(() -> newSearch.setArea(null));
            relaxConditions.add(() -> newSearch.setExperience(null));
            relaxConditions.add(() -> newSearch.setMaxSalary(null));
            relaxConditions.add(() -> newSearch.setMinSalary(null));
            relaxConditions.add(() -> newSearch.setEducation(null));
            relaxConditions.add(()-> newSearch.setJobTitle(null));
            // 保存所有查询到的文档
            List<ESJobDocument> allDocuments = new ArrayList<>(esJobDocuments);

            // 记录已经放宽的条件数量
            int relaxedConditions = 0;

            // 继续放宽条件直到满足分页或所有条件都已放宽
            while (allDocuments.size() < esJobSearch.getPageSize()
                    && relaxedConditions < relaxConditions.size()) {
                // 放宽下一个条件
                relaxConditions.get(relaxedConditions).run();
                relaxedConditions++;

                // 查询新增的文档（不包含之前已经查询到的）
                wrapper = getWrapper(newSearch, jobIds);
                wrapper.limit(esJobSearch.getPageSize() - allDocuments.size());
                if (!allDocuments.isEmpty()) {
                    // 排除已经查询到的文档ID
                    Set<String> existingIds = allDocuments.stream()
                            .map(ESJobDocument::getId)
                            .collect(Collectors.toSet());
                    wrapper.not().in(ESJobDocument::getId, existingIds);
                }

                List<ESJobDocument> newDocuments = esJobDocumentMapper.selectList(wrapper);
                allDocuments.addAll(newDocuments);
            }

            // 如果总数超过分页大小，截取所需数量
            if (allDocuments.size() > esJobSearch.getPageSize()) {
                esJobDocuments = allDocuments.subList(0, esJobSearch.getPageSize());
            } else {
                esJobDocuments = allDocuments;
            }
        }

        return esJobDocuments;
    }


    /**
     * 新增全文检索数据
     */
    @Override
    public Integer addESJobDocument(ESJobDocument esJobDocument)
    {
        return esJobDocumentMapper.insert(esJobDocument);
    }

    /**
     * 修改全文检索数据
     */
    @Override
    public Integer updateESJobDocument(ESJobDocument esJobDocument)
    {

        LambdaEsUpdateWrapper<ESJobDocument> wrapper = new LambdaEsUpdateWrapper<>();
        wrapper.eq(ESJobDocument::getJobId, esJobDocument.getJobId());
        return esJobDocumentMapper.update(esJobDocument, wrapper);
    }

    /**
     * 根据ID查询全文检索数据
     */
    @Override
    public ESJobDocument getESJobDocument(Long jobId)
    {
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<ESJobDocument>();
        wrapper.eq(ESJobDocument::getJobId, jobId);
        return esJobDocumentMapper.selectOne(wrapper);
    }

    /**
     * 根据ID删除全文检索数据
     */
    @Override
    public void deleteESJobDocument(String ids)
    {
        for (Long jobId : Convert.toLongArray(ids))
        {
            LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<ESJobDocument>();
            wrapper.eq(ESJobDocument::getJobId, jobId);
            esJobDocumentMapper.delete(wrapper);
        }
    }

    @Override
    public EsPageInfo<ESJobDocument> nearJob(ESJobSearch jobQuery) {
        Integer pageNum = jobQuery.getCurrent();
        Integer pageSize = jobQuery.getPageSize();
        LambdaEsQueryWrapper<ESJobDocument> wrapper = getWrapper(jobQuery,null);
        EsPageInfo<ESJobDocument> esJobDocumentEsPageInfo = esJobDocumentMapper.pageQuery(wrapper, pageNum, pageSize);
        return esJobDocumentEsPageInfo;
    }

    @Override
    public EsPageInfo<ESJobDocument> countyJobList(ESJobSearch jobQuery) {
        Integer pageNum = jobQuery.getCurrent();
        Integer pageSize = jobQuery.getPageSize();
        LambdaEsQueryWrapper<ESJobDocument> wrapper = getWrapper(jobQuery, null);
        if(jobQuery.getCountyIds()!=null){
            wrapper.and(x->x.in(ESJobDocument::getJobLocationAreaCode,jobQuery.getCountyIds()));
        }
        EsPageInfo<ESJobDocument> esJobDocumentEsPageInfo = esJobDocumentMapper.pageQuery(wrapper, pageNum, pageSize);
        return esJobDocumentEsPageInfo;
    }

    @Override
    public EsPageInfo<ESJobDocument> subway(ESJobSearch jobQuery) {
        Integer pageNum = jobQuery.getCurrent();
        Integer pageSize = jobQuery.getPageSize();
        LambdaEsQueryWrapper<ESJobDocument> wrapper = getWrapper(jobQuery,null);
        EsPageInfo<ESJobDocument> esJobDocumentEsPageInfo = esJobDocumentMapper.pageQuery(wrapper, pageNum, pageSize);
        return esJobDocumentEsPageInfo;
    }

    @Override
    public EsPageInfo<ESJobDocument> commercialArea(ESJobSearch jobQuery) {
        Integer pageNum = jobQuery.getCurrent();
        Integer pageSize = jobQuery.getPageSize();
        LambdaEsQueryWrapper<ESJobDocument> wrapper = getWrapper(jobQuery,null);
        if(jobQuery.getLongitude()!=null){
            wrapper.geoDistance(ESJobDocument::getLatAndLon,Double.valueOf(jobQuery.getRadius()), DistanceUnit.KILOMETERS,new GeoPoint(Double.parseDouble(jobQuery.getLatitude().toString()), Double.parseDouble(jobQuery.getLongitude().toString())));
        }
        EsPageInfo<ESJobDocument> esJobDocumentEsPageInfo = esJobDocumentMapper.pageQuery(wrapper, pageNum, pageSize);
        return esJobDocumentEsPageInfo;
    }

    @Override
    public List<ESJobDocument> littleVideo(ESJobSearch esJobSearch) {
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.eq(ESJobDocument::getIsExplain, 1);
        wrapper.limit(esJobSearch.getPageSize());
        return esJobDocumentMapper.selectList(wrapper);
    }

    @Override
    public void updateEs() {
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
        esJobDocumentMapper.selectList(wrapper).forEach(esJobDocument -> {
            esJobDocument.setPostingDate(new Date());
            this.updateESJobDocument(esJobDocument);
        });
    }

    @Override
    public List<ESJobDocument> littleVideoRandom(List<Long> cacheList, Integer count,String jobTitle) {
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.eq(ESJobDocument::getIsExplain, 1);
        if(!ListUtil.isListEmptyOrNull(cacheList)){
            wrapper.not().in(ESJobDocument::getJobId,cacheList);
        }
        if(count==null){
            count = 1;
        }
        if(StringUtil.isEmptyOrNull(jobTitle)){
            wrapper.or(a -> a.like(ESJobDocument::getJobTitle, jobTitle, 5.0f)
                    .or()
                    .like(ESJobDocument::getDescription, jobTitle, 1.0f)
            );
        }
        wrapper.limit(count);
        return esJobDocumentMapper.selectList(wrapper);
    }

    private LambdaEsQueryWrapper<ESJobDocument> getWrapper(ESJobSearch esJobSearch,List<Long> jobIds){

        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
        if(!StringUtil.isEmptyOrNull(esJobSearch.getJobTitle())){
            for (String keyWord:esJobSearch.getJobTitle().split(",")) {
                wrapper.and(a -> a.match(ESJobDocument::getJobTitle, keyWord, 5.0f)
                );
            }

        }

        if(esJobSearch.getLongitude()!=null){
            wrapper.geoDistance(ESJobDocument::getLatAndLon,Double.valueOf(esJobSearch.getRadius()), DistanceUnit.KILOMETERS,new GeoPoint(Double.parseDouble(esJobSearch.getLatitude().toString()), Double.parseDouble(esJobSearch.getLongitude().toString())));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getEducation())){
            Integer maxValue = StringUtil.findMaxValue(esJobSearch.getEducation());
            wrapper.and(x->x.le(ESJobDocument::getEducation_int,maxValue));
        }
        if(Objects.nonNull(esJobSearch.getMaxSalary())){
            wrapper.and(x->x.le(ESJobDocument::getMaxSalary,esJobSearch.getMaxSalary()));
        }
        if(Objects.nonNull(esJobSearch.getMinSalary())){
            wrapper.and(x->x.ge(ESJobDocument::getMinSalary,esJobSearch.getMinSalary()));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getExperience())){
            Integer maxValue = StringUtil.findMaxValue(esJobSearch.getExperience());
            wrapper.and(x->x.le(ESJobDocument::getExperience_int,maxValue));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getJobCategory())){
            wrapper.and(x->x.eq(ESJobDocument::getJobCategory,esJobSearch.getJobCategory()));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getScale())){
            Integer maxValue = StringUtil.findMaxValue(esJobSearch.getScale());
            wrapper.and(x->x.le(ESJobDocument::getScale,maxValue));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getArea())){
            List<Integer> integers = StringUtil.convertStringToIntegerList(esJobSearch.getArea());
            wrapper.and(x->x.in(ESJobDocument::getJobLocationAreaCode,integers));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getJobType())){
            wrapper.and(x->x.eq(ESJobDocument::getJobType,esJobSearch.getJobType()));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getType())){
            wrapper.and(x->x.eq(ESJobDocument::getType,esJobSearch.getType()));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getDescription())){
            wrapper.and(x->x.like(ESJobDocument::getDescription,esJobSearch.getDescription()));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getCompanyNature())){
            wrapper.and(x->x.eq(ESJobDocument::getCompanyNature,esJobSearch.getCompanyNature()));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getCode())){
            wrapper.and(x->x.eq(ESJobDocument::getCode,esJobSearch.getCode()));
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getType())){
            wrapper.and(x->x.eq(ESJobDocument::getType,esJobSearch.getType()));
        }
        if(esJobSearch.getJobId()!=null){
            wrapper.and(x->x.eq(ESJobDocument::getJobId,esJobSearch.getJobId()));
        }
        if(Objects.nonNull(esJobSearch.getOrder())){
            if(esJobSearch.getOrder()==1){
                wrapper.orderByDesc(ESJobDocument::getIsHot);
            }
            if(esJobSearch.getOrder()==2){
                wrapper.orderByDesc(ESJobDocument::getPostingDate);
            }
            if(esJobSearch.getOrder()==3){
                wrapper.orderByDesc(ESJobDocument::getMaxSalary);
            }
        }
        //企业用户排除es去除jobIds
        boolean needExclude = true;
        needExclude = !StringUtil.IS_COMPANY_USER.equals(esJobSearch.getUserType());
        if(needExclude && !ListUtil.isListEmptyOrNull(jobIds)){
            wrapper.not().in(ESJobDocument::getJobId, jobIds);
        }
        return wrapper;
    }

    //todo 存储用户搜索
    @Override
    public EsPageInfo<ESJobDocument> appList(ESJobSearch jobQuery) {
        Integer pageNum = jobQuery.getCurrent();
        Integer pageSize = jobQuery.getPageSize();
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
//        if(SiteSecurityUtils.isLogin()){
//            AppUser appUser = appUserService.selectAppUserByUserId(SiteSecurityUtils.getUserId());
//            if(!ListUtil.isEmptyOrNull(appUser.getJobTitle())){
//                List<String> jobTitle = appUser.getJobTitle();
//                jobQuery.setJobTitle(String.join(",", jobTitle));
//            }
//        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getJobTitle())){
            wrapper.and(a->a.match(ESJobDocument::getJobTitle,jobQuery.getJobTitle(),5.0f)
                    .or()
                    .match(ESJobDocument::getDescription,jobQuery.getJobTitle(),1.0f));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getEducation())){
            wrapper.and(a->a.le(ESJobDocument::getEducation,jobQuery.getEducation()));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getArea())){
            List<Integer> integers = StringUtil.convertStringToIntegerList(jobQuery.getArea());
            wrapper.and(x->x.in(ESJobDocument::getJobLocationAreaCode,integers));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getExperience())){
            wrapper.and(a->a.le(ESJobDocument::getExperience,jobQuery.getExperience()));
        }
        if(Objects.nonNull(jobQuery.getMaxSalary())){
            wrapper.and(x->x.le(ESJobDocument::getMaxSalary,jobQuery.getMaxSalary()));
        }
        if(Objects.nonNull(jobQuery.getMinSalary())){
            wrapper.and(x->x.ge(ESJobDocument::getMinSalary,jobQuery.getMinSalary()));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getScaleDictCode())){
            wrapper.and(a->a.eq(ESJobDocument::getScaleDictCode,jobQuery.getScaleDictCode()));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getIndustry())){
            wrapper.and(a->a.eq(ESJobDocument::getIndustry,jobQuery.getIndustry()));
        }
        if(jobQuery.getLongitude()!=null){
            wrapper.geoDistance(ESJobDocument::getLatAndLon,Double.valueOf(jobQuery.getRadius()), DistanceUnit.KILOMETERS,new GeoPoint(Double.parseDouble(jobQuery.getLatitude().toString()), Double.parseDouble(jobQuery.getLongitude().toString())));
        }
        if(jobQuery.getJobLocationAreaCode()!=null){
            wrapper.and(a->a.eq(ESJobDocument::getJobLocationAreaCode,jobQuery.getJobLocationAreaCode()));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getScale())){
            wrapper.and(a->a.eq(ESJobDocument::getScale,jobQuery.getScale()));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getSearchValue())){
            wrapper.and(a->a.match(ESJobDocument::getDescription,jobQuery.getSearchValue(),4.0f));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getCompanyNature())){
            wrapper.and(a->a.eq(ESJobDocument::getCompanyNature,jobQuery.getCompanyNature()));
        }
        if(!StringUtil.isEmptyOrNull(jobQuery.getType())){
            wrapper.and(a->a.eq(ESJobDocument::getType,jobQuery.getType()));
        }
        if(Objects.nonNull(jobQuery.getOrder())){
            if (jobQuery.getOrder()==2){
                wrapper.orderByDesc(ESJobDocument::getPostingDate);
            }
            if (jobQuery.getOrder()==1){
                wrapper.orderByDesc(ESJobDocument::getIsHot);
                wrapper.orderByDesc(ESJobDocument::getApplyNum);
                wrapper.orderByDesc(ESJobDocument::getView);
            }
        }
        EsPageInfo<ESJobDocument> esJobDocumentEsPageInfo = esJobDocumentMapper.pageQuery(wrapper, pageNum, pageSize);
        return esJobDocumentEsPageInfo;
    }

    @Override
    public ESJobDocument selectById(Long jobId) {
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.eq(ESJobDocument::getJobId,jobId);
        return esJobDocumentMapper.selectOne(wrapper);
    }

    @Override
    public void fix() {
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.eq(ESJobDocument::getIsExplain,1);
        List<ESJobDocument> esJobDocuments = esJobDocumentMapper.selectList(wrapper);
        for (ESJobDocument esJobDocument : esJobDocuments) {
            Job job = new Job();
            BeanUtils.copyProperties(esJobDocument,job);
            job.setJobId(null);
            jobMapper.insert(job);
        }
    }

    @Override
    public void deleteJob(Long jobId) {
        LambdaEsQueryWrapper<ESJobDocument> lambdaEsQueryWrapper = new LambdaEsQueryWrapper();
        lambdaEsQueryWrapper.eq(ESJobDocument::getJobId,jobId);
        esJobDocumentMapper.delete(lambdaEsQueryWrapper);
    }

    @Override
    public void updateJob(Long jobId) {
        ESJobDocument esJobDocument = new ESJobDocument();
        Job job = jobMapper.selectById(jobId);
        if(job!=null){
            if(job.getCompanyId()!=null){
                Company company=iCompanyService.selectCompanyByCompanyId(job.getCompanyId());
                job.setCode(company.getCode());
            }
        }

        BeanUtils.copyBeanProp(esJobDocument, job);
        esJobDocument.setAppJobUrl("https://ks.zhaopinzao8dian.com/app#/packageA/pages/post/post?jobId="+ Base64.getEncoder().encodeToString(String.valueOf(job.getJobId()).getBytes()));
        if(!StringUtil.isEmptyOrNull(job.getScale())){
            esJobDocument.setScale(Integer.valueOf(job.getScale()));
        }else {
            esJobDocument.setScale(0);
        }
        if(!StringUtil.isEmptyOrNull(job.getExperience())){
            esJobDocument.setExperience_int(Integer.valueOf(job.getExperience()));
        }else {
            esJobDocument.setExperience("0");
            esJobDocument.setExperience_int(0);
        }
        if(!StringUtil.isEmptyOrNull(job.getEducation())){
            esJobDocument.setEducation_int(Integer.valueOf(job.getEducation()));
        }else {
            esJobDocument.setEducation("-1");
            esJobDocument.setEducation_int(-1);
        }
        if (esJobDocument.getLatitude() != null) {
            esJobDocument.setLatAndLon(esJobDocument.getLatitude().toString() + "," + esJobDocument.getLongitude().toString());
        }
        if(StringUtil.isEmptyOrNull(job.getCompanyNature())){
            esJobDocument.setCompanyNature("6");
        }
        LambdaEsQueryWrapper<ESJobDocument> lambdaEsQueryWrapper = new LambdaEsQueryWrapper();
        lambdaEsQueryWrapper.eq(ESJobDocument::getJobId,job.getJobId());
        esJobDocumentMapper.delete(lambdaEsQueryWrapper);
        esJobDocumentMapper.insert(esJobDocument);
    }

    public List<ESJobDocument> selectByIds(Long[] jobIds) {
        LambdaEsQueryWrapper<ESJobDocument> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.in(ESJobDocument::getJobId,jobIds);
        return esJobDocumentMapper.selectList(wrapper);
    }

    /**
     * pc端查询es
     * @param esJobSearch
     * @param jobIds
     * @param appUser
     * @return
     */
    @Override
    public List<ESJobDocument> selectSysTextListExceptJobId(ESJobSearch esJobSearch, List<Long> jobIds,AppUser appUser) {

        ESJobSearch newSearch = new ESJobSearch();
        BeanUtils.copyProperties(esJobSearch,newSearch);
        //查询
        if(appUser!=null){
            if(!ListUtil.isEmptyOrNull(appUser.getJobTitle())){
                List<String> jobTitle = appUser.getJobTitle();
                newSearch.setJobTitle(String.join(",", jobTitle));
            }
            if(!StringUtil.isEmptyOrNull(appUser.getEducation())){
                newSearch.setEducation(appUser.getEducation());
            }
            if(!StringUtil.isEmptyOrNull(appUser.getArea())){
                newSearch.setArea(appUser.getArea());
            }
            if(!StringUtil.isEmptyOrNull(appUser.getWorkExperience())){
                newSearch.setExperience(appUser.getWorkExperience());
            }
            if(!StringUtil.isEmptyOrNull(esJobSearch.getExperience())){
                newSearch.setExperience(esJobSearch.getExperience());
            }
            if(!StringUtil.isEmptyOrNull(appUser.getSalaryMax())){
                newSearch.setMaxSalary(Long.valueOf(appUser.getSalaryMax()));
            }
            if(!StringUtil.isEmptyOrNull(appUser.getSalaryMin())){
                newSearch.setMinSalary(Long.valueOf(appUser.getSalaryMin()));
            }
        }

        if(!StringUtil.isEmptyOrNull(esJobSearch.getArea())){
            newSearch.setArea(esJobSearch.getArea());
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getEducation())){
            newSearch.setEducation(esJobSearch.getEducation());
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getJobTitle())){
            newSearch.setJobTitle(esJobSearch.getJobTitle());
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getJobType())){
            newSearch.setJobType(esJobSearch.getJobType());
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getType())){
            newSearch.setType(esJobSearch.getType());
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getDescription())){
            newSearch.setDescription(esJobSearch.getDescription());
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getCompanyNature())){
            newSearch.setCompanyNature(esJobSearch.getCompanyNature());
        }
        if(!StringUtil.isEmptyOrNull(esJobSearch.getCode())){
            newSearch.setCode(esJobSearch.getCode());
        }

        LambdaEsQueryWrapper<ESJobDocument> wrapper = getWrapper(newSearch,jobIds);

        //todo 暂时
        wrapper.limit(esJobSearch.getPageSize());
        List<ESJobDocument> esJobDocuments = esJobDocumentMapper.selectList(wrapper);

        if (esJobDocuments.size() < esJobSearch.getPageSize()) {
            // 定义要逐步放宽的搜索条件字段
            List<Runnable> relaxConditions = new ArrayList<>();
            relaxConditions.add(() -> newSearch.setArea(null));
            relaxConditions.add(() -> newSearch.setExperience(null));
            relaxConditions.add(() -> newSearch.setMaxSalary(null));
            relaxConditions.add(() -> newSearch.setMinSalary(null));
            relaxConditions.add(() -> newSearch.setEducation(null));
            relaxConditions.add(()-> newSearch.setJobTitle(null));
            // 保存所有查询到的文档
            List<ESJobDocument> allDocuments = new ArrayList<>(esJobDocuments);

            // 记录已经放宽的条件数量
            int relaxedConditions = 0;

            // 继续放宽条件直到满足分页或所有条件都已放宽
            while (allDocuments.size() < esJobSearch.getPageSize()
                    && relaxedConditions < relaxConditions.size()) {
                // 放宽下一个条件
                relaxConditions.get(relaxedConditions).run();
                relaxedConditions++;

                // 查询新增的文档（不包含之前已经查询到的）
                wrapper = getWrapper(newSearch, jobIds);
                wrapper.limit(esJobSearch.getPageSize() - allDocuments.size());
                if (!allDocuments.isEmpty()) {
                    // 排除已经查询到的文档ID
                    Set<String> existingIds = allDocuments.stream()
                            .map(ESJobDocument::getId)
                            .collect(Collectors.toSet());
                    wrapper.not().in(ESJobDocument::getId, existingIds);
                }

                List<ESJobDocument> newDocuments = esJobDocumentMapper.selectList(wrapper);
                allDocuments.addAll(newDocuments);
            }

            // 如果总数超过分页大小，截取所需数量
            if (allDocuments.size() > esJobSearch.getPageSize()) {
                esJobDocuments = allDocuments.subList(0, esJobSearch.getPageSize());
            } else {
                esJobDocuments = allDocuments;
            }
        }

        return esJobDocuments;
    }
}
