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

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.info.collection.domain.CcdiStaffTransfer;
import com.ruoyi.info.collection.domain.dto.CcdiStaffTransferAddDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffTransferEditDTO;
import com.ruoyi.info.collection.domain.dto.CcdiStaffTransferQueryDTO;
import com.ruoyi.info.collection.domain.dto.TransferUniqueKey;
import com.ruoyi.info.collection.domain.excel.CcdiStaffTransferExcel;
import com.ruoyi.info.collection.domain.vo.CcdiStaffTransferVO;
import com.ruoyi.info.collection.mapper.CcdiBaseStaffMapper;
import com.ruoyi.info.collection.mapper.CcdiStaffTransferMapper;
import com.ruoyi.info.collection.service.ICcdiStaffTransferImportService;
import com.ruoyi.info.collection.service.ICcdiStaffTransferService;
import com.ruoyi.common.exception.ServiceException;
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.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 员工调动记录 服务层处理
 *
 * @author ruoyi
 * @date 2026-02-10
 */
@Service
public class CcdiStaffTransferServiceImpl implements ICcdiStaffTransferService {

    @Resource
    private CcdiStaffTransferMapper transferMapper;

    @Resource
    private ICcdiStaffTransferImportService transferImportService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private CcdiBaseStaffMapper staffMapper;

    /**
     * 查询员工调动记录列表
     *
     * @param queryDTO 查询条件
     * @return 员工调动记录VO集合
     */
    @Override
    public java.util.List<CcdiStaffTransferVO> selectTransferList(CcdiStaffTransferQueryDTO queryDTO) {
        Page<CcdiStaffTransferVO> page = new Page<>(1, Integer.MAX_VALUE);
        Page<CcdiStaffTransferVO> resultPage = transferMapper.selectTransferPage(page, queryDTO);
        return resultPage.getRecords();
    }

    /**
     * 分页查询员工调动记录列表
     *
     * @param page     分页对象
     * @param queryDTO 查询条件
     * @return 员工调动记录VO分页结果
     */
    @Override
    public Page<CcdiStaffTransferVO> selectTransferPage(Page<CcdiStaffTransferVO> page, CcdiStaffTransferQueryDTO queryDTO) {
        return transferMapper.selectTransferPage(page, queryDTO);
    }

    /**
     * 查询员工调动记录列表（用于导出）
     *
     * @param queryDTO 查询条件
     * @return 员工调动记录Excel实体集合
     */
    @Override
    public java.util.List<CcdiStaffTransferExcel> selectTransferListForExport(CcdiStaffTransferQueryDTO queryDTO) {
        return transferMapper.selectTransferListForExport(queryDTO).stream().map(vo -> {
            CcdiStaffTransferExcel excel = new CcdiStaffTransferExcel();
            BeanUtils.copyProperties(vo, excel);
            return excel;
        }).collect(Collectors.toList());
    }

    /**
     * 查询员工调动记录详情
     *
     * @param id 主键ID
     * @return 员工调动记录VO
     */
    @Override
    public CcdiStaffTransferVO selectTransferById(Long id) {
        return transferMapper.selectTransferById(id);
    }

    /**
     * 新增员工调动记录
     *
     * @param addDTO 新增DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int insertTransfer(CcdiStaffTransferAddDTO addDTO) {
        // 唯一性校验
        checkUniqueForAdd(addDTO);

        CcdiStaffTransfer transfer = new CcdiStaffTransfer();
        BeanUtils.copyProperties(addDTO, transfer);
        int result = transferMapper.insert(transfer);
        return result;
    }

    /**
     * 修改员工调动记录
     *
     * @param editDTO 编辑DTO
     * @return 结果
     */
    @Override
    @Transactional
    public int updateTransfer(CcdiStaffTransferEditDTO editDTO) {
        // 唯一性校验（排除当前记录）
        checkUniqueForEdit(editDTO);

        CcdiStaffTransfer transfer = new CcdiStaffTransfer();
        BeanUtils.copyProperties(editDTO, transfer);
        int result = transferMapper.updateById(transfer);
        return result;
    }

    /**
     * 批量删除员工调动记录
     *
     * @param ids 需要删除的主键ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteTransferByIds(Long[] ids) {
        return transferMapper.deleteBatchIds(java.util.List.of(ids));
    }

    /**
     * 导入员工调动记录数据（异步）
     *
     * @param excelList Excel实体列表
     * @return 任务ID
     */
    @Override
    @Transactional
    public String importTransfer(java.util.List<CcdiStaffTransferExcel> excelList) {
        if (StringUtils.isNull(excelList) || excelList.isEmpty()) {
            throw new RuntimeException("至少需要一条数据");
        }

        // 生成任务ID
        String taskId = UUID.randomUUID().toString();
        long startTime = System.currentTimeMillis();

        // 获取当前用户名
        String userName = SecurityUtils.getUsername();

        // 初始化Redis状态
        String statusKey = "import:staffTransfer:" + taskId;
        Map<String, Object> statusData = new HashMap<>();
        statusData.put("taskId", taskId);
        statusData.put("status", "PROCESSING");
        statusData.put("totalCount", excelList.size());
        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);

        // 调用异步导入服务
        transferImportService.importTransferAsync(excelList, taskId, userName);

        return taskId;
    }

    /**
     * 新增时校验唯一性
     *
     * @param addDTO 新增DTO
     * @throws ServiceException 如果记录已存在
     */
    @Override
    public void checkUniqueForAdd(CcdiStaffTransferAddDTO addDTO) {
        TransferUniqueKey key = TransferUniqueKey.from(addDTO);
        CcdiStaffTransfer existing = transferMapper.checkExists(key);
        if (existing != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String dateStr = sdf.format(addDTO.getTransferDate());
            throw new ServiceException("该员工在 [" + dateStr + "] 的调动记录已存在（从[" +
                    addDTO.getDeptNameBefore() + "]调往[" + addDTO.getDeptNameAfter() + "]）");
        }
    }

    /**
     * 编辑时校验唯一性
     *
     * @param editDTO 编辑DTO
     * @throws ServiceException 如果记录已存在
     */
    @Override
    public void checkUniqueForEdit(CcdiStaffTransferEditDTO editDTO) {
        TransferUniqueKey key = TransferUniqueKey.from(editDTO);
        CcdiStaffTransfer existing = transferMapper.checkExistsExcludeId(key, editDTO.getId());
        if (existing != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String dateStr = sdf.format(editDTO.getTransferDate());
            throw new ServiceException("该员工在 [" + dateStr + "] 的调动记录已存在（从[" +
                    editDTO.getDeptNameBefore() + "]调往[" + editDTO.getDeptNameAfter() + "]）");
        }
    }
}
