package com.ruoyi.cms.service.impl;

import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cms.domain.*;
import com.ruoyi.cms.domain.vo.CompetitivenessResponse;
import com.ruoyi.cms.domain.vo.RadarChart;
import com.ruoyi.cms.mapper.AppUserMapper;
import com.ruoyi.cms.mapper.JobApplyMapper;
import com.ruoyi.cms.mapper.JobMapper;
import com.ruoyi.cms.service.IBussinessDictTypeService;
import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SiteSecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import com.ruoyi.cms.mapper.JobCollectionMapper;
import com.ruoyi.cms.service.IJobCollectionService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 用户岗位收藏Service业务层处理
 *
 * @author lishundong
 * @date 2024-09-03
 */
@Service
public class JobCollectionServiceImpl extends ServiceImpl<JobCollectionMapper,JobCollection> implements IJobCollectionService
{
    @Autowired
    private JobCollectionMapper jobCollectionMapper;
    @Autowired
    private JobApplyMapper jobApplyMapper;
    @Autowired
    private AppUserMapper appUserMapper;
    @Autowired
    private JobMapper jobMapper;
    @Autowired
    private IBussinessDictTypeService iBussinessDictTypeService;
    /**
     * 查询用户岗位收藏
     *
     * @param id 用户岗位收藏主键
     * @return 用户岗位收藏
     */
    @Override
    public JobCollection selectJobCollectionById(Long id)
    {
        return jobCollectionMapper.selectById(id);
    }

    /**
     * 查询用户岗位收藏列表
     *
     * @param jobCollection 用户岗位收藏
     * @return 用户岗位收藏
     */
    @Override
    public List<JobCollection> selectJobCollectionList(JobCollection jobCollection)
    {
        return jobCollectionMapper.selectJobCollectionList(jobCollection);
    }

    /**
     * 新增用户岗位收藏
     *
     * @param jobCollection 用户岗位收藏
     * @return 结果
     */
    @Override
    public int insertJobCollection(JobCollection jobCollection)
    {
        return jobCollectionMapper.insert(jobCollection);
    }

    /**
     * 修改用户岗位收藏
     *
     * @param jobCollection 用户岗位收藏
     * @return 结果
     */
    @Override
    public int updateJobCollection(JobCollection jobCollection)
    {
        return jobCollectionMapper.updateById(jobCollection);
    }

    /**
     * 批量删除用户岗位收藏
     *
     * @param ids 需要删除的用户岗位收藏主键
     * @return 结果
     */
    @Override
    public int deleteJobCollectionByIds(Long[] ids)
    {
        return jobCollectionMapper.deleteBatchIds(Arrays.asList(ids));
    }
    /**
     * 用户收藏岗位
     */
    @Override
    @Transactional
    public int jobCollection(Long jobId) {
        Long userId = SiteSecurityUtils.getUserId();
        List<JobCollection> jobCollections = jobCollectionMapper.selectList(Wrappers.<JobCollection>lambdaQuery().eq(JobCollection::getJobId, jobId).eq(JobCollection::getUserId, userId));
        if(jobCollections.size()>0){
            jobCollectionMapper.deleteBatchIds(jobCollections.stream().map(JobCollection::getId).collect(Collectors.toList()));
        }
        JobCollection jobCollection = new JobCollection();
        jobCollection.setJobId(jobId);
        jobCollection.setUserId(userId);
        jobCollectionMapper.insert(jobCollection);
        return 1;
    }
    /**
     * 用户取消收藏岗位
     */
    @Override
    public int cancel(Long jobId) {
        Long userId = SiteSecurityUtils.getUserId();
        List<JobCollection> jobCollections = jobCollectionMapper.selectList(Wrappers.<JobCollection>lambdaQuery().eq(JobCollection::getJobId, jobId).eq(JobCollection::getUserId, userId));
        if(jobCollections.size()>0){
            jobCollectionMapper.deleteBatchIds(jobCollections.stream().map(JobCollection::getId).collect(Collectors.toList()));
        }
        return 1;
    }

