/**
 * KRA - HTTP Request Utility
 * Based on UMI request with custom interceptors
 */
import { request } from '@umijs/max';
import { message, notification } from 'antd';
import type { RequestConfig } from '@umijs/max';

// API Response type
export interface ApiResponse<T = any> {
  code: number;
  data: T;
  msg: string;
}

// Request options extension
export interface KraRequestOptions {
  skipErrorHandler?: boolean;
  donNotShowLoading?: boolean;
}

// Loading state management
let activeRequests = 0;
let loadingTimer: NodeJS.Timeout | null = null;
let forceCloseTimer: NodeJS.Timeout | null = null;

const showLoading = () => {
  activeRequests++;
  if (loadingTimer) {
    clearTimeout(loadingTimer);
  }
  // Delay showing loading to avoid flicker for fast requests
  loadingTimer = setTimeout(() => {
    if (activeRequests > 0) {
      message.loading({ content: '加载中...', key: 'globalLoading', duration: 0 });
      // Force close after 30 seconds
      forceCloseTimer = setTimeout(() => {
        message.destroy('globalLoading');
        activeRequests = 0;
      }, 30000);
    }
  }, 400);
};

const hideLoading = () => {
  activeRequests--;
  if (activeRequests <= 0) {
    activeRequests = 0;
    if (loadingTimer) {
      clearTimeout(loadingTimer);
      loadingTimer = null;
    }
    if (forceCloseTimer) {
      clearTimeout(forceCloseTimer);
      forceCloseTimer = null;
    }
    message.destroy('globalLoading');
  }
};

export const resetLoading = () => {
  activeRequests = 0;
  if (loadingTimer) {
    clearTimeout(loadingTimer);
    loadingTimer = null;
  }
  if (forceCloseTimer) {
    clearTimeout(forceCloseTimer);
    forceCloseTimer = null;
  }
  message.destroy('globalLoading');
};

// Get error message from response
const getErrorMessage = (error: any): string => {
  return error?.response?.data?.msg || error?.response?.statusText || error?.message || '请求失败';
};

// Error handler
const errorHandler = (error: any) => {
  hideLoading();

  if (!error.response) {
    // Network error
    resetLoading();
    notification.error({
      message: '网络异常',
      description: '您的网络发生异常，无法连接服务器',
    });
    return Promise.reject(error);
  }

  const { status, data } = error.response;
  const errorMsg = getErrorMessage(error);

  switch (status) {
    case 401:
      message.error(errorMsg || '登录已过期，请重新登录');
      // Clear token and redirect to login
      localStorage.removeItem('token');
      localStorage.removeItem('userInfo');
      window.location.href = '/user/login';
      break;
    case 403:
      message.error(errorMsg || '没有权限访问');
      break;
    case 404:
      message.error(errorMsg || '请求的资源不存在');
      break;
    case 500:
      message.error(errorMsg || '服务器错误');
      break;
    default:
      message.error(errorMsg);
  }

  return Promise.reject(error);
};

// Request configuration for UMI
export const requestConfig: RequestConfig = {
  timeout: 99999,
  errorConfig: {
    errorHandler,
    errorThrower: (res: ApiResponse) => {
      if (res.code !== 0) {
        const error: any = new Error(res.msg);
        error.name = 'BizError';
        error.info = res;
        throw error;
      }
    },
  },
  requestInterceptors: [
    (config: any) => {
      // Show loading
      if (!config.donNotShowLoading) {
        showLoading();
      }
      // Add token to headers
      const token = localStorage.getItem('token');
      const userInfoStr = localStorage.getItem('userInfo');
      let userId = '';
      if (userInfoStr) {
        try {
          const userInfo = JSON.parse(userInfoStr);
          userId = userInfo?.ID || '';
        } catch (e) {
          // ignore
        }
      }
      config.headers = {
        'Content-Type': 'application/json',
        'x-token': token || '',
        'x-user-id': userId,
        ...config.headers,
      };
      return config;
    },
  ],
  responseInterceptors: [
    (response: any) => {
      // Hide loading
      if (!response.config?.donNotShowLoading) {
        hideLoading();
      }
      // Handle new token in response headers
      const newToken = response.headers?.['new-token'];
      if (newToken) {
        localStorage.setItem('token', newToken);
      }
      // Check response data
      const { data } = response;
      if (typeof data?.code === 'undefined') {
        return response;
      }
      if (data.code === 0 || response.headers?.success === 'true') {
        if (response.headers?.msg) {
          data.msg = decodeURI(response.headers.msg);
        }
        return data;
      } else {
        message.error(data.msg || '操作失败');
        return data;
      }
    },
  ],
};

// Request function type with HTTP method shortcuts
interface KraRequestFunction {
  <T = any>(url: string, options?: RequestInit & KraRequestOptions): Promise<ApiResponse<T>>;
  get: <T = any>(url: string, options?: any) => Promise<ApiResponse<T>>;
  post: <T = any>(url: string, data?: any, options?: any) => Promise<ApiResponse<T>>;
  put: <T = any>(url: string, data?: any, options?: any) => Promise<ApiResponse<T>>;
  delete: <T = any>(url: string, options?: any) => Promise<ApiResponse<T>>;
  patch: <T = any>(url: string, data?: any, options?: any) => Promise<ApiResponse<T>>;
}

/**
 * KRA Request wrapper
 * Provides typed API calls with consistent error handling
 */
const kraRequest: KraRequestFunction = Object.assign(
  async function <T = any>(
    url: string,
    options?: RequestInit & KraRequestOptions,
  ): Promise<ApiResponse<T>> {
    return request<ApiResponse<T>>(url, options as any);
  },
  {
    get: <T = any>(url: string, options?: any): Promise<ApiResponse<T>> => {
      return request<ApiResponse<T>>(url, { method: 'GET', ...options });
    },
    post: <T = any>(url: string, data?: any, options?: any): Promise<ApiResponse<T>> => {
      return request<ApiResponse<T>>(url, { method: 'POST', data, ...options });
    },
    put: <T = any>(url: string, data?: any, options?: any): Promise<ApiResponse<T>> => {
      return request<ApiResponse<T>>(url, { method: 'PUT', data, ...options });
    },
    delete: <T = any>(url: string, options?: any): Promise<ApiResponse<T>> => {
      return request<ApiResponse<T>>(url, { method: 'DELETE', ...options });
    },
    patch: <T = any>(url: string, data?: any, options?: any): Promise<ApiResponse<T>> => {
      return request<ApiResponse<T>>(url, { method: 'PATCH', data, ...options });
    },
  }
);

// Clean up on page unload
if (typeof window !== 'undefined') {
  window.addEventListener('beforeunload', resetLoading);
  window.addEventListener('unload', resetLoading);
}

export default kraRequest;
