/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package com.unis.basic.info.modular.remindcycle.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.unis.auth.core.util.StpClientUtil;
import com.unis.auth.modular.login.entity.UserCollectLogin;
import com.unis.basic.info.modular.pricemonitor.enums.PriceMonitorEnum;
import com.unis.basic.info.modular.remindcycle.entity.RemindCycle;
import com.unis.basic.info.modular.remindcycle.enums.RemindCycleEnum;
import com.unis.basic.info.modular.remindcycle.mapper.RemindCycleMapper;
import com.unis.basic.info.modular.remindcycle.param.RemindCycleAddParam;
import com.unis.basic.info.modular.remindcycle.param.RemindCycleEditParam;
import com.unis.basic.info.modular.remindcycle.param.RemindCycleIdParam;
import com.unis.basic.info.modular.remindcycle.param.RemindCyclePageParam;
import com.unis.basic.info.modular.remindcycle.service.RemindCycleService;
import com.unis.common.pojo.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.unis.common.enums.CommonSortOrderEnum;
import com.unis.common.exception.CommonException;
import com.unis.common.page.CommonPageRequest;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 报送周期Service接口实现类
 *
 * @author weiyinbin
 * @date 2024/04/02 14:45
 **/
@Slf4j
@Service
public class RemindCycleServiceImpl extends ServiceImpl<RemindCycleMapper, RemindCycle> implements RemindCycleService {


    @Autowired
    private RemindCycleMapper remindCycleMapper;

    @Override
    public Page<RemindCycle> page(RemindCyclePageParam remindCyclePageParam) {
        QueryWrapper<RemindCycle> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isAllNotEmpty(remindCyclePageParam.getSortField(), remindCyclePageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(remindCyclePageParam.getSortOrder());
            queryWrapper.orderBy(true, remindCyclePageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(remindCyclePageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(RemindCycle::getId);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    /**
     * @author: hujianchun
     * @Description: 新增报送周期
     * @param:
     * @return: void
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(RemindCycleAddParam remindCycleAddParam) {

        RemindCycle remindCycle = new RemindCycle();
        BeanUtils.copyProperties(remindCycleAddParam, remindCycle);
//        Integer dayOfWeek = remindCycle.getDayOfWeek();
//        //根据周来获取对应时间节点
//        //处理对应的时间
//        Date startTime = remindCycle.getStartTime();
//        Date endTime = remindCycle.getEndTime();
//        Calendar instance = Calendar.getInstance();
//        instance.setTime(new Date());
//        int i = instance.get(Calendar.DAY_OF_WEEK) - 1;
//        instance.add(Calendar.DATE, remindCycle.getDayOfWeek() - i);
//        String format = new SimpleDateFormat("yyyyMMdd").format(instance.getTime());
//        String st = format + startTime;
//        String et = format + endTime;
//        Date date = new Date();
//        SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMddHHmmss");
//        Date sDate = null;
//        Date eDate = null;
//        try {
//            sDate = format1.parse(st);
//            eDate = format1.parse(et);
//        } catch (ParseException e) {
//            throw new CommonException("日期时间转换异常");
//        }
//        remindCycle.setStartTime(sDate);
//        remindCycle.setEndTime(eDate);
        remindCycle.setCreateTime(new Date());
        remindCycle.setUpdateTime(new Date());
        try {
            remindCycleMapper.insert(remindCycle);
        } catch (Exception e) {
            log.error("新增报送周期，操作数据库失败:[{}]", e.getMessage());
            throw new CommonException("保存新增报送周期失败");
        }


    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(RemindCycleEditParam remindCycleEditParam) {
        RemindCycle remindCycle = this.queryEntity(remindCycleEditParam.getId());
        BeanUtil.copyProperties(remindCycleEditParam, remindCycle);
        this.updateById(remindCycle);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<RemindCycleIdParam> remindCycleIdParamList) {
        // 执行删除
        this.removeByIds(CollStreamUtil.toList(remindCycleIdParamList, RemindCycleIdParam::getId));
    }

    @Override
    public RemindCycle detail(RemindCycleIdParam remindCycleIdParam) {
        return this.queryEntity(remindCycleIdParam.getId());

    }

    @Override
    public RemindCycle queryEntity(String id) {
        RemindCycle remindCycle = this.getById(id);
        if (ObjectUtil.isEmpty(remindCycle)) {
            throw new CommonException("报送周期不存在，id值为：{}", id);
        }
        return remindCycle;
    }


    /**
     * 前端调用定时报送周期的专用接口
     *
     * @author weiyinbin
     * @date 2024/04/02 14:45
     */
    @Override
    public String task() {

        //通过token获取到当前登录用户的信息
        UserCollectLogin userCollectLogin = (UserCollectLogin) StpClientUtil.getTokenSession().get("loginUser");
        if (ObjectUtil.isEmpty(userCollectLogin)) {
            throw new CommonException("无登录用户信息");
        }
        LambdaQueryWrapper<RemindCycle> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RemindCycle::getCreateUser, userCollectLogin.getId());
        List<RemindCycle> remindCycles = remindCycleMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(remindCycles)) {
            throw new CommonException("暂无数据");
        }
        //有数据，就可以开始报送
        //获取到当前用户的所有报送时间
        for (RemindCycle remindCycle : remindCycles) {

            Date date = new Date();
            // 获取当前时间的LocalTime和DayOfWeek
            LocalTime currentLocalTime = getCurrentLocalTime(date);
            int currentDayOfWeek = DateUtil.dayOfWeek(date) - 1;

            // 获取提醒周期的起始和结束时间以及DayOfWeek
            LocalTime startTime = getLocalTimeFromInstant(remindCycle.getStartTime().toInstant());
            LocalTime endTime = getLocalTimeFromInstant(remindCycle.getEndTime().toInstant());
            int remindCycleDayOfWeek = remindCycle.getDayOfWeek();

            // 判断当前时间是否在提醒周期内且当前日期为提醒周期的指定星期
            if (currentDayOfWeek == remindCycleDayOfWeek && isCurrentTimeInInterval(currentLocalTime, startTime, endTime)) {
                //结束时间的前两个小时开始报送
                LocalTime localTime = endTime.minusHours(remindCycle.getAdvanceHour());
                if (currentLocalTime.isAfter(localTime) && currentLocalTime.isBefore(endTime)) {
                    return "你有新的报送信息，请注意查看！";
                }

            }
        }
        return null;

    }

    /*
     判断当前时间是不是和报送周期相同
  */
    private boolean isCurrentDateReportDay(Date currentDate, RemindCycle cycle) {
        int currentDayOfWeek = getAdjustedDayOfWeek(currentDate);
        return currentDayOfWeek == cycle.getDayOfWeek();
    }

    private int getAdjustedDayOfWeek(Date date) {
        return DateUtil.dayOfWeek(date) - 1;
    }

    /*
        时间转换
     */
    private LocalTime getCurrentLocalTime(Date date) {
        return toLocalTime(date.toInstant());
    }

    private LocalTime getLocalTimeFromInstant(Instant instant) {
        return toLocalTime(instant);
    }

    private LocalTime toLocalTime(Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalTime();
    }

    /*
        判断在不在这个时间段内
     */
    private boolean isCurrentTimeInInterval(LocalTime currentLocalTime, LocalTime startTime, LocalTime endTime) {
        return currentLocalTime.isAfter(startTime) && currentLocalTime.isBefore(endTime);
    }
}
