package com.xunmei.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.google.common.collect.Lists;
import com.xunmei.common.core.utils.DateUtils;
import com.xunmei.common.core.utils.Ymd;
import com.xunmei.common.core.web.page.TableDataInfo;
import com.xunmei.common.security.utils.SecurityUtils;
import com.xunmei.system.api.domain.SysWorkTime;
import com.xunmei.system.domain.SysWorkTimeSet;
import com.xunmei.system.dto.SysWorkTimeDto;
import com.xunmei.system.mapper.SysWorkTimeMapper;
import com.xunmei.system.mapper.SysWorkTimeSetMapper;
import com.xunmei.system.service.ISysOrgService;
import com.xunmei.system.service.ISysWorkTimeService;
import com.xunmei.system.util.WorkChangeEvent;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author xunmei
 * @date 2023-08-14
 */
@Service
public class SysWorkTimeServiceImpl extends ServiceImpl<SysWorkTimeMapper, SysWorkTime> implements ISysWorkTimeService {
    @Autowired
    private SysWorkTimeMapper sysWorkTimeMapper;
    @Autowired
    private ISysOrgService orgService;
    @Autowired
    private SysWorkTimeSetMapper sysWorkTimeSetMapper;
    @Autowired
    private ApplicationContext context;


    @Override
    public TableDataInfo<SysWorkTime> selectPage(SysWorkTime sysWorkTime) {


        //未删除
//        sysWorkTime.setDeleted(0L);
        Page<SysWorkTime> page;
        //分页
        if (sysWorkTime.getPageNum() != null && sysWorkTime.getPageSize() != null) {
            page = new Page<>(sysWorkTime.getPageNum(), sysWorkTime.getPageSize());
        } else {
            page = new Page<>();
        }
        //查询条件
        QueryWrapper<SysWorkTime> query = new QueryWrapper<>();
        if (sysWorkTime.getIsEnable() != null) {
            query.eq("t.is_enable", sysWorkTime.getIsEnable());
        }
        if (sysWorkTime.getOrgId() != null && !sysWorkTime.getCheckSub()) {
            query.eq("t.org_id", sysWorkTime.getOrgId());
        }
        if (sysWorkTime.getModifiedName() != null) {
            query.eq("t.modified_name", sysWorkTime.getModifiedName());
        }
        //下穿
        if (sysWorkTime.getCheckSub()) {
            List<Long> ids = orgService.selectCheckSubOrgIdList(sysWorkTime.getOrgId());
            //清空前端传递的org_id
            sysWorkTime.setOrgId(null);
            //添加in条件
            query.in("t.org_id", ids);
        }
        query.orderByDesc("ymd_date");
        //时间范围查询
        if (sysWorkTime.getRange() != null && sysWorkTime.getRange().length > 1) {
            query.between("t.ymd_date", sysWorkTime.getRange()[0], sysWorkTime.getRange()[1]);
        }
        //获取数据
        IPage<SysWorkTimeDto> page1 = sysWorkTimeMapper.selectByPage(page, query);
        //抓换为TableDataInfo适配前端
        return TableDataInfo.build(page);


    }