    @Override
    public int apply(Long jobId) {
        Long userId = SiteSecurityUtils.getUserId();
        JobApply jobApply = new JobApply();
        jobApply.setJobId(jobId);
        jobApply.setUserId(userId);
        //todo 计算匹配度
        jobApply.setMatchingDegree(1L);
        List<JobApply> jobApplies = jobApplyMapper.selectList(Wrappers.<JobApply>lambdaQuery().eq(JobApply::getJobId, jobId).eq(JobApply::getUserId, userId));
        if(jobApplies.size()>0){
            List<Long> ids = jobApplies.stream().map(JobApply::getId).collect(Collectors.toList());
            jobApplyMapper.deleteBatchIds(ids);
        }
        jobApplyMapper.insert(jobApply);
        return 1;
    }

    @Override
    public List<Job> collectionJob() {
        List<Job> jobs = jobCollectionMapper.collectionJob(SiteSecurityUtils.getUserId());
        return jobs;
    }

    @Override
    @Transactional
    public int pcJobCollection(JobCollection collection) {
        List<JobCollection> jobCollections = jobCollectionMapper.selectList(Wrappers.<JobCollection>lambdaQuery().eq(JobCollection::getJobId, collection.getJobId()).eq(JobCollection::getUserId, collection.getUserId()));
        if(jobCollections.size()>0){
            jobCollectionMapper.deleteBatchIds(jobCollections.stream().map(JobCollection::getId).collect(Collectors.toList()));
        }
        JobCollection jobCollection = new JobCollection();
        jobCollection.setJobId(collection.getJobId());
        jobCollection.setUserId(collection.getUserId());
        jobCollectionMapper.insert(jobCollection);
        return 1;
    }

    @Override
    public int pcCancel(JobCollection collection) {
        List<JobCollection> jobCollections = jobCollectionMapper.selectList(Wrappers.<JobCollection>lambdaQuery().eq(JobCollection::getJobId, collection.getJobId()).eq(JobCollection::getUserId, collection.getUserId()));
        if(jobCollections.size()>0){
            jobCollectionMapper.deleteBatchIds(jobCollections.stream().map(JobCollection::getId).collect(Collectors.toList()));
        }
        return 1;
    }

