package com.xunmei.system.service.impl;

import java.util.*;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xunmei.common.core.utils.DateUtils;
import com.xunmei.common.core.utils.snowId.DateHelper;
import com.xunmei.common.core.web.domain.AjaxResult;
import com.xunmei.system.api.domain.SysOrg;
import com.xunmei.system.api.domain.SysWorkTime;
import com.xunmei.system.domain.SysWorkTimeSetDayofweek;
import com.xunmei.system.mapper.SysWorkTimeMapper;
import com.xunmei.system.mapper.SysWorkTimeSetDayofweekMapper;
import com.xunmei.common.core.util.BeanHelper;
import com.xunmei.system.util.StreamHelper;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xunmei.system.service.ISysOrgService;

import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xunmei.common.core.web.page.TableDataInfo;
import com.xunmei.system.mapper.SysWorkTimeSetMapper;
import com.xunmei.system.domain.SysWorkTimeSet;
import com.xunmei.system.service.ISysWorkTimeSetService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 作息设置Service业务层处理
 *
 * @author xunmei
 * @date 2023-08-14
 */
@Service
public class SysWorkTimeSetServiceImpl extends ServiceImpl<SysWorkTimeSetMapper, SysWorkTimeSet> implements ISysWorkTimeSetService {
    @Autowired
    private SysWorkTimeSetMapper  sysWorkTimeSetMapper;
    @Autowired
    private ISysOrgService orgService;
    @Autowired
    private SysWorkTimeSetDayofweekMapper sysWorkTimeSetDayofweekMapper;
    @Autowired
    private SysWorkTimeMapper sysWorkTimeMapper;
    @Override
    public TableDataInfo<SysWorkTimeSet> selectPage(SysWorkTimeSet sysWorkTimeSet) {
        //未删除
        sysWorkTimeSet.setDeleted(0L);
        Page<SysWorkTimeSet> page;
        //分页
        if (sysWorkTimeSet.getPageNum() != null && sysWorkTimeSet.getPageSize() != null) {
            page = new Page<>(sysWorkTimeSet.getPageNum(), sysWorkTimeSet.getPageSize());
        } else {
            page = new Page<>();
        }
        //查询条件
        QueryWrapper<SysWorkTimeSet> query = new QueryWrapper<>(sysWorkTimeSet);
        //下穿
        if (sysWorkTimeSet.getCheckSub()) {
            List<Long> ids = orgService.selectCheckSubOrgIdList(sysWorkTimeSet.getOrgId());
            //清空前端传递的org_id
            sysWorkTimeSet.setOrgId(null);
            //添加in条件
            query.in("org_id", ids);
        }
        //时间范围查询
        if (sysWorkTimeSet.getParams().get("beginTime") != null && sysWorkTimeSet.getParams().get("endTime") != null) {
            query.between("create_time", sysWorkTimeSet.getParams().get("beginTime"), sysWorkTimeSet.getParams().get("endTime"));
        }
        //获取数据
        page = sysWorkTimeSetMapper.selectPage(page, query);
        //抓换为TableDataInfo适配前端
        return TableDataInfo.build(page);
    }

