package com.ruoyi.system.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.ZsOperationGoodsMapper;
import com.ruoyi.system.mapper.ZsOperationSendconfigMapper;
import com.ruoyi.system.mapper.ZsOperationWarnconfigMapper;
import com.ruoyi.system.mapper.ZsOperationWarnresultMapper;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.utils.EmailUtils;
import com.ruoyi.system.utils.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

@Component
@Slf4j
public class MonitorTaskScheduler {

  //  private final ThreadPoolTaskScheduler taskScheduler;
    private ScheduledFuture<?> scheduledTask;
    @Autowired
    private ZsOperationWarnconfigMapper zsOperationWarnconfigMapper;
    @Autowired
    private ZsOperationGoodsMapper zsOperationGoodsMapper;
    @Autowired
    private ZsOperationWarnresultMapper zsOperationWarnresultMapper;
    @Autowired
    private ZsOperationSendconfigMapper zsOperationSendconfigMapper;
    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private ISysDictDataService iSysDictDataService;

    @Autowired
    private SpringTemplateEngine templateEngine;
/*    public MonitorTaskScheduler( ) {
        this.taskScheduler = new ThreadPoolTaskScheduler();
        this.taskScheduler.setPoolSize(1);
        this.taskScheduler.initialize();
    }*/

/*    @PostConstruct
    public void init() {
        // 启动时从数据库加载初始配置
        rescheduleTask();
    }

    //查询配置 并设置定时任务
    public void rescheduleTask() {
        // 取消当前任务
        if (scheduledTask != null) {
            scheduledTask.cancel(true);
        }
        // 根据新的频率重新调度
        List<ZsOperationWarnconfig> zsOperationWarnconfigs =  zsOperationWarnconfigMapper.selectList();
        if (zsOperationWarnconfigs!=null&&zsOperationWarnconfigs.size()>0) {
            ZsOperationWarnconfig zsOperationWarnconfig = zsOperationWarnconfigs.get(0);
            String frequency = zsOperationWarnconfig.getMonitorFrequency();
            //如果是null或者不是数字 默认为1小时
            if (StringUtils.isBlank(frequency)||!frequency.matches("\\d+")) {
                frequency = "1";
            }
            String cron = convertFrequencyToCron(Integer.parseInt(frequency));
            //
            scheduledTask = taskScheduler.schedule(
                () -> monitorWarn(zsOperationWarnconfig),
                new CronTrigger(cron)
            );
        }
    }*/

