package com.ruoyi.info.collection.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.CcdiStaffRecruitment;
import com.ruoyi.info.collection.domain.CcdiStaffRecruitmentWork;
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentQueryDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffRecruitmentWorkEditDTO;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentExcel;
import com.ruoyi.info.collection.domain.excel.CcdiStaffRecruitmentWorkExcel;
import com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentVO;
import com.ruoyi.info.collection.domain.vo.CcdiStaffRecruitmentWorkVO;
import com.ruoyi.info.collection.enums.AdmitStatus;
import com.ruoyi.info.collection.enums.RecruitType;
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentWorkMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffRecruitmentMapper;
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentImportService;
import com.ruoyi.info.collection.service.ICcdiStaffRecruitmentService;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 员工招聘信息 服务层处理
 *
 * @author ruoyi
 * @date 2025-02-05
 */
@Service
public class CcdiStaffRecruitmentServiceImpl implements ICcdiStaffRecruitmentService {

    @Resource
    private CcdiStaffRecruitmentMapper recruitmentMapper;

    @Resource
    private CcdiStaffRecruitmentWorkMapper recruitmentWorkMapper;

    @Resource
    private ICcdiStaffRecruitmentImportService recruitmentImportService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 查询招聘信息列表
     *
     * @param queryDTO 查询条件
     * @return 招聘信息VO集合
     */
    @Override
    public List<CcdiStaffRecruitmentVO> selectRecruitmentList(CcdiStaffRecruitmentQueryDTO queryDTO) {
        Page<CcdiStaffRecruitmentVO> page = new Page<>(1, Integer.MAX_VALUE);
        Page<CcdiStaffRecruitmentVO> resultPage = recruitmentMapper.selectRecruitmentPage(page, queryDTO);
        return resultPage.getRecords();
    }

    /**
     * 分页查询招聘信息列表
     *
     * @param page     分页对象
     * @param queryDTO 查询条件
     * @return 招聘信息VO分页结果
     */
    @Override
    public Page<CcdiStaffRecruitmentVO> selectRecruitmentPage(Page<CcdiStaffRecruitmentVO> page, CcdiStaffRecruitmentQueryDTO queryDTO) {
        Page<CcdiStaffRecruitmentVO> resultPage = recruitmentMapper.selectRecruitmentPage(page, queryDTO);

        // 设置录用状态描述
        resultPage.getRecords().forEach(vo ->
            vo.setAdmitStatusDesc(AdmitStatus.getDescByCode(vo.getAdmitStatus()))
        );

        return resultPage;
    }

    /**
     * 查询招聘信息列表（用于导出）
     *
     * @param queryDTO 查询条件
     * @return 招聘信息Excel实体集合
     */
    @Override
    public List<CcdiStaffRecruitmentExcel> selectRecruitmentListForExport(CcdiStaffRecruitmentQueryDTO queryDTO) {
        Page<CcdiStaffRecruitmentVO> page = new Page<>(1, Integer.MAX_VALUE);
        Page<CcdiStaffRecruitmentVO> resultPage = recruitmentMapper.selectRecruitmentPage(page, queryDTO);

        return resultPage.getRecords().stream().map(vo -> {
            CcdiStaffRecruitmentExcel excel = new CcdiStaffRecruitmentExcel();
            BeanUtils.copyProperties(vo, excel);
            return excel;
        }).toList();
    }

    /**
     * 查询招聘信息详情
     *
     * @param id 主键ID
     * @return 招聘信息VO
     */
    @Override
    public CcdiStaffRecruitmentVO selectRecruitmentById(Long id) {
        CcdiStaffRecruitmentVO vo = recruitmentMapper.selectRecruitmentById(id);
        if (vo != null) {
            vo.setAdmitStatusDesc(AdmitStatus.getDescByCode(vo.getAdmitStatus()));
            vo.setWorkExperienceList(selectWorkExperienceList(vo.getId()));
        }
        return vo;
    }

