package com.wzj.soopin.content.consumer;

import cn.hutool.core.util.ObjectUtil;
import com.wzj.soopin.content.domain.po.Vlog;
import com.wzj.soopin.content.service.VlogService;
import com.wzj.soopin.content.utils.MinIOUtils;
import com.wzj.soopin.content.utils.QcCloud;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.OssService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mq.config.RocketMQConfig;
import org.dromara.common.mq.domain.MQMessage;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.springframework.stereotype.Component;

import java.nio.file.Files;
import java.nio.file.Path;

/**
 * RocketMQ消息消费者
 *
 * @author wzj
 */
@Slf4j
@Component
@RequiredArgsConstructor
@RocketMQMessageListener(
    topic = RocketMQConfig.VLOG_UPLOAD_TOPIC,
    consumerGroup = RocketMQConfig.VLOG_UPLOAD_GROUP,
    selectorExpression =  RocketMQConfig.VLOG_UPLOAD_TAG
)
public class VlogUploadMessageConsumer implements RocketMQListener<MessageExt> {
    private final QcCloud qcCloud;
    private final ISysOssService ossService;
    private final VlogService vlogService;

    @Override
    public void onMessage(MessageExt messageExt) {  // 参数为MessageExt

        String message = new String(messageExt.getBody());
        log.info("接收到RocketMQ消息: {}, msgId: {}", message, messageExt.getMsgId());

        try {
            MQMessage mqMessage = JsonUtils.parseObject(message, MQMessage.class);

            if (mqMessage != null && messageExt.getBody() != null) {
                boolean result = this.handleMessage(mqMessage);
                if (result) {
                    // 消息处理成功，手动确认
//                    messageExt.acknowledge();  // 2.3.1版本支持该方法
                    log.info("消息确认成功, msgId: {}", messageExt.getMsgId());
                } else {
                    // 业务失败，抛出异常触发重试
                    throw new RuntimeException("业务处理失败，将重试");
                }
            } else {
                log.warn("消息格式错误，直接确认避免重试: {}", message);
//                messageExt.acknowledge();  // 格式错误无需重试
            }
        } catch (Exception e) {
            log.error("消息处理异常, msgId: {}", messageExt.getMsgId(), e);
            // 达到最大重试次数后确认消息
            if (messageExt.getReconsumeTimes() >= 3) {
                log.error("达到最大重试次数，确认消息进入死信队列, msgId: {}", messageExt.getMsgId());
//                messageExt.acknowledge();
            } else {
                // 未达重试上限，抛出异常触发重试
                throw new RuntimeException("消息处理异常，将重试", e);
            }
        }
    }

    private boolean handleMessage(MQMessage mqMessage) throws Exception {
        //视频上传消息会包含视频的内容
        Vlog vlog = vlogService.getById((String) mqMessage.getData());
        //获取文件内容
        if (ObjectUtil.isNull(vlog)) {
            return false;
        }
        String fileId = vlog.getFileId();
        //检查该文件是否为oss文件，如果不是说明已经上传过了
        if (!vlog.getUrl().contains("#")) {
            return true;
        }
        //从oss下载文件

        SysOssVo sysOss = ossService.getById(Long.parseLong(fileId));
        if (ObjectUtil.isNull(sysOss)) {
            throw new ServiceException("文件数据不存在!");
        }
        OssClient ossClient = OssFactory.instance(sysOss.getService());
        Path filePath = ossClient.fileDownload(sysOss.getUrl(), sysOss.getOriginalName());
        //对文件进行重命名


        String[] fileInfo = qcCloud.uploadViaTempFile(filePath);
        if (fileInfo == null) {
            return false;
        }
        log.info("视频发布ID:" + fileId);
        vlog.setFileId(fileInfo[0]);
        vlog.setUrl(fileInfo[1]);
        vlogService.updateById(vlog);
        // 删除minio文件,删除本地文件
        Files.deleteIfExists(filePath);
//        MinIOUtils.removeFile("wzj", fileId);
        log.info("删除minio文件：" + fileId);

        return true;
    }

}
