package com.sckw.remote.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.service.GenericService;

import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FILTER_VALIDATION_EXCEPTION;

@Activate(group = CommonConstants.CONSUMER)
public class DubboConsumerExceptionFilter implements Filter, Filter.Listener {
    private ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DubboConsumerExceptionFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        return invoker.invoke(invocation);
    }

    @Override
    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
        if (appResponse.hasException() && GenericService.class != invoker.getInterface()) {
            try {
                Throwable exception = appResponse.getException();
                
                // 直接抛出RuntimeException，避免将底层异常信息暴露给调用方
                String className = exception.getClass().getName();
                if (className.startsWith("java.") || className.startsWith("javax.")) {
                    return;
                }
                
                // 自定义异常处理
                if (className.startsWith("com.sckw.core.exception")) {
                    return;
                }
                
                // Dubbo异常处理
                if (exception instanceof RpcException) {
                    // 记录RpcException日志，但不暴露给前端
                    logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
                        "Dubbo RpcException. service: " + invoker.getInterface().getName() + 
                        ", method: " + invocation.getMethodName() + 
                        ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), 
                        exception);
                    
                    // 包装为通用异常信息返回给客户端
                    appResponse.setException(new RuntimeException("服务暂时不可用，请稍后重试"));
                    return;
                }

                // 记录异常日志
                logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
                    "Dubbo consumer caught exception. service: " + invoker.getInterface().getName() + 
                    ", method: " + invocation.getMethodName() + 
                    ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), 
                    exception);

                // 包装为RuntimeException并返回给客户端
                appResponse.setException(new RuntimeException("服务调用异常，请稍后重试"));
            } catch (Throwable e) {
                logger.warn(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
                    "Fail to ExceptionFilter when called by " + RpcContext.getServiceContext().getRemoteHost() + 
                    ". service: " + invoker.getInterface().getName() + 
                    ", method: " + invocation.getMethodName() + 
                    ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
            }
        }
    }

    @Override
    public void onError(Throwable e, Invoker<?> invoker, Invocation invocation) {
        logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "", 
            "Got unchecked and undeclared exception which called by " + RpcContext.getServiceContext().getRemoteHost() + 
            ". service: " + invoker.getInterface().getName() + 
            ", method: " + invocation.getMethodName() + 
            ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
    }

    // For test purpose
    public void setLogger(ErrorTypeAwareLogger logger) {
        this.logger = logger;
    }
}