    @Override
    public AjaxResult workTimePageList(SysWorkTimeSet sysWorkTimeSet) {


        //未删除
        sysWorkTimeSet.setDeleted(0L);
        Page<SysWorkTimeSet> page;
        //分页
        if (sysWorkTimeSet.getPageNum() != null && sysWorkTimeSet.getPageSize() != null) {
            page = new Page<>(sysWorkTimeSet.getPageNum(), sysWorkTimeSet.getPageSize());
        } else {
            page = new Page<>();
        }
        //查询条件
        QueryWrapper<SysWorkTimeSet> query = new QueryWrapper<>(sysWorkTimeSet);
        //下穿
        if (sysWorkTimeSet.getCheckSub()) {
            List<Long> ids = orgService.selectCheckSubOrgIdList(sysWorkTimeSet.getOrgId());
            //清空前端传递的org_id
            sysWorkTimeSet.setOrgId(null);
            //添加in条件
            query.in("org_id", ids);
        }
        query.orderByDesc
                ("effective_date");
        //时间范围查询
        if (sysWorkTimeSet.getParams().get("beginTime") != null && sysWorkTimeSet.getParams().get("endTime") != null) {
            query.between("effective_date", sysWorkTimeSet.getParams().get("beginTime"), sysWorkTimeSet.getParams().get("endTime"));
        }
        //获取数据
        page = sysWorkTimeSetMapper.selectPage(page, query);


        List<SysWorkTimeSet> list = page.getRecords();
        List<Long> ids = new ArrayList<>();
        list.forEach(l -> {
            ids.add(l.getId());
        });
        if (list.size() > 0) {
            List<SysWorkTimeSetDayofweek> dayOfWeeks = sysWorkTimeSetDayofweekMapper.findByWorkTimeSetIdIn(ids);
            list.forEach(l -> {
                List<SysWorkTimeSetDayofweek> dayOfWeekList = dayOfWeeks.stream().filter(d -> d.getWorkTimeSetId().equals(l.getId())).collect(Collectors.toList());
                String workDay = "";
                workDay = getWorkDay(dayOfWeekList);
                l.setWorkDay(workDay);
                //当月和下月的作息不能删除
                //获取当前时间的月份
                Calendar cal = Calendar.getInstance();
                cal.setTime(new Date());
                int month = cal.get(Calendar.MONTH) + 1;
                //获取l.getEffectiveDate()的月份
                Calendar cal1 = Calendar.getInstance();
                cal1.setTime(l.getEffectiveDate());
                int month1 = cal1.get(Calendar.MONTH) + 1;
                //l.getEffectiveDate()在当前时间之前的作息不能删除，当月和下月的作息不能删除
                //下月后的模版可删除可编辑
                if (month1 - month >= 2) {
                    l.setTimeCheck(0);
                } else {
                    //本月之前的不能删除也不能编辑
                    if (month1 - month < 0) {
                        l.setTimeCheck(1);
                    } else {
                        //当月和下月的数据1不能删除2生效的不能编辑3未生效的可以编辑
                        if (l.getEffectiveDate().before(new Date())) {
                            //2生效的不能编辑不能删除
                            l.setTimeCheck(2);
                        } else {
                            //3未生效的可编辑不能删除
                            l.setTimeCheck(3);
                        }

                    }
                }

//            if(l.getEffectiveDate().before(new Date()) || month == month1 || month+1 == month1) {
//                l.setTimeCheck(1);
//            }else{
//                l.setTimeCheck(0);
//            }

            });
        }
        return AjaxResult.success(page);
    }

    public String getWorkDay(List<SysWorkTimeSetDayofweek> dayOfWeekList) {
        String workDay = "";
        if (CollectionUtils.isNotEmpty(dayOfWeekList)) {
            for (SysWorkTimeSetDayofweek dayOfWeek : dayOfWeekList) {
                if (ObjectUtil.isNull(dayOfWeek.getIsWorkday()) || dayOfWeek.getIsWorkday() == 0) {
                    continue;
                }
                switch (dayOfWeek.getDayOfWeek().intValue()) {
                    case 2:
                        workDay += ",周一";
                        break;
                    case 3:
                        workDay += ",周二";
                        break;
                    case 4:
                        workDay += ",周三";
                        break;
                    case 5:
                        workDay += ",周四";
                        break;
                    case 6:
                        workDay += ",周五";
                        break;
                    case 7:
                        workDay += ",周六";
                        break;
                    case 1:
                        workDay += ",周日";
                        break;
                }
            }
        }

        if (workDay.length() > 0) {
            workDay = workDay.substring(1);
        }
        return workDay;
    }

