package com.boman.web.core.service.leave;

import com.alibaba.fastjson.JSONObject;
import com.boman.common.core.utils.DateUtils;
import com.boman.domain.dto.UpdateDto;
import com.boman.system.api.model.LoginUser;
import com.boman.web.core.mapper.LeaveMapper;
import com.boman.web.core.mapper.StandardlyMapper;
import com.boman.web.core.service.common.ICommonService;
import com.boman.web.core.utils.AuthUtils;
import com.boman.web.core.utils.JSONObjectUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.boman.common.core.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;
import static com.boman.common.core.utils.obj.ObjectUtils.isEmpty;
import static com.boman.common.core.utils.obj.ObjectUtils.requireNonNull;
import static com.boman.domain.constant.LeaveConst.*;

/**
 * @author shiqian
 * @date 2021年06月17日 16:04
 **/
@Service
public class LeaveServiceImpl implements LeaveService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LeaveServiceImpl.class);

    @Resource
    private ICommonService commonService;
    @Resource
    private StandardlyMapper standardlyMapper;

    @Autowired
    private LeaveMapper leaveMapper;

    /**
     * 功能描述: 直接查询一年的
     *
     * @param yyyy yyyy
     * @return int
     */
    @Override
    public Map<String, Integer> statisticByType(String yyyy) {
        requireNonNull(yyyy, "statisticByType yyyy is empty");
        Map<String, Integer> map = new HashMap<>(2);

        String yearStartTime = yyyy + "-01-01 00:00:00";
        String yearEndTime = yyyy + "-12-31 23:59:59";

        List<JSONObject> result = listByTime(yearStartTime, yearEndTime);
        if (isEmpty(result)) {
            map.put(YEAR_LEAVE_COUNT, 0);
            map.put(MONTH_LEAVE_COUNT, 0);
            return map;
        }

        Date firstDayOfMonth = DateUtils.dateTime(YYYY_MM_DD_HH_MM_SS, yyyy + "-" + DateUtils.getMonth() + "-01 00:00:00");
        Date lastDayOfMonth = DateUtils.dateTime(YYYY_MM_DD_HH_MM_SS, DateUtils.getLastDayOfMonthStr(yyyy));
        int count = 0;
        for (JSONObject jsonObject : result) {
            Timestamp startTime = jsonObject.getTimestamp(LEAVEFROM_START_TIME);
            // 并且是当月的
            if (startTime.after(firstDayOfMonth) && startTime.before(lastDayOfMonth)) {
                count++;
            }
        }

        map.put(YEAR_LEAVE_COUNT, result.size());
        map.put(MONTH_LEAVE_COUNT, count);
        return map;
    }

    /**
     * 功能描述: 直接查询一年的
     *
     * @return int
     */
    @Override
    public Integer statisticLeave() {
        Integer count = leaveMapper.statisticLeave();
        return count == null ? 0 : count;
    }

    private List<JSONObject> listByTime(String startTime, String endTime) {
        JSONObject condition = new JSONObject();
        condition.put(LEAVEFROM_START_TIME, startTime);
        condition.put(LEAVEFROM_END_TIME, endTime);
        return commonService.getByMap(TABLE_NAME, condition);
    }

    /**
     * 功能描述: 根据deptId获取销假标准
     *
     * @param deptId deptId
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject getStandard(Long deptId) {
        requireNonNull(deptId, "deptId is empty");
        JSONObject condition = new JSONObject();
        condition.put(DEPT_ID, deptId);
        JSONObject standard = commonService.getOneByMap(TABLE_NAME_OFFSET_LEAVEFROM_STANDARD, condition);
        if (MapUtils.isEmpty(standard)) {
            LOGGER.error(String.format("该部门 = [%s], 未配置销假标准", deptId));
            throw new IllegalArgumentException("该人员所在部门未配置销假标准");
        }

        return standard;
    }

    /**
     * 功能描述: 根据id查找
     *
     * @param id id
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject getTempLeave(Long id) {
        requireNonNull(id, "tempLeave id is empty");

        JSONObject tempLeave = commonService.getOneByMap(TABLE_NAME_BOMAN_TEMP_LEAVEFORM, JSONObjectUtils.putValue(ID, id));
        if (MapUtils.isEmpty(tempLeave)) {
            LOGGER.error(String.format("id = [%s]的临时请假数据不存在", id));
            throw new IllegalArgumentException("临时请假数据不存在");
        }

        return tempLeave;
    }

    /**
     * 功能描述: 拿到当前人，当月的总临时时长
     *
     * @param username username
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public BigDecimal sumBeforeTempLeaveTime(String username, String startTime, String endTime, List<Long> idList) {
        requireNonNull(username, "sumBeforeTempLeaveTime username is empty");
        requireNonNull(startTime, "sumBeforeTempLeaveTime startTime is empty");
        requireNonNull(endTime, "sumBeforeTempLeaveTime endTime is empty");
        requireNonNull(idList, "sumBeforeTempLeaveTime idList is empty");

        String sum = standardlyMapper.sumBeforeTempLeaveTime(username, startTime, endTime, idList);
        return isEmpty(sum) ? BigDecimal.ZERO : new BigDecimal(sum);
    }

    /**
     * 功能描述: 销假 (自己销自己的)
     *
     * @param idList idList
     * @return com.boman.domain.dto.AjaxResult
     */
    @Override
    public boolean cancelLeave(List<Long> idList) {
        requireNonNull(idList, "sumBeforeTempLeaveTime idList is empty");
        LoginUser loginUser = AuthUtils.getLoginUser();
        JSONObject jsonObject = getStandard(loginUser.getSysUser().getDeptId());
        BigDecimal standard = jsonObject.getBigDecimal(OFFSET_TIME);

        List<JSONObject> tempList = commonService.getByMap(TABLE_NAME_BOMAN_TEMP_LEAVEFORM,  JSONObjectUtils.putValue(ID, idList));

        BigDecimal passDecimal = BigDecimal.ZERO;
        for (JSONObject object : tempList) {
            BigDecimal decimal = object.getBigDecimal(LEAVEFROM_TIME);
            passDecimal = passDecimal.add(decimal);
        }

        String first = DateUtils.getFirstDayOfMonthStr();
        String last = DateUtils.getLastDayOfMonthStr();
        BigDecimal beforeSum = sumBeforeTempLeaveTime(loginUser.getUsername(), first, last, idList);
        if ((beforeSum.add(passDecimal).subtract(standard)).compareTo(BigDecimal.ZERO) > 0) {
            // 超过可销假时长
            throw new IllegalArgumentException(String.format("超过本部门人员可销假总时长(%s h), 无法销假", standard));
        }

        // 修改状态
        UpdateDto updateDto = new UpdateDto();
        updateDto.setTableName(TABLE_NAME_BOMAN_TEMP_LEAVEFORM);
        JSONObject commitData = JSONObjectUtils.putValue(LEAVE_STATUS, Y);
        JSONObject condition = JSONObjectUtils.putValue(ID, idList);
        updateDto.setCommitData(commitData);
        updateDto.setCondition(condition);

        int update = commonService.update(updateDto);
        return update == idList.size();
    }

}
