import type { RequestOptions } from '@@/plugin-request/request';
import type { RequestConfig } from '@umijs/max';
import { history } from '@umijs/max';
import { message } from 'antd';
import {
  getAccessToken,
  isTokenExpired,
  isRefreshTokenExpired,
  clearTokens,
} from '@/services/auth/tokenManager';
import { refreshToken } from '@/services/auth/api';
import { getErrorMessage, isAuthError } from '@/services/auth/errorCodes';

const loginPath = '/user/login';

// 是否正在刷新 Token
let isRefreshing = false;
// 等待刷新 Token 的请求队列（同时保存 resolve 和 reject）
let refreshSubscribers: Array<{ resolve: (token: string) => void; reject: (reason?: any) => void }> = [];

// 添加到刷新队列
function subscribeTokenRefresh(resolve: (token: string) => void, reject: (reason?: any) => void) {
  refreshSubscribers.push({ resolve, reject });
}

// 通知所有等待的请求
function onTokenRefreshed(token: string) {
  refreshSubscribers.forEach(({ resolve }) => resolve(token));
  refreshSubscribers = [];
}

// 刷新 Token 失败，跳转登录
function onRefreshFailed() {
  refreshSubscribers.forEach(({ reject }) => reject(new Error('Token refresh failed')));
  refreshSubscribers = [];
  clearTokens();
  history.push(loginPath);
}

// 错误处理方案： 错误类型
enum ErrorShowType {
  SILENT = 0,
  WARN_MESSAGE = 1,
  ERROR_MESSAGE = 2,
  NOTIFICATION = 3,
  REDIRECT = 9,
}

// 与后端约定的响应数据格式
interface ResponseStructure {
  success: boolean;
  data: any;
  message?: string;
  error?: {
    code: string;
    details?: Record<string, any>;
  };
  errorCode?: number;
  errorMessage?: string;
  showType?: ErrorShowType;
}

export const errorConfig: RequestConfig = {
  errorConfig: {
    errorThrower: (res) => {
      const { success, message: errorMessage, error } = res as unknown as ResponseStructure;
      if (!success) {
        const err: any = new Error(errorMessage);
        err.name = 'BizError';
        err.info = {
          errorCode: error?.code,
          errorMessage,
          data: res,
        };
        throw err;
      }
    },

    errorHandler: (error: any, opts: any) => {
      if (opts?.skipErrorHandler) throw error;

      if (error.name === 'BizError') {
        const errorInfo = error.info;
        if (errorInfo) {
          const { errorCode, errorMessage } = errorInfo;
          const displayMessage = errorMessage || getErrorMessage(errorCode);

          // 认证错误，跳转登录
          if (isAuthError(errorCode)) {
            clearTokens();
            message.error(displayMessage || '登录已过期，请重新登录');
            history.push(loginPath);
            return;
          }

          message.error(displayMessage);
        }
      } else if (error.response) {
        const status = error.response.status;
        const data = error.response.data as ResponseStructure;
        const errorCode = data?.error?.code;

        // 优先使用后端返回的 message，其次使用错误码对应的消息
        let displayMessage = data?.message;
        if (!displayMessage && errorCode) {
          displayMessage = getErrorMessage(errorCode);
        }

        // 处理 401 未授权
        if (status === 401) {
          if (errorCode && isAuthError(errorCode)) {
            clearTokens();
            message.error(displayMessage || '登录已过期，请重新登录');
            history.push(loginPath);
            return;
          }
          // 401 但不是认证错误码，显示具体错误
          message.error(displayMessage || '未授权，请重新登录');
          return;
        }

        // 处理其他 HTTP 错误
        if (displayMessage && displayMessage !== '未知错误') {
          message.error(displayMessage);
        } else {
          // 根据 HTTP 状态码显示友好消息
          const statusMessages: Record<number, string> = {
            400: '请求参数错误',
            403: '没有权限访问',
            404: '请求的资源不存在',
            409: '资源冲突',
            423: '账户已被锁定',
            429: '请求过于频繁，请稍后再试',
            500: '服务器错误，请稍后再试',
          };
          message.error(statusMessages[status] || `请求失败`);
        }
      } else if (error.request) {
        message.error('网络错误，请检查网络连接');
      } else {
        message.error('请求失败，请重试');
      }
    },
  },

  // 请求拦截器
  requestInterceptors: [
    async (config: RequestOptions) => {
      const token = getAccessToken();

      // 如果有 Token，检查是否过期
      if (token && isTokenExpired()) {
        // Refresh Token 也过期了，直接清除，无需尝试刷新
        if (isRefreshTokenExpired()) {
          clearTokens();
          return config;
        }
        // Access Token 过期但 Refresh Token 有效，尝试刷新
        if (!isRefreshing) {
          isRefreshing = true;
          try {
            const result = await refreshToken();
            if (result.success && result.data) {
              onTokenRefreshed(result.data.accessToken);
              // 使用新 Token
              config.headers = {
                ...config.headers,
                Authorization: `Bearer ${result.data.accessToken}`,
              };
            } else {
              onRefreshFailed();
            }
          } catch {
            onRefreshFailed();
          } finally {
            isRefreshing = false;
          }
        } else {
          // 正在刷新，加入等待队列
          return new Promise((resolve, reject) => {
            subscribeTokenRefresh((newToken) => {
              config.headers = {
                ...config.headers,
                Authorization: `Bearer ${newToken}`,
              };
              resolve(config);
            }, reject);
          });
        }
      } else if (token) {
        // Token 未过期，直接使用
        config.headers = {
          ...config.headers,
          Authorization: `Bearer ${token}`,
        };
      }

      return config;
    },
  ],

};