    /**
     * 查询作息设置
     *
     * @param id 作息设置主键
     * @return 作息设置
     */
    @Override
    public SysWorkTimeSet selectSysWorkTimeSetById(Long id) {
        SysWorkTimeSet sysWorkTimeSet = sysWorkTimeSetMapper.selectById(id);
        if(sysWorkTimeSet!=null) {
            sysWorkTimeSet.setDayOfWeeks(sysWorkTimeSetDayofweekMapper.selectList(new QueryWrapper<SysWorkTimeSetDayofweek>().eq("work_time_set_id", id)));
            for (SysWorkTimeSetDayofweek day :
                    sysWorkTimeSet.getDayOfWeeks()) {
                if (day.getDayOfWeek() == 1) {
                    day.setDayOfWeekText("星期天");
                } else if (day.getDayOfWeek() == 2) {
                    day.setDayOfWeekText("星期一");
                }else if (day.getDayOfWeek() == 3) {
                    day.setDayOfWeekText("星期二");
                }else if (day.getDayOfWeek() == 4) {
                    day.setDayOfWeekText("星期三");
                }else if (day.getDayOfWeek() == 5) {
                    day.setDayOfWeekText("星期四");
                }else if (day.getDayOfWeek() == 6) {
                    day.setDayOfWeekText("星期五");
                }else if (day.getDayOfWeek() == 7) {
                    day.setDayOfWeekText("星期六");
                }
            }
        }
        return sysWorkTimeSet;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String add(SysWorkTimeSet request) {
        List<Long> orgIds = request.getOrgIds();
        int year = Calendar.getInstance().get(Calendar.YEAR);

        if (request.getEffectiveDate() != null) {
            year = new DateHelper(request.getEffectiveDate()).getYear();
        }

        if (CollectionUtils.isNotEmpty(orgIds)) {
            List<SysWorkTimeSet> sets = new ArrayList<>();
            SysWorkTimeSet set = null;
            SysOrg org = null;
            List<SysWorkTimeSetDayofweek> dayOfWeeks = new ArrayList<>();
            for (Long orgId : orgIds) {
                if (request.getId() != null) {
                    set = sysWorkTimeSetMapper.selectById(request.getId());
                } else {
                    set = new SysWorkTimeSet();
                    org = orgService.selectSysOrgById(orgId);
                }
                BeanHelper.copyProperties(set, request);
                set.setOrgId(orgId);
                set.setYear((long) year);
                set.setDayOfWeeks(new ArrayList<>());
                if (set.getId() == null) {
                    if (org != null) {
                        set.setOrgName(org.getName());
                    }

                    sysWorkTimeSetMapper.insert(set);

                } else {
                    sysWorkTimeSetMapper.updateById(set);
                }

                Long id = set.getId();

                List<SysWorkTimeSetDayofweek> tmp = request.getDayOfWeeks().stream().map(w -> {
                    SysWorkTimeSetDayofweek dw = new SysWorkTimeSetDayofweek();
                    BeanUtils.copyProperties(w, dw);
                    return dw;
                }).collect(Collectors.toList());
                tmp.forEach(w -> {
                    w.setWorkTimeSetId(id);
                });

                dayOfWeeks.addAll(tmp);
                set.setDayOfWeeks(dayOfWeeks);
                sets.add(set);
            }

            // workTimeSetDayOfWeekRepository.deleteByWorkTimeSetIds(oldWorkTimeSetIds);
            for (SysWorkTimeSetDayofweek s :
                    dayOfWeeks) {
                sysWorkTimeSetDayofweekMapper.insert(s);
            }
            if (CollectionUtils.isNotEmpty(dayOfWeeks)) {
                changeOrgWorkTime(sets, dayOfWeeks, request.getEffectiveDate(), orgIds, request.getCheckDataResult());
            }
        }
        return "ok";
    }
    private void changeOrgWorkTime(List<SysWorkTimeSet> sets,List<SysWorkTimeSetDayofweek> dayOfWeeks, Date effectiveDate, List<Long> orgIds,Integer checkDataResult) {
        int month = new DateHelper(effectiveDate).getMonth();
        int monthDay = new DateHelper(new Date()).getMonth();
        //如果生效月份等于当前月份，那么就修改当本月生效日期后及下个月的作息时间
        if(month==monthDay||month==monthDay+1){
            // 获取当前时间的Calendar实例
            Calendar cal = Calendar.getInstance();
            // 将Calendar实例的月份设置为下个月的月份
            if(month==monthDay){
                cal.set(Calendar.MONTH, month + 1);
            }else{
                cal.set(Calendar.MONTH, month);
            }
            // 将Calendar实例的日期设置为1号
            cal.set(Calendar.DATE, 1);
            // 将Calendar实例的日期往前推1天，即获取下个月的最后一天的日期
            cal.add(Calendar.DATE, -1);
            cal.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            //删除当月生效日期后的作息时间及下个月的作息时间
            Map<String,Object> map = new HashMap<>();
            map.put("effectiveDate",effectiveDate);
            map.put("lastDayOfNextMonth", DateUtil.format(cal.getTime(),"yyyy-MM-dd"));
            map.put("orgIds",orgIds);
            //objectMapper.deleteOrgWorkTimeByMonth(map);
            //获取不需要生成的日期
            List<SysWorkTime> list = new ArrayList<>();
            if(checkDataResult!=null&&checkDataResult==0){
                list = sysWorkTimeMapper.getOrgWorkTimeByMonth(map);
            }
            //添加当月生效日期后的作息时间及下个月的作息时间
            final List<DateTime> dateTimeList = DateUtil.rangeToList(effectiveDate, cal.getTime(), DateField.DAY_OF_MONTH);
            List<SysWorkTime> workTimeEditDtoListAll = new ArrayList<>();
            for (SysWorkTimeSet workTime : sets) {
                List<SysWorkTime> workTimeEditDtoList = new ArrayList<>();
                for (DateTime time : dateTimeList) {
                    SysWorkTimeSetDayofweek dayOfWeekSet = workTime.getDayOfWeeks().stream().filter(w -> w.getDayOfWeek() == time.dayOfWeek() && ObjectUtil.isNotNull(w.getIsWorkday()) && w.getIsWorkday()>0).findFirst().get();
                    boolean isEnable = ObjectUtil.isNotNull(dayOfWeekSet) && dayOfWeekSet.getIsWorkday()>0;
                    SysWorkTime dto = new SysWorkTime();
                    dto.setDate(time);
                    dto.setIsEnable(isEnable?1L:0);
                    workTimeEditDtoList.add(dto);
                    if (ObjectUtil.isNull(dayOfWeekSet) || !(dayOfWeekSet.getIsWorkday()>0)) {
                        Optional<SysWorkTimeSetDayofweek> firstWorkDay = workTime.getDayOfWeeks().stream().filter(f -> f.getIsWorkday()>0).findFirst();
                        if (firstWorkDay.isPresent()) {
                            dayOfWeekSet = firstWorkDay.get();
                        }
                    }
                    dto.setWorkTime(dayOfWeekSet.getWorkTime());
                    dto.setWorkOffTime(dayOfWeekSet.getWorkOffTime());
                    dto.setOpenTime(dayOfWeekSet.getOpenTime());
                    dto.setCloseTime(dayOfWeekSet.getCloseTime());
                    dto.setNoonbreakStart(dayOfWeekSet.getNoonbreakStart());
                    dto.setNoonbreakEnd(dayOfWeekSet.getNoonbreakEnd());
                }
                workTimeEditDtoListAll.addAll(workTimeEditDtoList);
            }
            if(CollectionUtils.isNotEmpty(workTimeEditDtoListAll)){
                SysWorkTimeSet requesta = new SysWorkTimeSet();
                requesta.setOrgIds(orgIds);
                //获取所有的作息配置
                List<SysWorkTimeSet> listSet = sysWorkTimeSetMapper.selectWorkTimeSetList(requesta);
                for(Long orgId:orgIds){
                    List<SysWorkTimeSet> listSetOrg = listSet.stream().filter(f->f.getOrgId().equals(orgId)&&f.getEffectiveDate().getTime()!=effectiveDate.getTime()).collect(Collectors.toList());
                    if(CollectionUtils.isNotEmpty(listSetOrg)){
                        List<Date> dateList = new ArrayList<>();
                        dateList.add(effectiveDate);
                        listSetOrg.forEach(f->{
                            dateList.add(f.getEffectiveDate());
                        });
                        //dateList排序
                        dateList.sort(Comparator.comparing(Date::getTime));
                        //取出request.getEffectiveDate()在dateList中的位置
                        int index = dateList.indexOf(effectiveDate);
                        if(index!=dateList.size()-1){
                            Date effectiveDateNext = dateList.get(index+1);
                            //取出workTimeEditDtoListAll中ymd_date在EffectiveDate和effectiveDateNext之间的数据
                            List<SysWorkTime> workTimeEditDtoList = workTimeEditDtoListAll.stream().filter(f->f.getDate().getTime()>=effectiveDate.getTime()&&f.getDate().getTime()<effectiveDateNext.getTime()).collect(Collectors.toList());
                            batchnew(orgId,workTimeEditDtoList,list);
                        }else{
                            batchnew(orgId,workTimeEditDtoListAll,list);
                        }
                    }else{
                        batchnew(orgId,workTimeEditDtoListAll,list);
                    }

                }
            }
        }
    }
    public List<SysWorkTime> batchnew(Long orgId, List<SysWorkTime> workTimeDtoList,List<SysWorkTime> list) {
        // 小于现在时间的不允许修改
        final Date now = DateUtil.beginOfDay(new Date());
        Date updateTime = new Date();
        List<SysWorkTime> workTimeList = StreamHelper.to(workTimeDtoList, workTimeEditDto -> {
            final Date workDate = workTimeEditDto.getDate();
            if (workTimeEditDto.getIsEnable() == null || workDate.before(now)) {
//                WORKTIMELOG.info("作息时间[ {} ]小于现在时间, 不允许改变", workDate);
                return null;
            }
//            final SysWorkTime workTime = SysWorkTime.of(orgId, workTimeEditDto.getDate());
            final SysWorkTime workTime = new SysWorkTime();
            BeanHelper.copyProperties(workTime, workTimeEditDto);
            workTime.setIsManual(0L);
            workTime.setIsEnable(workTimeEditDto.getIsEnable());
            workTime.setUpdateTime(updateTime);
            if(!(workTimeEditDto.getIsEnable()>0)){
                workTime.setWorkTime(null);
                workTime.setWorkOffTime(null);
                workTime.setOpenTime(null);
                workTime.setCloseTime(null);
                workTime.setNoonbreakStart(null);
                workTime.setNoonbreakEnd(null);
            }
            return workTime;
        }, true);
        //去掉workTimeList中orgId和ymd相同的数据
        List<SysWorkTime> list1 = workTimeList.stream().filter(s -> {
            return list.stream().noneMatch(f -> f.getOrgId().equals(s.getOrgId()) && f.getYmdDate().equals(s.getYmd().getDate()));
        }).collect(Collectors.toList());
        for (SysWorkTime s :
                list1) {
              sysWorkTimeMapper.insert(s);
            workTimeList.add(s);
        }

        return workTimeList;
    }
    /**
     * 查询作息设置列表
     *
     * @param sysWorkTimeSet 作息设置
     * @return 作息设置
     */
    @Override
    public List<SysWorkTimeSet> selectSysWorkTimeSetList(SysWorkTimeSet sysWorkTimeSet) {
        return sysWorkTimeSetMapper.selectList(new QueryWrapper<>(sysWorkTimeSet));
    }

    /**
     * 新增作息设置
     *
     * @param sysWorkTimeSet 作息设置
     * @return 结果
     */
    @Override
    public int insertSysWorkTimeSet(SysWorkTimeSet sysWorkTimeSet) {
        sysWorkTimeSet.setCreateTime(DateUtils.getNowDate());
        return sysWorkTimeSetMapper.insert(sysWorkTimeSet);
    }

    /**
     * 修改作息设置
     *
     * @param sysWorkTimeSet 作息设置
     * @return 结果
     */
    @Override
    public int updateSysWorkTimeSet(SysWorkTimeSet sysWorkTimeSet) {
        sysWorkTimeSet.setUpdateTime(DateUtils.getNowDate());
        return sysWorkTimeSetMapper.updateById(sysWorkTimeSet);
    }

    /**
     * 批量删除作息设置
     *
     * @param ids 需要删除的作息设置主键
     * @return 结果
     */
    @Override
    public int deleteSysWorkTimeSetByIds(Long[] ids) {
        return sysWorkTimeSetMapper.deleteBatchIds(Arrays.asList((ids)));
    }

    /**
     * 删除作息设置信息
     *
     * @param id 作息设置主键
     * @return 结果
     */
    @Override
    public int deleteSysWorkTimeSetById(Long id) {
        return sysWorkTimeSetMapper.deleteById(id);
    }
}