    @Override
    public Map<String, Object> checkData(SysWorkTimeSet sysWorkTime) {
        Map<String, Object> map = new HashMap<>();
        List<SysWorkTimeSet> setList = sysWorkTimeSetMapper.findWorkTimeForOrgIdsAndErrectiveDate(sysWorkTime.getOrgIds(), sysWorkTime.getEffectiveDate());
        if (setList.size() > 0 && sysWorkTime.getId() == null || setList.size() > 1 && (sysWorkTime.getId() != null && !sysWorkTime.getId().equals(setList.get(0).getId()))) {
            throw new RuntimeException("机构中已存" + DateUtil.format(sysWorkTime.getEffectiveDate(), "yyyy-MM-dd") + "的作息模版，请核查数据");
        }
        //如果生效日期是本月或下月则返回
        if (!DateUtil.isSameMonth(sysWorkTime.getEffectiveDate(), new Date()) && !DateUtil.isSameMonth(sysWorkTime.getEffectiveDate(), DateUtil.offsetMonth(new Date(), 1))) {
            return map;
        }
        ;

        int num = sysWorkTimeSetMapper.checkData(sysWorkTime);
        List<SysWorkTimeSet> list = sysWorkTimeSetMapper.selectList(new QueryWrapper<>(sysWorkTime));
        if (CollectionUtil.isNotEmpty(list)) {
            //将list 按照orgId分组
            Map<Long, List<SysWorkTimeSet>> orgMap = list.stream().collect(Collectors.groupingBy(SysWorkTimeSet::getOrgId));
            //遍历orgMap
            StringBuffer sbf = new StringBuffer();
            for (Long key : orgMap.keySet()) {
                List<SysWorkTimeSet> wo = orgMap.get(key);
                //遍历wo
                List<Date> dateList = new ArrayList<>();
                dateList.add(sysWorkTime.getEffectiveDate());
                if (CollectionUtil.isNotEmpty(wo)) {
                    for (SysWorkTimeSet vo : wo) {
                        dateList.add(vo.getEffectiveDate());
                    }
                }
                //dateList排序
                dateList.sort(Comparator.comparing(Date::getTime));
                //取出sysWorkTime.getEffectiveDate()在dateList中的位置
                int index = dateList.indexOf(sysWorkTime.getEffectiveDate());
                if (index != dateList.size() - 1) {
                    //不是最后一个
                    Date nextDate = dateList.get(index + 1);
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(nextDate);
                    calendar.add(Calendar.DAY_OF_MONTH, -1);
                    calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
                    Date lastDate = calendar.getTime();
                    //判断sysWorkTime.getEffectiveDate()与lastDate日期是否相同
                    if (!DateUtil.isSameDay(sysWorkTime.getEffectiveDate(), lastDate)) {
                        sbf.append("[" + wo.get(0).getOrgName() + DateUtil.format(sysWorkTime.getEffectiveDate(), "yyyy-MM-dd") + "到" + DateUtil.format(lastDate, "yyyy-MM-dd") + "]\n\r");
                    }
                } else {
                    //是最后一个
//                         Date nextDate = dateList.get(index-1);
//                         Calendar calendar = Calendar.getInstance();
//                         calendar.setTime(nextDate);
//                         calendar.add(Calendar.DAY_OF_MONTH,+1);
//                         calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
//                         Date lastDate = calendar.getTime();
                    //判断sysWorkTime.getEffectiveDate()是当月还是下月
                    Date lastDate = DateUtil.endOfMonth(DateUtil.offsetMonth(new Date(), 1));
//                           if(DateUtil.isSameMonth(sysWorkTime.getEffectiveDate(),new Date())){
//                               //如果是当月，则取下月最后一天
//                                 lastDate = DateUtil.endOfMonth(DateUtil.offsetMonth(new Date(),1));
//                           }else{
//                                 //如果是下月，则取下下月最后一天
//                                 lastDate = DateUtil.endOfMonth(DateUtil.offsetMonth(new Date(),1));
//                           }

                    //判断sysWorkTime.getEffectiveDate()与当前日期是否相同
                    if (!DateUtil.isSameDay(sysWorkTime.getEffectiveDate(), new Date())) {
                        sbf.append("[" + wo.get(0).getOrgName() + DateUtil.format(sysWorkTime.getEffectiveDate(), "yyyy-MM-dd") + "到" + DateUtil.format(lastDate, "yyyy-MM-dd") + "]\n\r");
                    }

                }
            }
            map.put("checkMsg", StringUtils.isNotEmpty(sbf.toString()) ? sbf.toString() : null);
        }
        map.put("checkData", num);
        return map;
    }

    @Override
    public List<Long> findOrgIdsByYmd(String toYmd) {
        return this.baseMapper.findOrgIdsByYmd(toYmd);
    }

    @Override
    public SysWorkTime findWorkTimeByYmd(Long orgId, Ymd ymd, boolean isEnable) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = ymd.getYear() + "-" + ymd.getMonth() + "-" + ymd.getDay();
        Date date = null;
        try {
            date = sdf.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        QueryWrapper<SysWorkTime> queryWrapper = new QueryWrapper();
        if (orgId != null) {
            queryWrapper.eq("org_id", orgId);
        }
//        if (ymd.getYear() != null) {
//            queryWrapper.eq("ymd_year", ymd.getYear());
//        }
//        if (ymd.getMonth() != null) {
//            queryWrapper.eq("ymd_month", ymd.getMonth());
//        }
//        if (ymd.getDay() != null) {
//            queryWrapper.eq("ymd_day", ymd.getDay());
//        }
        queryWrapper.eq("ymd_date", date);
        queryWrapper.eq("is_enable", isEnable);
        List<SysWorkTime> workTimes = this.baseMapper.selectList(queryWrapper);
        if (workTimes != null && workTimes.size() > 0) {
            return workTimes.get(0);
        } else {
            return null;
        }
    }