    /**
     * 新增招聘信息
     *
     * @param addDTO 新增DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int insertRecruitment(CcdiStaffRecruitmentAddDTO addDTO) {
        String recruitId = trim(addDTO.getRecruitId());

        CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
        BeanUtils.copyProperties(addDTO, recruitment);
        recruitment.setRecruitId(recruitId);

        int result = recruitmentMapper.insert(recruitment);
        insertWorkExperienceList(recruitment.getId(), recruitId, addDTO.getRecruitType(), addDTO.getWorkExperienceList());
        return result;
    }

    /**
     * 修改招聘信息
     *
     * @param editDTO 编辑DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int updateRecruitment(CcdiStaffRecruitmentEditDTO editDTO) {
        CcdiStaffRecruitment existing = recruitmentMapper.selectById(editDTO.getId());
        if (existing == null) {
            throw new RuntimeException("招聘信息不存在");
        }

        String recruitId = trim(editDTO.getRecruitId());
        editDTO.setRecruitId(recruitId);

        CcdiStaffRecruitment recruitment = new CcdiStaffRecruitment();
        BeanUtils.copyProperties(editDTO, recruitment);
        int result = recruitmentMapper.updateById(recruitment);
        if (!Objects.equals(existing.getRecruitId(), recruitId)) {
            updateWorkRecruitId(editDTO.getId(), recruitId);
        }
        replaceWorkExperienceList(editDTO);

        return result;
    }

    /**
     * 批量删除招聘信息
     *
     * @param ids 需要删除的招聘信息ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteRecruitmentByIds(Long[] ids) {
        List<Long> idList = Arrays.asList(ids);
        if (!idList.isEmpty()) {
            LambdaQueryWrapper<CcdiStaffRecruitmentWork> workWrapper = new LambdaQueryWrapper<>();
            workWrapper.in(CcdiStaffRecruitmentWork::getRecruitmentId, idList);
            recruitmentWorkMapper.delete(workWrapper);
        }
        return recruitmentMapper.deleteBatchIds(idList);
    }

    /**
     * 导入招聘信息数据（异步）
     *
     * @param excelList Excel实体列表
     * @return 任务ID
     */
    @Override
    @Transactional
    public String importRecruitment(List<CcdiStaffRecruitmentExcel> recruitmentList,
                                    List<CcdiStaffRecruitmentWorkExcel> workList) {
        recruitmentList = recruitmentList == null ? List.of() : recruitmentList;
        workList = workList == null ? List.of() : workList;
        boolean noRecruitmentRows = StringUtils.isNull(recruitmentList) || recruitmentList.isEmpty();
        boolean noWorkRows = StringUtils.isNull(workList) || workList.isEmpty();
        if (noRecruitmentRows && noWorkRows) {
            throw new RuntimeException("至少需要一条数据");
        }

        String taskId = UUID.randomUUID().toString();
        long startTime = System.currentTimeMillis();
        String userName = SecurityUtils.getUsername();
        int totalCount = recruitmentList.size() + workList.size();

        String statusKey = "import:recruitment:" + taskId;
        Map<String, Object> statusData = new HashMap<>();
        statusData.put("taskId", taskId);
        statusData.put("status", "PROCESSING");
        statusData.put("totalCount", totalCount);
        statusData.put("successCount", 0);
        statusData.put("failureCount", 0);
        statusData.put("progress", 0);
        statusData.put("startTime", startTime);
        statusData.put("message", "正在处理...");

        redisTemplate.opsForHash().putAll(statusKey, statusData);
        redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);

        recruitmentImportService.importRecruitmentAsync(recruitmentList, workList, taskId, userName);

        return taskId;
    }

    private List<CcdiStaffRecruitmentWorkVO> selectWorkExperienceList(Long recruitmentId) {
        LambdaQueryWrapper<CcdiStaffRecruitmentWork> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CcdiStaffRecruitmentWork::getRecruitmentId, recruitmentId)
                .orderByAsc(CcdiStaffRecruitmentWork::getSortOrder)
                .orderByDesc(CcdiStaffRecruitmentWork::getId);
        List<CcdiStaffRecruitmentWork> workList = recruitmentWorkMapper.selectList(wrapper);
        if (workList == null || workList.isEmpty()) {
            return new ArrayList<>();
        }
        return workList.stream().map(work -> {
            CcdiStaffRecruitmentWorkVO vo = new CcdiStaffRecruitmentWorkVO();
            BeanUtils.copyProperties(work, vo);
            return vo;
        }).toList();
    }

    private void updateWorkRecruitId(Long recruitmentId, String newRecruitId) {
        LambdaUpdateWrapper<CcdiStaffRecruitmentWork> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(CcdiStaffRecruitmentWork::getRecruitmentId, recruitmentId)
                .set(CcdiStaffRecruitmentWork::getRecruitId, newRecruitId);
        recruitmentWorkMapper.update(null, updateWrapper);
    }

    private String trim(String value) {
        return value == null ? null : value.trim();
    }

    private void replaceWorkExperienceList(CcdiStaffRecruitmentEditDTO editDTO) {
        LambdaQueryWrapper<CcdiStaffRecruitmentWork> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(CcdiStaffRecruitmentWork::getRecruitmentId, editDTO.getId());

        if (!Objects.equals(RecruitType.SOCIAL.getCode(), editDTO.getRecruitType())) {
            recruitmentWorkMapper.delete(deleteWrapper);
            return;
        }

        if (editDTO.getWorkExperienceList() == null) {
            return;
        }

        recruitmentWorkMapper.delete(deleteWrapper);
        List<CcdiStaffRecruitmentWork> workList = buildWorkExperienceEntities(
                editDTO.getId(),
                editDTO.getRecruitId(),
                editDTO.getWorkExperienceList()
        );
        workList.forEach(recruitmentWorkMapper::insert);
    }

    private void insertWorkExperienceList(Long recruitmentId,
                                          String recruitId,
                                          String recruitType,
                                          List<CcdiStaffRecruitmentWorkEditDTO> workExperienceList) {
        if (!Objects.equals(RecruitType.SOCIAL.getCode(), recruitType)) {
            return;
        }
        List<CcdiStaffRecruitmentWork> workList = buildWorkExperienceEntities(recruitmentId, recruitId, workExperienceList);
        workList.forEach(recruitmentWorkMapper::insert);
    }

    private List<CcdiStaffRecruitmentWork> buildWorkExperienceEntities(Long recruitmentId,
                                                                       String recruitId,
                                                                       List<CcdiStaffRecruitmentWorkEditDTO> workExperienceList) {
        if (workExperienceList == null || workExperienceList.isEmpty()) {
            return new ArrayList<>();
        }

        List<CcdiStaffRecruitmentWork> entityList = new ArrayList<>();
        for (int i = 0; i < workExperienceList.size(); i++) {
            CcdiStaffRecruitmentWorkEditDTO item = workExperienceList.get(i);
            if (item == null || StringUtils.isBlank(item.getCompanyName()) || StringUtils.isBlank(item.getJobStartMonth())) {
                continue;
            }
            CcdiStaffRecruitmentWork work = new CcdiStaffRecruitmentWork();
            BeanUtils.copyProperties(item, work);
            work.setRecruitmentId(recruitmentId);
            work.setRecruitId(recruitId);
            work.setSortOrder(i + 1);
            entityList.add(work);
        }
        return entityList;
    }
}
