package com.ruoyi.modules.monitor.listener;

import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent;
import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.ruoyi.modules.monitor.service.AlarmEmailService;
import reactor.core.publisher.Mono;

/**
 * 服务状态变更通知器
 * 通过继承AbstractStatusChangeNotifier实现自定义通知
 * 
 * @author lydgt
 */
@Component
public class ServiceStatusListener extends AbstractStatusChangeNotifier
{
    private static final Logger log = LoggerFactory.getLogger(ServiceStatusListener.class);

    private final AlarmEmailService alarmEmailService;

    public ServiceStatusListener(InstanceRepository repository, AlarmEmailService alarmEmailService)
    {
        super(repository);
        this.alarmEmailService = alarmEmailService;
    }

    /**
     * 处理实例状态变更事件
     */
    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance)
    {
        return Mono.fromRunnable(() -> {
            if (event instanceof InstanceStatusChangedEvent)
            {
                String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus();
                String serviceName = instance.getRegistration().getName();
                String serviceUrl = instance.getRegistration().getServiceUrl();
                
                log.info("服务状态变更 - 服务: {}, URL: {}, 状态: {}", serviceName, serviceUrl, status);
                
                switch (status)
                {
                    // 健康检查没通过
                    case "DOWN":
                        log.warn("服务异常 - 服务: {}, 状态: DOWN", serviceName);
                        sendAlarmEmail(serviceName, serviceUrl, status, "DOWN", event);
                        break;
                    // 服务离线
                    case "OFFLINE":
                        log.warn("服务离线 - 服务: {}, 状态: OFFLINE", serviceName);
                        sendAlarmEmail(serviceName, serviceUrl, status, "OFFLINE", event);
                        break;
                    // 服务上线
                    case "UP":
                        log.info("服务恢复 - 服务: {}, 状态: UP", serviceName);
                        sendRecoveryEmail(serviceName, serviceUrl, status);
                        break;
                    // 服务未知异常
                    case "UNKNOWN":
                        log.warn("服务未知异常 - 服务: {}, 状态: UNKNOWN", serviceName);
                        sendAlarmEmail(serviceName, serviceUrl, status, "UNKNOWN", event);
                        break;
                    default:
                        log.debug("服务状态变更 - 服务: {}, 状态: {}", serviceName, status);
                        break;
                }
            }
        });
    }

    /**
     * 发送告警邮件
     */
    private void sendAlarmEmail(String serviceName, String serviceUrl, String status, String type, InstanceEvent event)
    {
        try
        {
            String subject = "【服务告警】服务异常通知 - " + serviceName;
            String content = buildAlarmContent(serviceName, serviceUrl, status, type, event);
            alarmEmailService.sendAlarmEmail(subject, content);
            log.warn("已发送服务告警邮件 - 服务: {}, 类型: {}", serviceName, type);
        }
        catch (Exception e)
        {
            log.error("发送告警邮件失败 - 服务: {}", serviceName, e);
        }
    }

    /**
     * 发送恢复邮件
     */
    private void sendRecoveryEmail(String serviceName, String serviceUrl, String status)
    {
        try
        {
            String subject = "【服务恢复】服务恢复正常通知 - " + serviceName;
            String content = buildRecoveryContent(serviceName, serviceUrl, status);
            alarmEmailService.sendAlarmEmail(subject, content);
            log.info("已发送服务恢复邮件 - 服务: {}", serviceName);
        }
        catch (Exception e)
        {
            log.error("发送恢复邮件失败 - 服务: {}", serviceName, e);
        }
    }

    /**
     * 构建告警邮件内容
     */
    private String buildAlarmContent(String serviceName, String serviceUrl, String status, String type, InstanceEvent event)
    {
        StringBuilder sb = new StringBuilder();
        sb.append("<h2 style='color: red;'>服务异常告警</h2>");
        sb.append("<p><strong>服务名称：</strong>").append(serviceName).append("</p>");
        sb.append("<p><strong>服务地址：</strong>").append(serviceUrl).append("</p>");
        sb.append("<p><strong>当前状态：</strong><span style='color: red;'>").append(status).append("</span></p>");
        sb.append("<p><strong>告警类型：</strong>").append(type).append("</p>");
        sb.append("<p><strong>告警时间：</strong>").append(java.time.LocalDateTime.now()).append("</p>");
        
        if (event instanceof InstanceStatusChangedEvent) {
            Object details = ((InstanceStatusChangedEvent) event).getStatusInfo().getDetails();
            if (details != null && !details.toString().isEmpty()) {
                sb.append("<p><strong>详细信息：</strong></p><pre>").append(details.toString()).append("</pre>");
            }
        }
        
        sb.append("<hr><p style='color: gray;'>此邮件由监控系统自动发送，请勿回复。</p>");
        return sb.toString();
    }

    /**
     * 构建恢复邮件内容
     */
    private String buildRecoveryContent(String serviceName, String serviceUrl, String status)
    {
        StringBuilder sb = new StringBuilder();
        sb.append("<h2 style='color: green;'>服务恢复正常</h2>");
        sb.append("<p><strong>服务名称：</strong>").append(serviceName).append("</p>");
        sb.append("<p><strong>服务地址：</strong>").append(serviceUrl).append("</p>");
        sb.append("<p><strong>当前状态：</strong><span style='color: green;'>").append(status).append("</span></p>");
        sb.append("<p><strong>恢复时间：</strong>").append(java.time.LocalDateTime.now()).append("</p>");
        sb.append("<hr><p style='color: gray;'>此邮件由监控系统自动发送，请勿回复。</p>");
        return sb.toString();
    }
}