package cn.iocoder.yudao.module.system.service.laborcontract;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractRespVO;
import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.laborcontract.LaborContractDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.laborcontract.LaborContractMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.LABOR_CONTRACT_NOT_EXISTS;

/**
 * 劳动合同管理 Service 实现类
 *
 * @author 符溶馨
 */
@Service
@Validated
public class LaborContractServiceImpl implements LaborContractService {

    @Resource
    private LaborContractMapper laborContractMapper;

    @Resource
    private AdminUserMapper userMapper;

    @Resource
    private DeptService deptService;

    @Override
    public Long createLaborContract(LaborContractSaveReqVO createReqVO) {
        // -- 查询是否有多条记录
        Long num = laborContractMapper.selectCount(new LambdaQueryWrapper<LaborContractDO>()
                .eq(LaborContractDO::getUserId, createReqVO.getUserId()));
        // 插入
        LaborContractDO laborContract = BeanUtils.toBean(createReqVO, LaborContractDO.class);
        // 设置到期时间
        laborContract.setExpirationDate(laborContract.getSigningDate().plusYears(laborContract.getContractDuration()));

        // 判断到期时间是否小于当前日期
        if (laborContract.getExpirationDate().isBefore(LocalDate.now())) {
            // 设置合同状态为过期
            laborContract.setStatus(LaborContractDO.STATUS_EXPIRE);
        }else {
            // 设置合同状态为 已签
            laborContract.setStatus(LaborContractDO.STATUS_SIGN);
        }

        laborContractMapper.insert(laborContract);
        // - 判断是否有多条记录 - 如果没有的话则 插入时间到用户表中
        if (num == 0) {
            userMapper.updateById(new AdminUserDO().setId(createReqVO.getUserId()).setEntryDate(createReqVO.getSigningDate().atStartOfDay()));
        }
        // 返回
        return laborContract.getId();
    }

    @Override
    public void updateLaborContract(LaborContractSaveReqVO updateReqVO) {
        // 校验存在
        validateLaborContractExists(updateReqVO.getId());
        // 更新
        LaborContractDO updateObj = BeanUtils.toBean(updateReqVO, LaborContractDO.class);
        laborContractMapper.updateById(updateObj);
    }

    @Override
    public void updateLaborContractList(List<Long> ids, Integer status) {

        List<LaborContractDO> updateVO = ids.stream()
                .map(id -> new LaborContractDO()
                        .setId(id)
                        .setStatus(status))
                .collect(Collectors.toList());

        laborContractMapper.updateBatch(updateVO);
    }

    @Override
    public void deleteLaborContract(Long id) {
        // 校验存在
        validateLaborContractExists(id);
        // 删除
        laborContractMapper.deleteById(id);
    }

    private void validateLaborContractExists(Long id) {
        if (laborContractMapper.selectById(id) == null) {
            throw exception(LABOR_CONTRACT_NOT_EXISTS);
        }
    }

    @Override
    public LaborContractDO getLaborContract(Long id) {
        return laborContractMapper.selectById(id);
    }

    @Override
    public PageResult<LaborContractRespVO> getLaborContractPage(LaborContractPageReqVO pageReqVO) {

        if (pageReqVO.getDeptId() != null) {

            // 获取所有子级部门
            List<DeptDO> deptDOS = deptService.getChildDept(pageReqVO.getDeptId());
            pageReqVO.setDeptIds(convertList(deptDOS, DeptDO::getId));
        }

        Page<LaborContractRespVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        IPage<LaborContractRespVO> pageList = userMapper.selectContractPage(page, pageReqVO);
        if (CollectionUtil.isNotEmpty(pageList.getRecords())) {

            List<Long> userIds = convertList(pageList.getRecords(), LaborContractRespVO::getUserId);
            List<LaborContractRespVO> countRespVOs = laborContractMapper.selectContractCount(userIds);
            Map<Long, LaborContractRespVO> countMap = convertMap(countRespVOs, LaborContractRespVO::getUserId);

            pageList.getRecords().forEach(item -> {
                LaborContractRespVO respVO = countMap.get(item.getUserId());
                if (respVO != null) {
                    item.setSigningCount(respVO.getSigningCount());
                }else {
                    item.setSigningCount(0);
                }
            });
        }

        return new PageResult<>(pageList.getRecords(), pageList.getTotal());
    }

    @Override
    public List<LaborContractDO> getHistoryList(Long userId) {

        return laborContractMapper.selectHistoryList(userId);
    }

    @Override
    public List<LaborContractDO> getListByUserIds(List<Long> userIds) {

        return laborContractMapper.selectList(LaborContractDO::getUserId, userIds);
    }

    @Override
    public List<LaborContractDO> getListByEndTime(LocalDate now) {

        return laborContractMapper.selectList(new LambdaQueryWrapperX<LaborContractDO>()
                .lt(LaborContractDO::getExpirationDate, now)
                .eq(LaborContractDO::getStatus, LaborContractDO.STATUS_SIGN));
    }

    @Override
    public LaborContractDO getSigningDate(Long userId) {

        List<LaborContractDO> list = laborContractMapper.selectList(new LambdaQueryWrapperX<LaborContractDO>()
                .eq(LaborContractDO::getUserId, userId)
                .isNotNull(LaborContractDO::getProbationPeriodTime)
                .orderByDesc(LaborContractDO::getCreateTime));

        return CollectionUtil.isEmpty(list) ? null : list.get(0);
    }

    @Override
    public LaborContractDO getTheEarliestContract(Long userId) {
        return laborContractMapper.getTheEarliestContract(userId);
    }

    @Override
    public List<LaborContractDO> getListByRemindDate(LocalDate remindDate) {

        return laborContractMapper.selectListByRemindDate(remindDate);
    }
}