    /**
     * 查询【请填写功能名称】
     *
     * @param id 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public SysWorkTime selectSysWorkTimeById(String id) {
        SysWorkTime sysWorkTime = sysWorkTimeMapper.selectById(id);
        if (sysWorkTime != null) {
            sysWorkTime.setOrgName(orgService.selectSysOrgById(sysWorkTime.getOrgId()).getName());
        }
        return sysWorkTime;
    }

    private boolean timesetIsEqual(SysWorkTime workTime, SysWorkTime dto) {
        return workTime.getIsEnable().equals(dto.getIsEnable())
                && StringUtils.equals(workTime.getOpenTime(), dto.getOpenTime()) && StringUtils.equals(workTime.getWorkTime(), dto.getWorkTime())
                && StringUtils.equals(workTime.getNoonbreakStart(), dto.getNoonbreakStart()) && StringUtils.equals(workTime.getNoonbreakEnd(), dto.getNoonbreakEnd())
                && StringUtils.equals(workTime.getWorkOffTime(), dto.getWorkOffTime()) && StringUtils.equals(workTime.getCloseTime(), dto.getCloseTime());
    }

    @Override
    public void handleTodayChanged(List<Long> orgIdList, List<SysWorkTime> workTimeList, List<SysWorkTime> exists, Date today) {
//        Optional<SysWorkTimeSet> todaySet = workTimeList.stream().filter(t -> DateUtil.beginOfDay(t.getDate()).equals(today)).findFirst();
//        if (todaySet.isPresent()) {
//            List<Long> todayChanged = exists.stream().filter(e -> !timesetIsEqual(e, todaySet.get())).map(WorkTime::getOrgId).collect(Collectors.toList());
//            List<Long> existOrgIds = exists.stream().map(SysWorkTime::getOrgId).collect(Collectors.toList());
//            List<Long> addOrgIds = orgIdList.stream().filter(o -> existOrgIds.indexOf(o) < 0).collect(Collectors.toList());
//            todayChanged.addAll(addOrgIds);
//            if (CollectionUtil.isNotEmpty(todayChanged)) {
//                WORKTIMELOG.info("以下机构今日作息变更，重新生成履职：" + JSON.toJSONString(todayChanged));
//                context.publishEvent(WorkChangeEvent.builder().orgIds(todayChanged).dateTime(DateTime.of(today)).build());
//            } else {
//                WORKTIMELOG.info("今日作息变更,今日作息未变化");
//                WORKTIMELOG.info("今日变化todayChanged：" + JSON.toJSONString(todayChanged));
//                WORKTIMELOG.info("今日变化existOrgIds：" + JSON.toJSONString(existOrgIds));
//                WORKTIMELOG.info("今日变化orgIdList：" + JSON.toJSONString(orgIdList));
//            }
//        } else {
//            WORKTIMELOG.info("今日作息变更，未找到今日作息配置数据" + DateUtil.format(today, "yyyy-MM-dd"));
//            WORKTIMELOG.info("配置数据:" + JSON.toJSONString(workTimeList));
//        }
    }

    @Override
    public List<SysWorkTime> findByYmd(List<Long> orgIds, Date ymd) {
        return sysWorkTimeMapper.findByYmd(orgIds, DateUtil.format(ymd, "yyyy-MM-dd"));
    }

    @Override
    public List<SysWorkTime> findByOrgAndMonth(SysWorkTime sysWorkTime) {
        //查询当月的作息时间
        //从requestmonth中获取 年月
        Date month = sysWorkTime.getMonth();
        String monthStr = DateUtil.format(month, "yyyy-MM");
        sysWorkTime.setMonthStr(monthStr);
        //通过月份获取当月第一天和最后一天
        Date fistDate = DateUtil.beginOfMonth(month);
        Date lastDate = DateUtil.endOfMonth(month);
        List<SysWorkTime> workTimeOnAppVos = sysWorkTimeMapper.findByOrgAndDate(sysWorkTime.getOrgId(), fistDate, lastDate);
        final List<DateTime> dateTimeList = DateUtil.rangeToList(fistDate, lastDate, DateField.DAY_OF_MONTH);
        //遍历dateTimeList
        List<SysWorkTime> workTimeOnAppVoList = new ArrayList<>();
        for (DateTime dateTime : dateTimeList) {
            SysWorkTime workTimeOnAppVo = new SysWorkTime();
            workTimeOnAppVo.setYmdDate(dateTime);
            workTimeOnAppVoList.add(workTimeOnAppVo);
        }
        for (SysWorkTime vo : workTimeOnAppVos) {
            for (DateTime dateTime : dateTimeList) {
                if (DateUtil.isSameDay(dateTime, vo.getYmdDate())) {
                    //获取dateTime的下标
                    int index = dateTimeList.indexOf(dateTime);
                    //将workTimeOnAppVoList中index位置的对象替换成vo
                    workTimeOnAppVoList.set(index, vo);
                }
            }
        }
        return workTimeOnAppVoList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public List<SysWorkTime> batchnew(Long orgId, List<SysWorkTime> workTimeDtoList) {
        Date now = DateUtil.beginOfDay(new Date());
        Date updateTime = new Date();

        for (SysWorkTime s : workTimeDtoList) {
            if (s.getIsEnable() == null || s.getYmdDate().before(now)) {
//                WORKTIMEBUSINESSLOG.info("作息时间[ {} ]小于现在时间, 不允许改变", workDate);
//                return null;
            } else {
                s.setId(null);
                s.setOrgId(orgId);
                s.setIsManual(1L);
                s.setUpdateTime(updateTime);

                baseMapper.insert(s);

            }

        }
        return workTimeDtoList;
    }

    @Override
    public boolean existByYmd(Long orgId, Ymd ymd, boolean isEnable) {
        QueryWrapper<SysWorkTime> queryWrapper = new QueryWrapper<>();
        if (ymd.getDay() != null) {
            queryWrapper.eq("ymd_day", ymd.getDay());
        }
        if (ymd.getMonth() != null) {
            queryWrapper.eq("ymd_month", ymd.getMonth());
        }
        if (ymd.getWeek() != null) {
            queryWrapper.eq("ymd_week", ymd.getWeek());
        }
        return sysWorkTimeMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 查询【请填写功能名称】列表
     *
     * @param sysWorkTime 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<SysWorkTime> selectSysWorkTimeList(SysWorkTime sysWorkTime) {
        return sysWorkTimeMapper.selectList(new QueryWrapper<>(sysWorkTime));
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param sysWorkTime 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int insertSysWorkTime(SysWorkTime sysWorkTime) {
        sysWorkTime.setCreateTime(DateUtils.getNowDate());
        return sysWorkTimeMapper.insert(sysWorkTime);
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param sysWorkTime 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int updateSysWorkTime(SysWorkTime sysWorkTime) {

        sysWorkTime.setUpdateTime(DateUtils.getNowDate());
        sysWorkTime.setModifiedName(SecurityUtils.getUsername());
        sysWorkTime.setModifiedId(SecurityUtils.getUserId());
        if (DateUtil.format(sysWorkTime.getYmd().getDate(), "yyyy-MM-dd").equals(DateUtil.format(new Date(), "yyyy-MM-dd"))) {
            context.publishEvent(WorkChangeEvent.builder().orgIds(Lists.newArrayList(sysWorkTime.getOrgId())).dateTime(DateTime.of(sysWorkTime.getYmd().getDate())).build());
        }
        return sysWorkTimeMapper.updateById(sysWorkTime);
    }

    /**
     * 批量删除【请填写功能名称】
     *
     * @param ids 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteSysWorkTimeByIds(String[] ids) {
        return sysWorkTimeMapper.deleteBatchIds(Arrays.asList((ids)));
    }

    /**
     * 删除【请填写功能名称】信息
     *
     * @param id 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteSysWorkTimeById(String id) {
        return sysWorkTimeMapper.deleteById(id);
    }
}