    //比对商品价格编号是否超过了阈值 并记录
    public void monitorWarn(ZsOperationWarnconfig zsOperationWarnconfig) {
        //1.查询启用的商品
        QueryWrapper<ZsOperationGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_disabled",1);
        List<ZsOperationGoods> zsOperationGoodsList =zsOperationGoodsMapper.selectList(queryWrapper);
        //2.遍历商品
        if (zsOperationGoodsList!=null&&zsOperationGoodsList.size()>0) {
            for (ZsOperationGoods zsOperationGoods: zsOperationGoodsList) {
                String curUrl = zsOperationGoods.getGoodsSkuUrl();
                //3.根据url 获取商品最新信息
                log.info("调用接口开始");
                Map<String, Object> reMap =  HttpUtil.sendGetRequest(curUrl,false,zsOperationGoods.getPlatform());
                log.info("调用接口结束");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if ((boolean)reMap.get("success")) {
                    List dataList = (List)reMap.get("data");
                    Map dataMap = (Map)dataList.get(0);
                    String newName = (String)dataMap.get("title");
                    String newSn = (String)dataMap.get("sku");
                    String newRemark = (String)dataMap.get("remark");
                    zsOperationGoods.setGoodsSkuName(newName);
                    zsOperationGoods.setGoodsSkuSn(newSn);
                    zsOperationGoods.setRemark(newRemark);

                    //4.更新商品表和预警结果表信息
                    UpdateWrapper goodsUpdateWrapper = new UpdateWrapper<>();
                    goodsUpdateWrapper.eq("goods_sku_url",curUrl);
                    goodsUpdateWrapper.set("goods_sku_name",newName);
                    goodsUpdateWrapper.set("goods_sku_sn",newSn);
                    goodsUpdateWrapper.set("remark",newRemark);
                    int j = zsOperationGoodsMapper.update(null,goodsUpdateWrapper);
                    UpdateWrapper<ZsOperationWarnresult> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("goods_sku_url",curUrl);
                    updateWrapper.set("goods_sku_name",newName);
                    updateWrapper.set("goods_sku_sn",newSn);
                    int i = zsOperationWarnresultMapper.update(null,updateWrapper);


                    String newPriceStr = (String)dataMap.get("price");
                    if (StringUtils.isNotBlank(newPriceStr)) {
                        newPriceStr =newPriceStr.replace(",","").trim();
                        BigDecimal newPrice = new BigDecimal(newPriceStr);
                        //如果新价格大于0
                        if (newPrice.compareTo(BigDecimal.ZERO) > 0) {
                            //判断这个商品最新的价格是否已经存在预警结果表了，如果在不发送消息和生成结果
                            if (checkIsExistsWarnResult(curUrl,newPrice)) {
                                log.info("已经存在预警结果表，并且价格没有再次变化，不记录 url=:"+curUrl);
                                continue;
                            }

                            //获取基准价格
                            BigDecimal initPrice = zsOperationGoods.getInitPrice();
                            //5. 获取基准价格和最新价格的差值比例
                            BigDecimal percentageChange= getChangeThreshold(initPrice,newPrice);
                            //我们设置的预警阈值
                            BigDecimal priceChange  = new BigDecimal(zsOperationWarnconfig.getPriceChangeThreshold());
                            // 6.比较差值比例是否大于等于我们设置的预警阈值
                            if (percentageChange.compareTo(priceChange) >= 0) {
                                //7.生成 预警结果数据
                                String warnTypes = zsOperationWarnconfig.getWarnTypes();
                                ZsOperationWarnresult zsOperationWarnresult = new ZsOperationWarnresult();
                                zsOperationWarnresult.setWarnTime(new Date());
                                zsOperationWarnresult.setGoodsSkuName(zsOperationGoods.getGoodsSkuName());
                                zsOperationWarnresult.setGoodsSkuSn(zsOperationGoods.getGoodsSkuSn());
                                zsOperationWarnresult.setGoodsSkuUrl(curUrl);
                                zsOperationWarnresult.setInitPrice(initPrice);
                                zsOperationWarnresult.setCurPrice(newPrice);
                                zsOperationWarnresult.setPriceChangeRatio(percentageChange.toString());
                                zsOperationWarnresult.setWarnTypes(warnTypes);
                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                String warnDate = sdf.format(zsOperationWarnresult.getWarnTime());
                                String warnContent = "<html>" +
                                    "<h2>商品价格发生变动！</h2>"+
                                    "<p>商品名称=:"+zsOperationGoods.getGoodsSkuName()+"</p>"+
                                    "<p>商品编号=:"+newSn+"</p>"+
                                    "<p>商品url=:"+curUrl+"</p>"+
                                    "<p>原价格=:"+initPrice+"</p>"+
                                    "<p>新价格=:"+newPrice.doubleValue()+"</p>"+
                                    "<p>预警时间=:"+warnDate+"</p>"+
                                    "<p>图片=:"+"<img src=\""+dataMap.get("screenshotUrl")+"\" ></p>"+
                                    "</html>";
                                zsOperationWarnresult.setWarnContent(warnContent);
                                zsOperationWarnresult.setSnapshotUrl((String)dataMap.get("screenshotUrl"));
                                zsOperationWarnresult.setStatus(0);
                                zsOperationWarnresult.setPlatform(zsOperationGoods.getPlatform());
                                zsOperationWarnresult.setCompareStatus(1);
                                zsOperationWarnresultMapper.insert(zsOperationWarnresult);

                                //8.发送邮件
                                QueryWrapper<ZsOperationSendconfig> sendWrapper= new QueryWrapper<>();
                                sendWrapper.eq("module",0);
                                sendWrapper.in("code",warnTypes.split(","));
                                //根据预警编码   查询出对应的预警信息接收地址
                                List<ZsOperationSendconfig> zsOperationSendconfigList = zsOperationSendconfigMapper.selectList(sendWrapper);
                                if (zsOperationSendconfigList!=null&&zsOperationSendconfigList.size()>0) {
                                    for (ZsOperationSendconfig zsOperationSendconfig : zsOperationSendconfigList) {
                                        String receiveEmailStr = zsOperationSendconfig.getConfigValue();
                                        String[] receiveEmails = receiveEmailStr.split(",");
                                        for (String receiveEmail : receiveEmails) {
                                            String platformName = iSysDictDataService.selectDictLabel("zs_operation_platform",zsOperationGoods.getPlatform());
                                            String title = "Digital System 系统提醒：您所监控的 "+platformName+" 商品已发生价格波动";

                                            WarnEmail warnEmail = new WarnEmail();
                                            warnEmail.setPlatformName(platformName);
                                            warnEmail.setSkuName(zsOperationGoods.getGoodsSkuName());
                                            warnEmail.setSkuSn(newSn);
                                            warnEmail.setSkuUrl(curUrl);
                                            warnEmail.setWarnTime(warnDate);
                                            warnEmail.setCurPrice(initPrice.toString());
                                            warnEmail.setNewPrice(newPrice.toString());
                                            warnEmail.setImagePath((String)dataMap.get("screenshotUrl"));
                                            Context context = new Context();
                                            context.setVariable("warnEmail", warnEmail);
                                            String warnContentHtml = templateEngine.process("warnEmail", context);
                                            //发送数据 1立刻发送 0 9:00-18:00 发送
                                            String warnTimeRange = zsOperationWarnconfig.getWarnTimeRange();
                                            if ("1".equals(warnTimeRange)) {
                                                emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,title,warnContentHtml,zsOperationSendconfig.getSmtpId());
                                            } else {
                                                if (isBetween9And18()) {
                                                    emailUtils.sendMailByTransportHtml(zsOperationSendconfig.getSendEmail(),receiveEmail,title,warnContentHtml,zsOperationSendconfig.getSmtpId());
                                                }
                                            }
                                        }
                                    }
                                } else {
                                    log.info("没有设置对应的预警配置");
                                }

                            } else {
                                log.info("商品:"+newName+";价格变动小于阈值，不生成比对结果;本次变动幅度=:"+percentageChange);
                            }
                        } else {
                            log.info("商品:"+newName+";新价格为0，不生成比对结果");
                        }
                    }
                } else {
                    log.info("商品同步数据失败！ curUrl="+curUrl+",reMap="+reMap.toString());
                    //7.生成 预警结果数据
                    String warnTypes = zsOperationWarnconfig.getWarnTypes();
                    ZsOperationWarnresult zsOperationWarnresult = new ZsOperationWarnresult();
                    zsOperationWarnresult.setWarnTime(new Date());
                    zsOperationWarnresult.setGoodsSkuName(zsOperationGoods.getGoodsSkuName());
                    zsOperationWarnresult.setGoodsSkuSn(zsOperationGoods.getGoodsSkuSn());
                    zsOperationWarnresult.setGoodsSkuUrl(curUrl);
                    zsOperationWarnresult.setInitPrice(zsOperationGoods.getInitPrice());
                    zsOperationWarnresult.setCurPrice(null);
                    zsOperationWarnresult.setPriceChangeRatio("");
                    zsOperationWarnresult.setWarnTypes(warnTypes);
                    String warnContent = "商品编号:"+zsOperationGoods.getGoodsSkuSn()+"抓取失败！";
                    zsOperationWarnresult.setWarnContent(warnContent);
                    zsOperationWarnresult.setStatus(0);
                    zsOperationWarnresult.setPlatform(zsOperationGoods.getPlatform());
                    zsOperationWarnresult.setCompareStatus(0);
                    zsOperationWarnresultMapper.insert(zsOperationWarnresult);
                }
            }
        }
    }




    //生成定时任务cron表达式
    private String convertFrequencyToCron(int frequency) {
        // 将频率转换为Cron表达式，例如1小时一次："0 0 0/1 * * ?"
        return "0 0 0/" + frequency + " * * ?";
    }
    /**
     * 判断价格变化是否超过阈值
     * @param curPrice 当前价格（基准价）
     * @param newPrice 新价格
     * @return 变化幅度超过阈值返回true，否则false
     */
    public  BigDecimal getChangeThreshold(BigDecimal curPrice,BigDecimal newPrice) {
        // 参数校验
        if (curPrice == null || newPrice == null ) {
            throw new IllegalArgumentException("参数不能为空");
        }
        // 计算价格变化绝对值
        BigDecimal diff = newPrice.subtract(curPrice).abs();
        // 计算百分比变化（保留4位小数）
        BigDecimal percentageChange = diff.divide(curPrice, 4, RoundingMode.HALF_UP)
            .multiply(new BigDecimal("100"));
        return percentageChange;
    }
     //判断是否是9-18点
    public boolean isBetween9And18() {
        LocalTime currentTime = LocalTime.now();
        LocalTime startTime = LocalTime.of(9, 0);   // 9:00
        LocalTime endTime = LocalTime.of(18, 0);    // 18:00
        // 判断当前时间是否在 [9:00, 18:00] 区间（包含边界）
        return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime);
    }
    public boolean checkIsExistsWarnResult(String url,BigDecimal newPrice) {
        boolean isExists = false;
        QueryWrapper<ZsOperationWarnresult> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_sku_url",url);
        queryWrapper.eq("status",0);
        queryWrapper.orderByDesc("warn_time");
        List<ZsOperationWarnresult> list = zsOperationWarnresultMapper.selectList(queryWrapper);
        if (list!=null&&list.size()>0) {
            ZsOperationWarnresult zsOperationWarnresult = list.get(0);
            BigDecimal curPrice = zsOperationWarnresult.getCurPrice();
            if (curPrice!=null&&newPrice.compareTo(curPrice)==0) {
                isExists = true;
            }
        }
        return isExists;
    }

}
