import { logger } from '../../shared/utils/logging';
import { STORAGE_KEYS } from '@/shared/constants';
/**
 * API 客户端
 * 统一的 HTTP 请求管理
 */

import axios, {
  AxiosError,
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig
} from 'axios';

// 请求配置
interface RequestConfig extends AxiosRequestConfig {
  skipAuth?: boolean;
  skipErrorHandler?: boolean;
  retryCount?: number;
}

// 响应数据
interface ApiResponse<T = unknown> {
  code: number;
  data: T;
  message: string;
  success: boolean;
}

class ApiClient {
  private client: AxiosInstance;

  constructor(baseURL: string = '') {
    this.client = axios.create({
      baseURL,
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json'
      }
    });

    this.setupInterceptors();
  }

  /**
   * 设置拦截器
   */
  private setupInterceptors(): void {
    // 请求拦截器
    this.client.interceptors.request.use(
      (config: InternalAxiosRequestConfig & RequestConfig) => {
        // 添加认证 token
        const token = this.getToken();
        if (token && !config.skipAuth) {
          const headers = config.headers;
          headers.set('Authorization', `Bearer ${token}`);
          config.headers.set('Authorization', `Bearer ${token}`);
        }

        return config;
      },
      (error) => Promise.reject(error)
    );

    // 响应拦截器
    this.client.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        const { data } = response;

        if (!data.success) {
          return Promise.reject(new Error(data.message || '请求失败'));
        }

        return response;
      },
      (error: AxiosError) => {
        this.handleError(error);
        return Promise.reject(error);
      }
    );
  }

  /**
   * 错误处理
   */
  private handleError(error: AxiosError): void {
    const config = error.config as (InternalAxiosRequestConfig & RequestConfig) | undefined;
    if (config?.skipErrorHandler) {
      return;
    }

    let errorMessage = '请求失败';

    if (error.response) {
      switch (error.response.status) {
        case 400:
          errorMessage = '请求参数错误';
          break;
        case 401:
          errorMessage = '未授权，请重新登录';
          // 可以在这里处理登出逻辑
          break;
        case 403:
          errorMessage = '拒绝访问';
          break;
        case 404:
          errorMessage = '请求的资源不存在';
          break;
        case 500:
          errorMessage = '服务器内部错误';
          break;
        default:
          errorMessage = `请求失败: ${error.response.status}`;
      }
    } else if (error.request) {
      errorMessage = '网络错误，请检查网络连接';
    } else {
      errorMessage = error.message;
    }

    logger.error('[api] request failed:', { errorMessage });
  }

  /**
   * GET 请求
   */
  async get<T = unknown>(url: string, config?: RequestConfig): Promise<T> {
    const response = await this.client.get<ApiResponse<T>>(url, config);
    return response.data.data;
  }

  /**
   * POST 请求
   */
  async post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<T> {
    const response = await this.client.post<ApiResponse<T>>(url, data, config);
    return response.data.data;
  }

  /**
   * PUT 请求
   */
  async put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<T> {
    const response = await this.client.put<ApiResponse<T>>(url, data, config);
    return response.data.data;
  }

  /**
   * DELETE 请求
   */
  async delete<T = unknown>(url: string, config?: RequestConfig): Promise<T> {
    const response = await this.client.delete<ApiResponse<T>>(url, config);
    return response.data.data;
  }

  /**
   * PATCH 请求
   */
  async patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<T> {
    const response = await this.client.patch<ApiResponse<T>>(url, data, config);
    return response.data.data;
  }

  /**
   * 上传文件
   */
  async upload<T = unknown>(
    url: string,
    file: File,
    onProgress?: (progress: number) => void,
    config?: RequestConfig
  ): Promise<T> {
    const formData = new FormData();
    formData.append('file', file);

    const response = await this.client.post<ApiResponse<T>>(url, formData, {
      ...config,
      headers: {
        ...config?.headers,
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: (progressEvent) => {
        if (progressEvent.total && onProgress) {
          const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
          onProgress(progress);
        }
      }
    });

    return response.data.data;
  }

  /**
   * 下载文件
   */
  async download(url: string, filename: string, config?: RequestConfig): Promise<void> {
    const response = await this.client.get<Blob>(url, {
      ...config,
      responseType: 'blob'
    });

    const blob = new Blob([response.data]);
    const downloadUrl = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = downloadUrl;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(downloadUrl);
  }

  /**
   * 设置 Token
   */
  setToken(token: string): void {
    // 优先使用新键名，同时兼容旧键名
    localStorage.setItem(STORAGE_KEYS.authToken, token);
    localStorage.setItem(STORAGE_KEYS.legacy.token, token);
  }

  /**
   * 清除 Token
   */
  clearToken(): void {
    localStorage.removeItem(STORAGE_KEYS.authToken);
    localStorage.removeItem(STORAGE_KEYS.legacy.token);
  }

  /**
   * 获取 Token
   */
  getToken(): string | null {
    // 优先读取新键名，兼容旧键名
    return localStorage.getItem(STORAGE_KEYS.authToken)
      || localStorage.getItem(STORAGE_KEYS.legacy.token);
  }
}

// 创建默认实例
export const apiClient = new ApiClient();

// 导出类型
export type { ApiResponse, RequestConfig };
export default ApiClient;
