package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.ZsOperationGoodsDetailBo;
import com.ruoyi.system.mapper.ZsOperationGoodsMapper;
import com.ruoyi.system.mapper.ZsOperationSendconfigMapper;
import com.ruoyi.system.mapper.ZsOperationWarnconfigMapper;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.IZsOperationGoodsDetailService;
import com.ruoyi.system.utils.DateUtil;
import com.ruoyi.system.utils.EmailUtils;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.domain.bo.ZsOperationWarnresultBo;
import com.ruoyi.system.domain.vo.ZsOperationWarnresultVo;
import com.ruoyi.system.mapper.ZsOperationWarnresultMapper;
import com.ruoyi.system.service.IZsOperationWarnresultService;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 预警结果Service业务层处理
 *
 * @author 王强
 * @date 2025-05-12
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class ZsOperationWarnresultServiceImpl implements IZsOperationWarnresultService {

    private final ZsOperationWarnresultMapper baseMapper;
    @Autowired
    private ZsOperationWarnconfigMapper zsOperationWarnconfigMapper;
    @Autowired
    private ZsOperationGoodsMapper zsOperationGoodsMapper;
    @Autowired
    private ZsOperationWarnresultMapper zsOperationWarnresultMapper;

    @Autowired
    private ZsOperationSendconfigMapper zsOperationSendconfigMapper;

    @Autowired
    private ISysDictDataService iSysDictDataService;

    @Autowired
    private SpringTemplateEngine templateEngine;
    @Autowired
    private EmailUtils emailUtils;
    @Autowired
    private IZsOperationGoodsDetailService iZsOperationGoodsDetailService;
    /**
     * 查询预警结果
     */
    @Override
    public ZsOperationWarnresultVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询预警结果列表
     */
    @Override
    public TableDataInfo<ZsOperationWarnresultVo> queryPageList(ZsOperationWarnresultBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ZsOperationWarnresult> lqw = buildQueryWrapper(bo);
        Page<ZsOperationWarnresultVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<ZsOperationWarnresultVo> warnList = result.getRecords();
        List<String> urls = new ArrayList<>();
        if (warnList!=null&&warnList.size()>0) {
            for (ZsOperationWarnresultVo zsOperationWarnresultVo : warnList) {
                String url = zsOperationWarnresultVo.getGoodsSkuUrl();
                urls.add(url);
            }
            QueryWrapper<ZsOperationGoods> queryWrapper = new QueryWrapper();
            queryWrapper.in("goods_sku_url",urls);
            List<ZsOperationGoods> goodsList = zsOperationGoodsMapper.selectList(queryWrapper);
            result.setRecords(getRemark(warnList,goodsList));
        }
        return TableDataInfo.build(result);
    }

    private List<ZsOperationWarnresultVo> getRemark(List<ZsOperationWarnresultVo> warns, List<ZsOperationGoods> goods) {
        // 使用Optional处理null值
        Map<String, String> goodsMap = goods.stream()
            .collect(Collectors.toMap(
                ZsOperationGoods::getGoodsSkuUrl,
                item -> Optional.ofNullable(item.getRemark()).orElse("")
            ));

        // 安全遍历赋值
        warns.forEach(warn -> {
            String remark = goodsMap.get(warn.getGoodsSkuUrl());
            warn.setRemark(remark != null && !remark.isEmpty() ? remark : warn.getRemark());
        });
        return warns;
    }

    /**
     * 查询预警结果列表
     */
    @Override
    public List<ZsOperationWarnresultVo> queryList(ZsOperationWarnresultBo bo) {
        LambdaQueryWrapper<ZsOperationWarnresult> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ZsOperationWarnresult> buildQueryWrapper(ZsOperationWarnresultBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ZsOperationWarnresult> lqw = Wrappers.lambdaQuery();
        lqw.between(params.get("beginWarnTime") != null && params.get("endWarnTime") != null,
            ZsOperationWarnresult::getWarnTime ,params.get("beginWarnTime"), params.get("endWarnTime"));
        lqw.like(StringUtils.isNotBlank(bo.getGoodsSkuName()), ZsOperationWarnresult::getGoodsSkuName, bo.getGoodsSkuName());
        lqw.eq(StringUtils.isNotBlank(bo.getGoodsSkuSn()), ZsOperationWarnresult::getGoodsSkuSn, bo.getGoodsSkuSn());
        lqw.eq(bo.getStatus() != null, ZsOperationWarnresult::getStatus, bo.getStatus());
        lqw.eq(bo.getCompareStatus() != null, ZsOperationWarnresult::getCompareStatus, bo.getCompareStatus());
        //按照预警时间倒叙排列
        lqw.orderByDesc(ZsOperationWarnresult::getWarnTime);
        return lqw;
    }

    /**
     * 新增预警结果
     */
    @Override
    public Boolean insertByBo(ZsOperationWarnresultBo bo) {
        ZsOperationWarnresult add = BeanUtil.toBean(bo, ZsOperationWarnresult.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改预警结果
     */
    @Override
    public Boolean updateByBo(ZsOperationWarnresultBo bo) {
        //已处理  修改商品基准价格为当前最新价格
        if(bo.getStatus()==1) {
            String url = bo.getGoodsSkuUrl();
            ZsOperationWarnresultVo zsOperationWarnresultVo = baseMapper.selectVoById(bo.getId());
            UpdateWrapper<ZsOperationGoods> updateWrapper =new UpdateWrapper();
            updateWrapper.set("init_price",zsOperationWarnresultVo.getCurPrice());
            updateWrapper.eq("goods_sku_url",url);
            //updateWrapper.eq("is_disabled",1);
            int i = zsOperationGoodsMapper.update(null,updateWrapper);
            if (i>=1) {
                ZsOperationWarnresult update = BeanUtil.toBean(bo, ZsOperationWarnresult.class);
                validEntityBeforeSave(update);
                return baseMapper.updateById(update) > 0;
            }
        }
        return false;

    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ZsOperationWarnresult entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除预警结果
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    //接收预警数据
    @Override
    public Map receiveLatestGoodsInfo(Map dataMap) {
        Map reMap =new HashMap();
        boolean success = true;
        String message = "成功";
        //1.查询预警配置
        List<ZsOperationWarnconfig> zsOperationWarnconfigs =  zsOperationWarnconfigMapper.selectList();
        if (zsOperationWarnconfigs!=null&&zsOperationWarnconfigs.size()>0) {
            ZsOperationWarnconfig zsOperationWarnconfig = zsOperationWarnconfigs.get(0);
            //2.更新商品表和预警结果表信息
            String curUrl = (String)dataMap.get("url");
            String newName = (String)dataMap.get("title");
            String newSn = (String)dataMap.get("sku");
            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);

            //插入
            ZsOperationGoodsDetailBo zsOperationGoodsDetailBo = new ZsOperationGoodsDetailBo();
            zsOperationGoodsDetailBo.setGoodsSkuName(newName);
            zsOperationGoodsDetailBo.setGoodsSkuSn(newSn);
            zsOperationGoodsDetailBo.setGoodsSkuUrl(curUrl);
            zsOperationGoodsDetailBo.setRemark((String)dataMap.get("remark"));
            zsOperationGoodsDetailBo.setCurPrice((String)dataMap.get("price"));
            zsOperationGoodsDetailBo.setReceiveDate(new Date(DateUtil.getShanghaiTimestamp()));
            iZsOperationGoodsDetailService.insertByBo(zsOperationGoodsDetailBo);

            //3.查询商品基准价格
            QueryWrapper<ZsOperationGoods> goodsQueryWrapper = new QueryWrapper();
            goodsQueryWrapper.eq("goods_sku_url",curUrl);
            List<ZsOperationGoods> goodsList = zsOperationGoodsMapper.selectList(goodsQueryWrapper);
            //4.比较基准价格和最新的价格是否相差大于等于 设定的阈值
            if (goodsList!=null&&goodsList.size()>0) {
                ZsOperationGoods zsOperationGoods  =goodsList.get(0);
                String newPriceStr = (String)dataMap.get("price");
                if (org.apache.commons.lang3.StringUtils.isNotBlank(newPriceStr)) {
                    newPriceStr =newPriceStr.replace(",","").trim();
                    BigDecimal newPrice = new BigDecimal(newPriceStr);
                    //如果新价格大于0
                    if (newPrice.compareTo(BigDecimal.ZERO) > 0) {
                        //判断这个商品最新的价格是否已经存在预警结果表了，如果在不发送消息和生成结果
                        if (checkIsExistsWarnResult(curUrl,newPrice)) {
                            message = "已经存在预警结果表被处理，并且价格没有再次变化，不记录 url=:"+curUrl;
                            log.info(message);
                        } else {
                            //获取基准价格
                            BigDecimal initPrice = zsOperationGoods.getInitPrice();
                            //获取基准价格和最新价格的差值比例
                            BigDecimal percentageChange= getChangeThreshold(initPrice,newPrice);
                            //我们设置的预警阈值
                            BigDecimal priceChange  = new BigDecimal(zsOperationWarnconfig.getPriceChangeThreshold());
                            // 比较差值比例是否大于等于我们设置的预警阈值
                            if ((priceChange.doubleValue()>=0&&percentageChange.compareTo(priceChange) >= 0)||
                                (priceChange.doubleValue()<0&&percentageChange.compareTo(priceChange) <= 0)
                            ) {
                                //5.生成 预警结果数据
                                String warnTypes = zsOperationWarnconfig.getWarnTypes();
                                ZsOperationWarnresult zsOperationWarnresult = new ZsOperationWarnresult();
                                zsOperationWarnresult.setWarnTime(new Date(DateUtil.getShanghaiTimestamp()));
                                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 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"));
                                warnEmail.setRemark(zsOperationGoods.getRemark());
                                //读取邮件模板
                                Context context = new Context();
                                context.setVariable("warnEmail", warnEmail);
                                String warnContentHtml = templateEngine.process("warnEmail", context);

                                zsOperationWarnresult.setWarnContent(warnContentHtml);
                                zsOperationWarnresult.setSnapshotUrl((String)dataMap.get("screenshotUrl"));
                                zsOperationWarnresult.setStatus(0);
                                zsOperationWarnresult.setPlatform(zsOperationGoods.getPlatform());
                                zsOperationWarnresult.setCompareStatus(1);
                                QueryWrapper<ZsOperationWarnresult> queryWrapper = new QueryWrapper();
                                queryWrapper.eq("goods_sku_url",curUrl);
                                queryWrapper.eq("status",0);//未处理
                                queryWrapper.orderByDesc("warn_time");
                                List<ZsOperationWarnresult> list =  zsOperationWarnresultMapper.selectList(queryWrapper);
                                if (list!=null&&list.size()>0) {
                                    zsOperationWarnresult.setId(list.get(0).getId());
                                    //更新
                                    zsOperationWarnresultMapper.update(zsOperationWarnresult,
                                        new UpdateWrapper<ZsOperationWarnresult>().eq("id",zsOperationWarnresult.getId()));
                                } else {
                                    //插入
                                    zsOperationWarnresultMapper.insert(zsOperationWarnresult);
                                }

                                //6.发送邮件
                                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) {
                                            //发送数据 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 {
                                    message = "预警接收配置为空,不发送邮件";
                                    log.info(message);
                                }
                            } else {
                                message = "商品:"+newName+";价格变动小于阈值，不生成比对结果;本次变动幅度=:"+percentageChange;
                                log.info(message);
                            }
                        }
                    } else {
                        log.info("商品:"+newName+";新价格为0，不生成比对结果");
                    }
                }
            } else {
                success = false;
                message = "商品不存在";
            }
        } else {
            success = false;
            message = "预警配置为空";
        }
        reMap.put("success",success);
        reMap.put("message",message);
        return reMap;
    }

    //查询是否存在已处理的数据
    public boolean checkIsExistsWarnResult(String url,BigDecimal newPrice) {
        boolean isExists = false;
        QueryWrapper<ZsOperationWarnresult> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_sku_url",url);
        queryWrapper.eq("status",1);//已处理
        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;
    }

    /**
     * 返回变化的差值比例
     * @param curPrice 当前价格（基准价）
     * @param newPrice 新价格
     */
/*    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;
    }*/

    public static BigDecimal getChangeThreshold(BigDecimal curPrice, BigDecimal newPrice) {
        if (curPrice == null || newPrice == null ) {
            throw new IllegalArgumentException("价格参数不能为空");
        }

        // 计算差值
        BigDecimal difference = newPrice.subtract(curPrice);
        // 计算百分比 (差值/原价)*100
        return difference.divide(curPrice,10, RoundingMode.HALF_UP)
            .multiply(new BigDecimal(100));
        //.setScale(2, RoundingMode.HALF_UP);
    }
    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);
    }

}
