package com.cmvr.framework.websocket.handler;

import com.cmvr.framework.websocket.manager.ChannelSubscriptionManager;
import com.cmvr.framework.websocket.message.WSChannelSubscriptionMessage;
import com.cmvr.framework.websocket.service.GrpcClientService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.WebSocketSession;

import java.util.concurrent.CompletableFuture;

@RequiredArgsConstructor
public abstract class BaseChannelSubscribeHandler implements WSMessageHandler<WSChannelSubscriptionMessage> {

    protected final Logger log = LoggerFactory.getLogger(getClass());
    protected final ChannelSubscriptionManager channelSubscriptionManager;
    protected final GrpcClientService grpcClientService;

    /**
     * 是否需要GRPC远程调用
     * true=格式 service/method/terminalId/deviceId 走grpc
     * false=普通频道，只本地订阅，不调用grpc
     */
    protected abstract boolean isNeedGrpc(String channel);

    /**
     * 解析grpc四个参数 [service,method,terminalId,deviceId]
     * 只有isNeedGrpc=true才会进入执行
     */
    protected abstract String[] parseGrpcParam(String channel);

    @Override
    public void handle(WebSocketSession session, WSChannelSubscriptionMessage message) throws Exception {
        String action = message.getAction();
        String userId = session.getAttributes().get("userId").toString();
        String channel = message.getChannel();

        switch (action) {
            case "subscribe":
                doSubscribe(channel, session);
                break;
            case "unsubscribe":
                doUnSubscribe(channel, session);
                break;
            default:
                log.warn("未知订阅动作：{}，channel:{}", action, channel);
                return;
        }
        log.info("用户{} {}频道{}", userId, "subscribe".equals(action) ? "订阅" : "取消订阅", channel);
    }

    /** 订阅统一模板 */
    private void doSubscribe(String channel, WebSocketSession session) {
        boolean needGrpc = isNeedGrpc(channel);
        // 没人订阅 + 需要grpc → 发起远端订阅
        if (needGrpc && !channelSubscriptionManager.hasSubscribers(channel)) {
            String[] params = parseGrpcParam(channel);
            String service = params[0];
            String method = params[1];
            String terminalId = params[2];
            String deviceId = params[3];
            CompletableFuture.runAsync(() -> {
                try {
                    grpcClientService.send(true, terminalId, deviceId, service, method);
                } catch (Exception e) {
                    log.error("频道{} grpc订阅异常", channel, e);
                }
            });
        }
        // 本地统一订阅
        channelSubscriptionManager.subscribe(channel, session);
    }

    /** 取消订阅统一模板 */
    private void doUnSubscribe(String channel, WebSocketSession session) {
        channelSubscriptionManager.unsubscribe(channel, session);
        boolean needGrpc = isNeedGrpc(channel);
        // 无任何订阅 + 需要grpc → 远端取消
        if (needGrpc && !channelSubscriptionManager.hasSubscribers(channel)) {
            String[] params = parseGrpcParam(channel);
            String service = params[0];
            String method = params[1];
            String terminalId = params[2];
            String deviceId = params[3];
            CompletableFuture.runAsync(() -> {
                try {
                    grpcClientService.send(false, terminalId, deviceId, service, method);
                } catch (Exception e) {
                    log.error("频道{} grpc取消订阅异常", channel, e);
                }
            });
        }
    }
}
