package cn.wisenergy.service.impl;

import cn.wisenergy.common.utils.exception.BASE_RESP_CODE_ENUM;
import cn.wisenergy.common.utils.exception.BaseCustomException;
import cn.wisenergy.mapper.WorkHolidayMapper;
import cn.wisenergy.model.app.WorkHoliday;
import cn.wisenergy.model.app.WorkSubmitAdopt;
import cn.wisenergy.model.app.WorkType;
import cn.wisenergy.model.dto.HolidayAndAutoDto;
import cn.wisenergy.model.enums.LevelEnum;
import cn.wisenergy.service.WorkHolidayService;
import cn.wisenergy.service.WorkSubmitAdoptService;
import cn.wisenergy.service.WorkTypeService;
import cn.wisenergy.service.utils.UserRoleLevelUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author chenqi
 * @since 2021-01-19
 */
@Service
@Slf4j
public class WorkHolidayServiceImpl implements WorkHolidayService {

    @Autowired
    private WorkHolidayMapper workHolidayMapper;

    @Autowired
    private WorkSubmitAdoptService workSubmitAdoptService;

    @Autowired
    private WorkTypeService workTypeService;

    @Override
    public Boolean isHoliday(Date date) {
        log.info("WorkHolidayServiceImpl[]workHolidayMapper[]input.param.date:{}" + date);
        if (null == date) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        List<WorkHoliday> workHolidays = workHolidayMapper.selectList(null);
        for (WorkHoliday holiday : workHolidays) {
            if (!yearMonthBetween(date, holiday.getDayStart(), holiday.getDayEnd())) {
                continue;
            }
            // 节假日
            if (1 == holiday.getDayType()) {
                return true;
            }
            // 工作日
            if (0 == holiday.getDayType()) {
                return false;
            }
        }
        return calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ||
                calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY;

    }


    private Boolean addHoliday(WorkHoliday workHoliday) {
        log.info("WorkHolidayServiceImpl[]addHoliday[]input.param.workHoliday:{}" + workHoliday);
        verificationDate(workHoliday);
        List<WorkHoliday> holidays = workHolidayMapper.getByTypeAndStartDate( new Date());
        if (!CollectionUtils.isEmpty(holidays)) {
            for (WorkHoliday holiday : holidays) {
                if (workHoliday.getDes().equals(holiday.getDes())) {
                    throw new BaseCustomException(BASE_RESP_CODE_ENUM.DUPLICATE_HOLIDAY_NAME);
                }
            }
        }
        if (isItRedundant(workHoliday, null)) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.REPEAT_WITH_OLDTIME);
        }
        int insert = workHolidayMapper.insert(workHoliday);
        return insert > 0;
    }

    @Transactional
    @Override
    public Boolean addAndModifyHoliday(WorkHoliday workHoliday) {
        log.info("WorkHolidayServiceImpl[]modifyHoliday[]input.param.workHoliday:{}" + workHoliday);
        if (null == workHoliday) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (null == workHoliday.getId()) {
            return addHoliday(workHoliday);
        } else {
            verificationDate(workHoliday);
            if (null == workHoliday.getId()) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
            }
            List<WorkHoliday> holidays = workHolidayMapper.getByTypeAndStartDate( new Date());
            if (!CollectionUtils.isEmpty(holidays)) {
                for (WorkHoliday holiday : holidays) {
                    if (holiday.getId().equals(workHoliday.getId())) {
                        continue;
                    }
                    if (workHoliday.getDes().equals(holiday.getDes())) {
                        throw new BaseCustomException(BASE_RESP_CODE_ENUM.DUPLICATE_HOLIDAY_NAME);
                    }
                }
            }
            WorkHoliday workHolidayById = workHolidayMapper.selectById(workHoliday);
            if (null == workHolidayById) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.HOLIDAY_NOT_IS_NULL);
            }
            if (isItRedundant(workHoliday, workHolidayById.getId())) {
                throw new BaseCustomException(BASE_RESP_CODE_ENUM.REPEAT_WITH_OLDTIME);
            }
            int i = workHolidayMapper.updateById(workHoliday);
            return i > 0;
        }
    }

    @Transactional
    @Override
    public Boolean deleteHoliday(Integer id) {
        log.info("WorkHolidayServiceImpl[]deleteHoliday[]input.param.id:{}" + id);
        if (null == id) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        WorkHoliday workHoliday = workHolidayMapper.selectById(id);
        if (null == workHoliday) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.HOLIDAY_NOT_IS_NULL);
        }
        int i = workHolidayMapper.deleteById(id);
        return i > 0;
    }

    @Override
    public HolidayAndAutoDto getHoliday(Integer userId) {
        log.info("WorkHolidayServiceImpl[]getHolidayAll[]input.param.userId:{}" + userId);
        if (!UserRoleLevelUtils.isManagerLevel(userId, LevelEnum.SYSTEMSETTINGS.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        HolidayAndAutoDto holidayAndAutoDto = new HolidayAndAutoDto();
        List<WorkHoliday> workHolidays = workHolidayMapper.getByTypeAndStartDate(new Date());
        WorkSubmitAdopt submitAdopt = workSubmitAdoptService.getById(1);
        holidayAndAutoDto.setWorkHolidays(workHolidays).setWorkSubmitAdopt(submitAdopt);
        List<WorkType> workTypes = workTypeService.getAll();
        if (!CollectionUtils.isEmpty(workTypes)) {
            holidayAndAutoDto.setWorkTypes(workTypes);
        }
        return holidayAndAutoDto;
    }

    private void verificationDate(WorkHoliday workHoliday) {
        if (null == workHoliday) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (null == workHoliday.getDayStart()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (null == workHoliday.getDayEnd()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (null == workHoliday.getDayType()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        /*if (null == workHoliday.getDayType()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }*/
        if (StringUtils.isEmpty(workHoliday.getDes())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        if (workHoliday.getDayStart().compareTo(workHoliday.getDayEnd()) > 0) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.START_NOT_THAN_END_DATE);
        }

    }



  /*  // 获取某时间段内的所有日期
    public List<Date> findDates(Date dBegin, Date dEnd) {
        List<Date> lDate = new ArrayList<>();
        lDate.add(dBegin);
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(calBegin.getTime());
        }
        return lDate;
    }
*/

    /**
     * 判断某个时间是否在时间段内
     */
    private static boolean yearMonthBetween(Date nowDate, Date startDate, Date endDate) {
        long nowTime = nowDate.getTime();
        long startTime = startDate.getTime();
        long endTime = endDate.getTime();
        return nowTime >= startTime && nowTime <= endTime;
    }

    /**
     * 判断某个时间段是否在另一个时间段
     */
    private boolean isItRedundant(WorkHoliday workHoliday, Integer id) {
        List<WorkHoliday> workHolidays = workHolidayMapper.selectList(new QueryWrapper<>());
        if (CollectionUtils.isEmpty(workHolidays)) {
            return false;
        }
        long d1 = workHoliday.getDayStart().getTime();
        long d2 = workHoliday.getDayEnd().getTime();
        long v = d2 - d1;
        long start;
        long end;

        for (WorkHoliday workHoliday1 : workHolidays) {
            if (workHoliday1.getId().equals(id)) {
                continue;
            }
            start = workHoliday1.getDayStart().getTime();
            end = workHoliday1.getDayEnd().getTime();
            if ((d1 - start >= 0 && d2 - end <= 0) || (d1 - start <= 0 && d2 - end >= 0) || (d1 - start <= 0 && d2 - start >= 0) || (d1 - start >= 0 && d1 - end <= 0)) {
                return true;
            }
        }
        return false;
    }

}
