package com.yifu.cloud.plus.v1.business.service.vacation.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.business.dto.vacation.UpdateVacationRedundancyDTO;
import com.yifu.cloud.plus.v1.business.entity.vacation.TVacationMonitor;
import com.yifu.cloud.plus.v1.business.mapper.vacation.TVacationMonitorMapper;
import com.yifu.cloud.plus.v1.business.query.vacation.TVacationMonitorQuery;
import com.yifu.cloud.plus.v1.business.service.vacation.TVacationMonitorService;
import com.yifu.cloud.plus.v1.business.service.vacation.TVacationRuleConfigService;
import com.yifu.cloud.plus.v1.business.util.BusinessResultErrorMsg;
import com.yifu.cloud.plus.v1.business.vo.vacation.TVacationMonitorVO;
import com.yifu.cloud.plus.v1.business.vo.vacation.VacationRuleConfigVO;
import com.yifu.cloud.plus.v1.yifu.archives.vo.BusinessEmployeeExtendVO;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TBusinessDataListVo;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.BigDecimalUtils;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @description: 假期监控表 service实现层
 * @author: wangweiguo
 * @date: 2021-08-13
*/
@Service
@AllArgsConstructor
public class TVacationMonitorServiceImpl extends ServiceImpl<TVacationMonitorMapper, TVacationMonitor>
implements TVacationMonitorService {

    private final TVacationRuleConfigService vacationRuleConfigService;

	private ArchivesDaprUtil archivesDaprUtil;

    /**
     * @description: 分页查询: 条件分页查询
     * @param query 查询条件
     * @return: R<IPage<TVacationMonitorVO>>
     * @author: wangweiguo
     * @date: 2021-08-13
    */
    @Override
    public R<IPage<TVacationMonitorVO>> getListByPage(TVacationMonitorQuery query) {
        Page<TVacationMonitorVO> page = new Page<>(query.getCurrent(), query.getSize());
        page.setOrders(query.getOrders());
        page = this.baseMapper.getListByPage(page, query);
        List<TVacationMonitorVO> voList = page.getRecords();
        // 设置vo展示 工龄计算
        voList.forEach(v -> v.setWorkingAge(BigDecimalUtils.safeDivide(BigDecimal.valueOf(Duration.between(v.getBusinessEnjoinDate(), LocalDateTime.now()).toDays()), BigDecimal.valueOf(365L), 1)));
        return R.ok(page, BusinessResultErrorMsg.SUCCESS);
    }

    /**
     * @description: 导出：根据查询条件导出
     * @param query 查询条件
     * @return: R<List<TVacationMonitorVO>>
     * @author: wangweiguo
     * @date: 2021-08-13
     */
    @Override
    public R<List<TVacationMonitorVO>> exportByParams(TVacationMonitorQuery query) {
        List<TVacationMonitorVO> list = this.baseMapper.getList(query);
        list.forEach(v -> v.setWorkingAge(BigDecimalUtils.safeDivide(BigDecimal.valueOf(Duration.between(v.getBusinessEnjoinDate(), LocalDateTime.now()).toDays()), BigDecimal.valueOf(365L), 1)));
        return R.ok(list, CommonConstants.SEARCH_SUCCESS);
    }

    /**
     * @description: 保存或者更新监控记录
     * @param entity
     * @return: boolean
     * @author: wangweiguo
     * @date: 2021/8/16
     */
    @Override
    public boolean saveOrUpdateData(TVacationMonitor entity) {
        beforeSaveInit(entity);
        return this.saveOrUpdate(entity);
    }

    /**
     * @description: 批量保存 OR 新增
     * @param list
     * @return: boolean
     * @author: wangweiguo
     * @date: 2021/8/16
     */
    @Override
    public boolean batchSaveOrUpdateData(List<TVacationMonitor> list) {
        if (!CollUtil.isEmpty(list)) {
            for (TVacationMonitor entity : list) {
                beforeSaveInit(entity);
            }
            return this.saveOrUpdateBatch(list, 200);
        }
        return false;
    }

    /**
     * @description: 查询-剩余年假：根据身份证号查询剩余年假
     * @param idcard
     * @return: com.yifu.cloud.v1.common.core.util.R<java.math.BigDecimal>
     * @author: wangweiguo
     * @date: 2021/8/17
     */
    @Override
    public R<BigDecimal> getNotUsedVacationDurationByIdCard(String idcard) {
        TVacationMonitor vacationMonitor = this.lambdaQuery()
                .eq(TVacationMonitor::getEmpIdcard, idcard)
                .eq(TVacationMonitor::getVacationYear, String.valueOf(LocalDate.now().getYear()))
                .last(CommonConstants.LAST_ONE_SQL)
                .one();
        if (null != vacationMonitor) {
            return R.ok(BigDecimalUtils.safeAdd(vacationMonitor.getNotUsedVacationDuration()),CommonConstants.SEARCH_SUCCESS);
        }
        return R.ok(null,CommonConstants.SEARCH_SUCCESS);
    }

    /**
     * @description: 定时任务：内部服务调用，每天初始化员工年假信息
     * @return: com.yifu.cloud.v1.common.core.util.R<java.lang.Boolean>
     * @author: wangweiguo
     * @date: 2021/8/17
     */
    @Override
    public R<Boolean> buildMonitorData() {
        R<VacationRuleConfigVO> vacationRuleConfigR = this.vacationRuleConfigService.getVacationRuleConfig();
        if (R.haveData(vacationRuleConfigR) && CommonConstants.ONE_STRING.equals(vacationRuleConfigR.getData().getVacationAutoInit())) {
            VacationRuleConfigVO ruleConfig = vacationRuleConfigR.getData();
            R<TBusinessDataListVo> listR = archivesDaprUtil.getNotLeaveExtendList();
            if (R.isSuccess(listR) && Common.isNotNull(listR.getData()) && Common.isNotNull(listR.getData().getExtendVO())) {
                List<BusinessEmployeeExtendVO> list = listR.getData().getExtendVO();
                List<TVacationMonitor> collect = list.stream().map(vo -> {
                    TVacationMonitor monitor = null;
                    if (null != vo.getBusinessEnjoinDate()) {
                        String curentYear = String.valueOf(LocalDate.now().getYear());
                        monitor = this.lambdaQuery()
                                .eq(TVacationMonitor::getVacationYear, curentYear)
                                .eq(TVacationMonitor::getEmpIdcard, vo.getEmpIdcard()).last(CommonConstants.LAST_ONE_SQL).one();
                        // 计算年假时长
                        Integer vacationDuration = this.vacationRuleConfigService.annualLeaveCalculationFormula(vo.getBusinessEnjoinDate());

                        // 没有年假监控记录并且至少有一天年假，初始化年假监控 && 四舍五入至少有一天年假再发放
                        if (monitor == null && vacationDuration >= 1) {
                            monitor = buildVacationMonitor(vo, ruleConfig, null);
                            return monitor;
                        }
                    }
                    return null;
                }).filter(Objects::nonNull).collect(Collectors.toList());
                boolean isSuccess = this.batchSaveOrUpdateData(collect);
                if (isSuccess) {
                    return R.ok(null,CommonConstants.RESULT_DATA_SUCESS);
                } else {
                    return R.failed(CommonConstants.RESULT_DATA_SUCESS);
                }
            }
        }
        return R.ok(null,CommonConstants.NO_DATA_TO_HANDLE);
    }

    /**
     * @description: 冗余更新：更新监控表中冗余的员工信息，电信工号和岗位
     * @return: com.yifu.cloud.v1.common.core.util.R<java.lang.Boolean>
     * @author: wangweiguo
     * @date: 2021/8/23
     */
    @Override
    public R<Boolean> updateRedundancyEmployeeFields(List<UpdateVacationRedundancyDTO> dtoList) {
        if (!CollUtil.isEmpty(dtoList)) {
            dtoList.forEach(v ->
                this.lambdaUpdate().eq(TVacationMonitor::getEmpIdcard, v.getEmpIdcard())
                        .set(StringUtils.isNotBlank(v.getBusinessTelecomNumber()), TVacationMonitor::getBusinessTelecomNumber, v.getBusinessTelecomNumber())
                        .set(StringUtils.isNotBlank(v.getBusinessPost()), TVacationMonitor::getBusinessPost, v.getBusinessPost())
                        .set(null != v.getDepartId(), TVacationMonitor::getDepartId, v.getDepartId())
                        .update()
            );
        }
        return R.ok(null,CommonConstants.RESULT_DATA_SUCESS);
    }

    /**
     * @description: 释放假期时长
     * @param empIdcard 身份证号
     * @param vacationDuration 假期时长
     * @param year 年份
     * @return: boolean
     * @author: wangweiguo
     * @date: 2021/8/24
     */
    @Override
    public boolean releaseVacationDuration(String empIdcard, BigDecimal vacationDuration, String year) {
        TVacationMonitor monitor = this.getMonitorByEmpIdcardAndYear(empIdcard, year);
        monitor.setNotUsedVacationDuration(BigDecimalUtils.safeAdd(monitor.getNotUsedVacationDuration(), vacationDuration));
        return this.saveOrUpdateData(monitor);
    }

    /**
     * @description: 消耗假期时长
     * @param empIdcard 身份证号
     * @param vacationDuration 假期时长
     * @param year 年份
     * @return: boolean
     * @author: wangweiguo
     * @date: 2021/8/24
     */
    @Override
    public boolean consumeVacationDuration(String empIdcard, BigDecimal vacationDuration, String year) {
        TVacationMonitor monitor = this.getMonitorByEmpIdcardAndYear(empIdcard, year);
        monitor.setNotUsedVacationDuration(BigDecimalUtils.safeSubtract(monitor.getNotUsedVacationDuration(), vacationDuration));
        return this.saveOrUpdateData(monitor);
    }

    /**
     * @description: 根据假勤年份和身份证号查询年假监控信息
     * @param empIdcard 身份证号
     * @param year 假勤年份
     * @return: com.yifu.cloud.v1.hrobusiness.api.entity.vacation.TVacationMonitor
     * @author: wangweiguo
     * @date: 2021/8/24
     */
    @Override
    public TVacationMonitor getMonitorByEmpIdcardAndYear(String empIdcard, String year) {
        return this.lambdaQuery().eq(TVacationMonitor::getEmpIdcard, empIdcard)
                .eq(TVacationMonitor::getVacationYear, year)
                .last(CommonConstants.LAST_ONE_SQL)
                .one();
    }

    /**
     * @description: 保存前，属性赋值
     * @param entity
     * @return: void
     * @author: wangweiguo
     * @date: 2021/8/16
     */
    private void beforeSaveInit(TVacationMonitor entity) {
        if (null != entity) {
            // 根据notUsedVacationDuration字段更新vacationStatus
            if (entity.getNotUsedVacationDuration().compareTo(BigDecimal.ZERO) > 0) {
                entity.setVacationStatus(CommonConstants.ZERO_STRING);
            }
            if (entity.getNotUsedVacationDuration().compareTo(BigDecimal.ZERO) == 0) {
                entity.setVacationStatus(CommonConstants.ONE_STRING);
            }
            if (null == entity.getNotUsedVacationDuration()) {
                entity.setVacationStatus(null);
            }
        }
    }

    /**
     * @author wangweiguo
     * @description 构建vacationmonitor对象
     * @date 21:48 2021/8/17
     * @param vo
     * @param ruleConfig
     * @return com.yifu.cloud.v1.hrobusiness.api.entity.vacation.TVacationMonitor
     **/
    private TVacationMonitor buildVacationMonitor(BusinessEmployeeExtendVO vo, VacationRuleConfigVO ruleConfig, TVacationMonitor monitor) {
        if (null == monitor) {
            monitor = new TVacationMonitor();
        }
        Integer vacationDuration = this.vacationRuleConfigService.annualLeaveCalculationFormula(vo.getBusinessEnjoinDate());
        monitor.setVacationYear(String.valueOf(LocalDate.now().getYear()));
        monitor.setNotUsedVacationDuration(BigDecimalUtils.safeMultiply(BigDecimal.valueOf(vacationDuration), ruleConfig.getTimeValue()));
        monitor.setVacationDuration(BigDecimalUtils.safeMultiply(BigDecimal.valueOf(vacationDuration), ruleConfig.getTimeValue()));
        monitor.setDepartId(vo.getDepartId());
        monitor.setBusinessEnjoinDate(vo.getBusinessEnjoinDate());
        monitor.setBusinessPost(vo.getBusinessPost());
        monitor.setBusinessTelecomNumber(vo.getBusinessTelecomNumber());
        monitor.setEmpIdcard(vo.getEmpIdcard());
        monitor.setEmpName(vo.getEmpName());
        monitor.setVacationStatus(CommonConstants.ZERO_STRING);
        return monitor;
    }

}




