package org.jeecg.modules.app.wxNotification;


import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j2;
import org.jeecg.modules.app.vo.weixin.NotificationRequest;
import org.jeecg.modules.app.weixinService.WechatNotificationService;
import org.jeecg.modules.quartz.vo.JobClassNoticeVo;
import org.jeecg.modules.quartz.vo.JobExtendedClassNoticeVo;
import org.jeecg.modules.quartz.vo.JobReservationSiteVo;
import org.jeecg.modules.system.app.entity.AppOrder;
import org.jeecg.modules.system.app.service.IAppOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Log4j2
@Service
public class WxNotificationService {


    @Autowired
    WechatNotificationService notificationService;
    @Autowired
    IAppOrderService iAppOrderService;
    private final int maxRetry = 3;
    private final List<Integer> notifyHoursBefore = Arrays.asList(8, 24);
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 上课时间服务通知  8小时和24小时
     */
    public void classNoticeJob() {

        String lockKey = "order:notification:lock";
        String lockValue = String.valueOf(System.currentTimeMillis());

        try {
            // 获取分布式锁，防止多实例重复执行
            Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 4, TimeUnit.MINUTES);
            if (locked == null || !locked) {
                log.debug("Failed to acquire notification lock, skipping this execution");
                return;
            }

            Date now = new Date();
            log.info("Start checking orders for notification at {}", now);

            // 处理每个预设的通知时间点
            for (Integer hours : notifyHoursBefore) {
                processNotificationForTimeWindow(now, hours);
            }

            log.info("Finished checking orders for notification");
        } catch (Exception e) {
            log.error("Error occurred while checking orders for notification", e);
        } finally {
            // 释放锁
            if (lockValue.equals(redisTemplate.opsForValue().get(lockKey))) {
                redisTemplate.delete(lockKey);
            }
        }
    }

    /**
     * 预约过场地通知 每天7点执行
     */
    public void siteJob() {

        String lockKey = "site:notification:lock";
        String lockValue = String.valueOf(System.currentTimeMillis());
        try {
            // 获取分布式锁，防止多实例重复执行
            Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 4, TimeUnit.MINUTES);
            if (locked == null || !locked) {
                log.debug("Failed to acquire notification lock, skipping this execution");
                return;
            }
            Date now = new Date();
            log.info("Start checking orders for notification at {}", now);

            LocalDate currentDate = LocalDate.now();
            LocalTime localTime = LocalTime.now().truncatedTo(ChronoUnit.SECONDS);

            //查询预约过学校场地的用户并通知他
           List<JobReservationSiteVo> jobReservationSiteVos =  iAppOrderService.findBySite(currentDate,localTime);

            ArrayList<NotificationRequest> notificationRequests = new ArrayList<>();
            for (JobReservationSiteVo jobReservationSiteVo : jobReservationSiteVos) {
                NotificationRequest notificationRequest = new NotificationRequest();
                notificationRequest.setOpenid(jobReservationSiteVo.getUserOpenId());
                notificationRequest.setTemplateId("ooDlPCKVLfo9njUzhUpTnFkFFhtlETpRlVLgrRtCfXk");
                JSONObject data = new JSONObject();
                // 根据模板内容设置数据项
                data.put("thing5", new JSONObject().fluentPut("value",jobReservationSiteVo.getSiteName() ));
                data.put("thing3", new JSONObject().fluentPut("value", "空闲：" +getDate(currentDate,jobReservationSiteVo.getStartTime(),jobReservationSiteVo.getEndTime()) ));
                notificationRequest.setData(data);
                notificationRequests.add(notificationRequest);
            }
            notificationService.batchSendSubscribeMessages(notificationRequests);
            log.info("Finished checking orders for notification");
        } catch (Exception e) {
            log.error("Error occurred while checking orders for notification", e);
        } finally {
            // 释放锁
            if (lockValue.equals(redisTemplate.opsForValue().get(lockKey))) {
                redisTemplate.delete(lockKey);
            }
        }
    }
    /**
     * 延课通知
     */
    public void extendedClassesJob(List<JobExtendedClassNoticeVo> jobExtendedClassNoticeVos) {
        String lockKey = "site:notification:lock";
        String lockValue = String.valueOf(System.currentTimeMillis());
        try {
            // 获取分布式锁，防止多实例重复执行
            Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 4, TimeUnit.MINUTES);
            if (locked == null || !locked) {
                log.debug("Failed to acquire notification lock, skipping this execution");
                return;
            }
            Date now = new Date();
            log.info("Start checking orders for notification at {}", now);
            ArrayList<NotificationRequest> notificationRequests = new ArrayList<>();
            for (JobExtendedClassNoticeVo jobExtendedClassNoticeVo : jobExtendedClassNoticeVos) {
                NotificationRequest notificationRequest = new NotificationRequest();
                notificationRequest.setOpenid(jobExtendedClassNoticeVo.getUserOpenId());
                notificationRequest.setTemplateId("HbK-qbIC_iTY0w08xfkgirdeR_VrVhetLwEIBo3Lue4");
                JSONObject data = new JSONObject();
                // 根据模板内容设置数据项
                data.put("thing2", new JSONObject().fluentPut("value", jobExtendedClassNoticeVo.getLassHourTime()));
                data.put("thing1", new JSONObject().fluentPut("value", jobExtendedClassNoticeVo.getSiteName()));
                data.put("thing3", new JSONObject().fluentPut("value", jobExtendedClassNoticeVo.getReasonClassExtension()));
                notificationRequest.setData(data);
                notificationRequests.add(notificationRequest);
            }
            notificationService.batchSendSubscribeMessages(notificationRequests);
            //查询被延课的数据通知他
//            iAppOrderService.findBySite();

            log.info("Finished checking orders for notification");
        } catch (Exception e) {
            log.error("Error occurred while checking orders for notification", e);
        } finally {
            // 释放锁
            if (lockValue.equals(redisTemplate.opsForValue().get(lockKey))) {
                redisTemplate.delete(lockKey);
            }
        }
    }



    private void processNotificationForTimeWindow(Date now, Integer hoursBefore) {
        long windowStart = now.getTime();
        long windowEnd = now.getTime() + hoursBefore * 3600 * 1000;
        ;
        String logPrefix = hoursBefore + "h notification";

        log.info("Processing {} for time window {} - {}", logPrefix, new Date(windowStart), new Date(windowEnd));

        // 查询需要通知的订单（未通知或重试次数未达上限）
        List<JobClassNoticeVo> list = iAppOrderService.findByJob(hoursBefore,new Date(windowEnd),maxRetry);
        if (list.isEmpty()) {
            log.debug("No orders found for {}", logPrefix);
            return;
        }

        log.info("Found {} orders for {}", list.size(), logPrefix);
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (JobClassNoticeVo jobClassNoticeVo : list) {
            try {
                // 发送到消息队列异步处理
                NotificationRequest notificationRequest = new NotificationRequest();
                notificationRequest.setOpenid(jobClassNoticeVo.getUserOpenId());
                notificationRequest.setTemplateId("T2icwNiI--oBnLfTiAniAoAJAwq1Ukb78bCjIcpuTRQ");//上课时间模板
                JSONObject data = new JSONObject();
                String date = getDate(jobClassNoticeVo.getStartTime());
                String siteName = null;
                if (jobClassNoticeVo.getSiteName()!=null){
                    siteName= jobClassNoticeVo.getSiteName().substring(0, Math.min(jobClassNoticeVo.getSiteName().length(), 20));
                }
                // 根据模板内容设置数据项
                data.put("time3", new JSONObject().fluentPut("value", date));
                data.put("thing4", new JSONObject().fluentPut("value", siteName));
                data.put("thing11", new JSONObject().fluentPut("value", "如有特殊情况不能上课，记得沟通延课"));
                notificationRequest.setData(data);
                executor.submit(() -> {
                    AppOrder appOrder = iAppOrderService.getById(jobClassNoticeVo.getOrderId());
                    if (appOrder==null){
                        log.error("上课消息通知未查询到该订单："+jobClassNoticeVo.getOrderNo()+",订单id："+jobClassNoticeVo.getOrderId());
                        return;
                    }
                    try {
                        notificationService.sendSubscribeMessage(notificationRequest);
                        if (hoursBefore==24){
                            appOrder.setNotified24h(1);
                        }else if (hoursBefore==8){
                            appOrder.setNotified24h(1);
                        }
                        iAppOrderService.updateById(appOrder);
                    } catch (Exception e) {
                        // 更新重试次数
                        appOrder.setNotifyRetryCount(appOrder.getNotifyRetryCount() + 1);
                        iAppOrderService.updateById(appOrder);
                        log.error("批量发送小程序订阅消息异常", e);
                    }
                });
                log.debug("Sent notification task for order {} to", jobClassNoticeVo.getOrderNo());
            } catch (Exception e) {
                log.error("Failed to send notification task for order {}", jobClassNoticeVo.getOrderNo(), e);
            }
        }
    }
    private String getDate(Date date){
        if (date==null){
            return "未知时间";
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
        return sdf.format(date);
    }

    private String getDate(LocalDate currentDate  ,Date startTime,Date endTime){

        if (startTime==null|| endTime==null){
            return null;
        }
        // 将 Date 转换为 LocalDateTime
        LocalDateTime startLdt = LocalDateTime.ofInstant(startTime.toInstant(), java.time.ZoneId.systemDefault());
        LocalDateTime endLdt = LocalDateTime.ofInstant(endTime.toInstant(), java.time.ZoneId.systemDefault());
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM.dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        String formattedDate = currentDate.format(dateFormatter);
        String formattedStartTime = startLdt.format(timeFormatter);
        String formattedEndTime = endLdt.format(timeFormatter);
        return   formattedDate + " " + formattedStartTime + "-" + formattedEndTime;
    }
}
