package com.backendsys.modules.sse.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.backendsys.modules.common.config.security.utils.HttpRequestUtil;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.sse.emitter.SseEmitterManager;
import com.backendsys.modules.sse.entity.SseResponse;
import com.backendsys.modules.sse.entity.SseResponseEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class SseUtil {

    @Autowired
    private HttpRequestUtil httpRequestUtil;

    @Value("${spring.application.name}")
    private String APPLICATION_NAME;

//    // [SSE] 发送消息 (单个)
//    public void send(String emitterKey, Object data) {
//        SseEmitterManager manager = SseEmitterManager.getInstance();
//        SseEmitterUTF8 emitter = manager.getEmitter(emitterKey);
//        if (emitter != null) {
//            try {
//                emitter.send(SseEmitter.event().data(data));
//            } catch (IOException e) {
//                System.out.println(e.getMessage());
//                manager.removeEmitter(emitter);
//            }
//        }
//    }

    // 当多层嵌套时，Service 没有经过 Spring AOP 代理，因此不会正确获得 SecurityContextHolder 上下文；
    // 因此此处不能使用 SecurityUtil.getUserId() 直接获得 UserId

    // [SSE] 发送消息 (单个) (自己)
    public void send(Long user_id, Object data) {

        // 遍历所有 Emitter 并发送匹配前缀的目标 (拼接键值: 应用名称-用户ID-浏览器窗口UUID)
        SseEmitterManager manager = SseEmitterManager.getInstance();
        ConcurrentHashMap<String, SseEmitterUTF8> emitters = manager.getAllEmitters();

        String prefix = APPLICATION_NAME + "-userid-" + Convert.toStr(user_id);
        for (String key : emitters.keySet()) {
            if (key.startsWith(prefix)) { // 检查是否满足前缀条件
                SseEmitterUTF8 emitter = emitters.get(key);
                if (emitter != null) {
                    try {
                        emitter.send(SseEmitter.event().data(data)); // 发送数据
                    } catch (IOException e) {
                        System.out.println(e.getMessage());
                        manager.removeEmitter(emitter); // 发生异常时移除
                    }
                }
            }
        }

        // 单个
//        SseEmitterManager manager = SseEmitterManager.getInstance();
//        SseEmitterUTF8 emitter = manager.getEmitter(APPLICATION_NAME + "-userid-" + Convert.toStr(user_id));
//        if (emitter != null) {
//            try {
//                emitter.send(SseEmitter.event().data(data));
//            } catch (IOException e) {
//                System.out.println(e.getMessage());
//                manager.removeEmitter(emitter);
//            }
//        }
    }

    // [SSE] 发送消息 (全部)
    public void sendToAll(Object data) {
        SseEmitterManager manager = SseEmitterManager.getInstance();
        ConcurrentHashMap<String, SseEmitterUTF8> emitters = manager.getAllEmitters();
        for (String key : emitters.keySet()) {
            SseEmitterUTF8 emitter = emitters.get(key);
            if (emitter != null) {
                try {
                    emitter.send(SseEmitter.event().data(data));
                } catch (IOException e) {
                    System.out.println("Failed to send message to emitter with key: " + key + ", Error: " + e.getMessage());
                    manager.removeEmitter(emitter);
                }
            }
        }
    }

    // 如果存在，则关闭 (此操作会完全关闭未连接的监听)
    public void closeIfExist(String emitterKey) {
        // 如果用户ID已经存在对应的连接，则关闭旧的连接
        SseEmitterManager manager = SseEmitterManager.getInstance();
        SseEmitterUTF8 oldEmitter = manager.getEmitter(emitterKey);
        if (oldEmitter != null) {
            try {
                String dataStr = (new SseResponse(SseResponseEnum.DISCONNECT)).toJsonStr();
                oldEmitter.send(SseEmitter.event().data(dataStr));
                oldEmitter.complete();              // 关闭旧的连接
            } catch (IOException e) {
                // System.out.println("(sse)(closeIfExist catch): " + e.getMessage() + oldEmitter);
            } finally {
                manager.removeEmitter(oldEmitter);  // 从管理器中移除旧的连接
                // 如果需要，可以在这里显式关闭底层资源
                if (oldEmitter != null) {
                    try {
                        // System.out.println("(closeIfExist finally) oldEmitter 关闭");
                        oldEmitter.complete();  // 再次尝试关闭
                    } catch (Exception e) {
                        System.err.println("Failed to forcefully close emitter: " + e.getMessage());
                    }
                }
            }
        }
    }

    // 添加一个新的方法：关闭所有 SSE 连接
    public void closeAllEmitters() {
        System.out.println("Closing all SSE connections...");
        SseEmitterManager manager = SseEmitterManager.getInstance();
        manager.removeAllEmitter();
    }

}