    @Override
    public CompetitivenessResponse competitiveness(Long jobId) {
        // 查询岗位信息
        Job job = jobMapper.selectById(jobId);
        if (job == null) {
            throw new RuntimeException("岗位不存在");
        }

        // 获取所有申请该岗位的用户
        List<AppUser> appUsers = appUserMapper.selectByJobId(jobId);
        Long applyCount = (long) appUsers.size();

        if (appUsers.isEmpty()) {
            // 没有人申请，返回默认值或0
            CompetitivenessResponse emptyResponse = new CompetitivenessResponse();
            emptyResponse.setTotalApplicants(0);
            emptyResponse.setMatchScore(0);
            emptyResponse.setRank(0);
            emptyResponse.setPercentile(0);
            RadarChart radarChart = new RadarChart();
            emptyResponse.setRadarChart(radarChart);
            return emptyResponse;
        }

        // ================== 数据字典映射（用于排序比较）==================
        // 假设你有字典工具类，如 DictUtils.getSort("education", value) 返回排序值
        // 这里我们用 Map 模拟字典排序（越小要求越低）
        // 获取字典数据
        List<BussinessDictData> educationDict = iBussinessDictTypeService.selectDictDataByType("education");
        List<BussinessDictData> experienceDict = iBussinessDictTypeService.selectDictDataByType("experience");

        // 构建学历排序映射：dictLabel -> dictSort（越小要求越低）
        Map<String, Integer> educationRank = educationDict.stream()
                .collect(Collectors.toMap(
                        BussinessDictData::getDictLabel,
                        data -> Math.toIntExact(data.getDictSort()),
                        (a, b) -> a // 若有重复 key，保留第一个
                ));

        Map<String, Integer> experienceRank = experienceDict.stream()
                .collect(Collectors.toMap(
                        BussinessDictData::getDictLabel,
                        data -> Math.toIntExact(data.getDictSort()),
                        (a, b) -> a
                ));

        // ================== 提取岗位要求 ==================
        Integer jobEducationRank = educationRank.getOrDefault(job.getEducation(), 999);
        Integer jobExperienceRank = experienceRank.getOrDefault(job.getExperience(), 999);
        Integer jobMinSalary = job.getMinSalary() != null ? job.getMinSalary().intValue() : 0;
        String jobLocation = job.getJobLocation();

        // ================== 聚合用户数据用于分析 ==================
        List<UserCompetitiveness> userScores = new ArrayList<>();

        for (AppUser user : appUsers) {
            int matchScore = 0;
            int totalFactors = 6; // 年龄、经验、学历、技能（暂用期望岗位匹配）、薪资、地点

            // 1. 学历匹配（越接近越好）
            Integer userEduRank = educationRank.getOrDefault(user.getEducation(), 999);
            if (userEduRank <= jobEducationRank) {
                matchScore += 1; // 达标
            } else if (userEduRank == jobEducationRank + 1) {
                matchScore += 0.5; // 略高也算匹配
            }

            // 2. 经验匹配
            Integer userExpRank = experienceRank.getOrDefault(user.getExperience(), 999);
            if (userExpRank >= jobExperienceRank) {
                matchScore += 1; // 满足经验要求
            }

            // 3. 薪资匹配（用户期望 <= 岗位最大薪资，且不低于最小太多）
            Integer userMinSalary = parseSalary(user.getSalaryMin());
            if (userMinSalary != null && userMinSalary <= job.getMaxSalary()) {
                if (userMinSalary >= job.getMinSalary()) {
                    matchScore += 1;
                } else if (userMinSalary >= job.getMinSalary() * 0.8) {
                    matchScore += 0.5;
                }
            }

            // 4. 地点匹配
            if (user.getArea() != null) {
                if(user.getArea().contains(jobLocation) || jobLocation.contains(user.getArea())){
                    matchScore += 1;
                }
            }

            // 5. 年龄估算（从生日计算）
            int userAge = getUserAge(DateUtils.stringToDateWithYmd(user.getBirthDate(),DateUtils.YYYY_MM_DD));
            // 假设最佳年龄区间为 22-35，越接近越匹配
            if (userAge >= 22 && userAge <= 35) {
                matchScore += 1;
            } else if (userAge >= 18 && userAge <= 45) {
                matchScore += 0.5;
            }

            // 6. 技能/岗位匹配（简化：期望岗位是否包含该岗位关键词）
            boolean jobMatch = user.getJobTitle() != null &&
                    user.getJobTitle().stream().anyMatch(title -> title.contains(job.getJobTitle()) || job.getJobTitle().contains(title));
            if (jobMatch) {
                matchScore += 1;
            }

            // 匹配度：0-6 → 映射为 0-100 分
            int finalScore = (int) Math.round((matchScore / (double) totalFactors) * 100);
            userScores.add(new UserCompetitiveness(user, finalScore));
        }

        // 按匹配度降序
        userScores.sort((a, b) -> Integer.compare(b.getScore(), a.getScore()));

        // ================== 计算雷达图数据（取平均值）==================
        RadarChart radarChart = new RadarChart();

        double avgAgeScore = userScores.stream().mapToInt(u -> getAgeScore(DateUtils.stringToDateWithYmd(u.getUser().getBirthDate(),DateUtils.YYYY_MM_DD))).average().orElse(0);
        double avgExperienceScore = userScores.stream().mapToInt(u -> getExperienceScore(u.getUser().getExperience(), job.getExperience(), experienceRank)).average().orElse(0);
        double avgEducationScore = userScores.stream().mapToInt(u -> getEducationScore(u.getUser().getEducation(), job.getEducation(), educationRank)).average().orElse(0);
        double avgSkillScore = userScores.stream().mapToInt(u -> getSkillScore(u.getUser(), job)).average().orElse(0);
        double avgSalaryScore = userScores.stream().mapToInt(u -> getSalaryScore(u.getUser(), job)).average().orElse(0);
        double avgLocationScore = userScores.stream().mapToInt(u -> getLocationScore(u.getUser(), job)).average().orElse(0);

        radarChart.setAge((int) avgAgeScore);
        radarChart.setExperience((int) avgExperienceScore);
        radarChart.setEducation((int) avgEducationScore);
        radarChart.setSkill((int) avgSkillScore);
        radarChart.setSalary((int) avgSalaryScore);
        radarChart.setLocation((int) avgLocationScore);

        // ================== 返回响应 ==================
        CompetitivenessResponse response = new CompetitivenessResponse();
        response.setTotalApplicants(Math.toIntExact(applyCount));

        // Top 用户的匹配分
        int topMatchScore = userScores.get(0).getScore();
        response.setMatchScore(topMatchScore);

        // 排名（Top1）
        response.setRank(1);

        // 百分位：top用户超过多少人？（100%）
        response.setPercentile(100);

        response.setRadarChart(radarChart);

        return response;
    }
    private int getUserAge(Date birthDate) {
        if (birthDate == null) return 0;
        try {
            LocalDate birth = birthDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            return Period.between(birth, LocalDate.now()).getYears();
        } catch (Exception e) {
            return 0;
        }
    }
    private int getEducationScore(String userEdu, String jobEdu, Map<String, Integer> rankMap) {
        if (userEdu == null || jobEdu == null) return 60;
        Integer u = rankMap.getOrDefault(userEdu, 999);
        Integer j = rankMap.getOrDefault(jobEdu, 999);
        if (u <= j) return 90;
        if (u == j + 1) return 75;
        return 60;
    }
    private int getExperienceScore(String userExp, String jobExp, Map<String, Integer> rankMap) {
        if (userExp == null || jobExp == null) return 60;
        Integer u = rankMap.getOrDefault(userExp, 999);
        Integer j = rankMap.getOrDefault(jobExp, 999);
        if (u >= j) return 90;
        if (u >= j - 1) return 75; // 容忍略低一年
        return 60;
    }
    private int getSalaryScore(AppUser user, Job job) {
        Integer min = parseSalary(user.getSalaryMin());
        if (min == null) return 60;
        if (job.getMinSalary() == null || job.getMaxSalary() == null) return 60;

        long jobMin = job.getMinSalary();
        long jobMax = job.getMaxSalary();

        if (min >= jobMin && min <= jobMax) return 90;
        if (min >= jobMin * 0.8 && min <= jobMax * 1.2) return 75;
        return 60;
    }
    private int getLocationScore(AppUser user, Job job) {
        String area = user.getArea();
        String loc = job.getJobLocation();
        if (area != null && (area.contains(loc) || loc.contains(area))) return 90;
        return 60;
    }
    private int getSkillScore(AppUser user, Job job) {
        String jobTitle = job.getJobTitle();
        List<String> userTitles = user.getJobTitle();
        if (jobTitle == null || userTitles == null || userTitles.isEmpty()) return 60;

        boolean match = userTitles.stream()
                .anyMatch(title -> title != null &&
                        (title.contains(jobTitle) || jobTitle.contains(title)));
        return match ? 90 : 60;
    }
    private Integer parseSalary(String salaryStr) {
        if (salaryStr == null || salaryStr.trim().isEmpty()) return null;
        try {
            // 提取第一个连续数字
            String numberStr = salaryStr.replaceAll("[^0-9]", "");
            return numberStr.isEmpty() ? null : Integer.parseInt(numberStr);
        } catch (Exception e) {
            return null;
        }
    }
    private int getAgeScore(Date birthDate) {
        int age = getUserAge(birthDate);
        if (age == 0) return 60; // 无法获取年龄，默认低分
        if (age >= 22 && age <= 35) return 90;
        if (age >= 18 && age <= 45) return 75;
        return 60;
    }
    private static class UserCompetitiveness {
        private final AppUser user;
        private final int score;

        public UserCompetitiveness(AppUser user, int score) {
            this.user = user;
            this.score = score;
        }

        public AppUser getUser() {
            return user;
        }

        public int getScore() {
            return score;
        }
    }

    @Override
    public List<Job> selectJobCollectionListJob(JobCollection jobCollection) {
        return jobCollectionMapper.selectJobCollectionListJob(jobCollection);
    }
}
