package org.xyzh.gateway.handler;

import com.alibaba.fastjson2.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import org.xyzh.common.core.domain.ResultDomain;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * @description Gateway 全局异常处理器
 * @author yslg
 * @since 2025-12-02
 */
@Component
@Order(-1)  // 优先级设置为最高
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class);

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        
        if (response.isCommitted()) {
            return Mono.error(ex);
        }

        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        ResultDomain<Object> result;
        HttpStatus httpStatus;

        // 根据不同异常类型返回不同的错误信息
        if (ex instanceof NotFoundException) {
            log.error("服务未找到: {}", ex.getMessage());
            httpStatus = HttpStatus.SERVICE_UNAVAILABLE;
            result = ResultDomain.failure(httpStatus.value(), "服务暂时不可用: " + ex.getMessage());
        } else if (ex instanceof ResponseStatusException rse) {
            log.error("响应状态异常: {}", rse.getMessage());
            httpStatus = (HttpStatus) rse.getStatusCode();
            result = ResultDomain.failure(httpStatus.value(), rse.getReason());
        } else if (ex instanceof IllegalStateException) {
            log.error("非法状态异常: {}", ex.getMessage());
            httpStatus = HttpStatus.BAD_REQUEST;
            result = ResultDomain.failure(httpStatus.value(), "请求参数错误: " + ex.getMessage());
        } else {
            log.error("Gateway 内部错误", ex);
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            result = ResultDomain.failure(httpStatus.value(), "网关内部错误，请稍后重试");
        }

        response.setStatusCode(httpStatus);

        String json = JSON.toJSONString(result);
        DataBuffer buffer = response.bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8));

        return response.writeWith(Mono.just(buffer));
    }
}
