package com.ruoyi.modules.monitor.notify;

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.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Component
public class ServiceChangeNotifier extends AbstractStatusChangeNotifier {

    private final DingTalkNotifier dingTalkNotifier;
    private final InstanceRepository repository;

    /* 新增字段 */
    private final ConcurrentHashMap<String, Instance> buffer = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();


    public ServiceChangeNotifier(InstanceRepository repository,
                                 DingTalkNotifier dingTalkNotifier) {
        super(repository);
        this.repository = repository;
        this.dingTalkNotifier = dingTalkNotifier;

        /* 每 5 秒聚合发送一次（可按需调整） */
        scheduler.scheduleWithFixedDelay(this::flush, 5, 5, TimeUnit.SECONDS);
    }

    @Override
    protected boolean shouldNotify(InstanceEvent event, Instance instance) {
        return event instanceof InstanceStatusChangedEvent;
    }

    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
        /* 仅把实例放进 buffer，不做实际推送 */
        buffer.put(String.valueOf(instance.getId()), instance);
        return Mono.empty();
    }

    private void flush() {
        if (buffer.isEmpty()) {
            return;
        }

        /* 拿到此刻的快照，然后清空 buffer */
        List<Instance> snapshot = new ArrayList<>(buffer.values());
        buffer.clear();

        /* 计算每个实例的 total，并排序 */
        Map<Instance, Long> totalMap = new HashMap<>();
        for (Instance inst : snapshot) {
            long total = repository.findAll().collectList().block().size(); // 这里简单起见直接 block
            totalMap.put(inst, total);
        }

        snapshot.sort(Comparator.comparing(totalMap::get));

        /* 依次发送钉钉 */
        for (Instance instance : snapshot) {
            sendOne(instance);
        }
    }

    private void sendOne(Instance instance) {
        String serviceName = instance.getRegistration().getName();
        String newStatus   = instance.getStatusInfo().getStatus();
        String serviceUrl  = instance.getRegistration().getServiceUrl();
        String time        = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

        List<Instance> all = repository.findAll().collectList().block();
        long total   = all.size();
        long online  = all.stream().filter(i -> "UP".equals(i.getStatusInfo().getStatus())).count();
        long offline = total - online;

        /* 根据状态决定颜色 */
        String icon = "UP".equalsIgnoreCase(newStatus)
                ? "<font color=\"#00ff00\">✅</font>"
                : "<font color=\"#ff0000\">🚨</font>";

        String markdown = "### " + icon + " 服务状态变更告警\n" +
                "- **服务名**: " + serviceName + "  \n" +
                "- **当前状态**: " + newStatus + "  \n" +
                "- **地址**: " + serviceUrl + "  \n" +
                "- **时间**: " + time + "  \n" +
                "- **统计**: 总 " + total + "，在线 " + online + "，离线 " + offline;

        dingTalkNotifier.sendMarkdown("服务状态变更", markdown).subscribe();
    }
}