/**
 * HTTP请求工具类
 * 封装uni.request，统一处理请求和响应
 */

import { API_CONFIG } from './config';
import { getToken, handleUnauthorized } from './auth';

/**
 * 请求配置接口
 */
interface RequestConfig {
  url: string;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  data?: any;
  header?: any;
  timeout?: number;
  /** 是否跳过添加token，用于免登录接口 */
  skipAuth?: boolean;
  /** 是否静默（不弹 toast），轮询类请求应设为 true */
  silent?: boolean;
}

/**
 * 响应数据接口
 */
interface ResponseData<T = any> {
  code: number;
  message: string;
  data?: T;
}

/**
 * 发起HTTP请求
 * @param config 请求配置
 * @returns Promise<响应数据>
 */
export const request = <T = any>(config: RequestConfig): Promise<T> => {
  return new Promise((resolve, reject) => {
    const { url, method = 'GET', data, header = {}, timeout, skipAuth = false, silent = false } = config;

    const effectiveTimeout = timeout ?? (silent ? 5000 : API_CONFIG.timeout);

    // 构建完整URL
    let fullUrl = url.startsWith('http') ? url : `${API_CONFIG.baseUrl}${url}`;

    // 添加token到请求头（skipAuth为true时跳过）
    if (!skipAuth) {
      const token = getToken();
      if (token) {
        header['accessToken'] = token;
        if (API_CONFIG.enableLog) {
          console.log('[请求拦截] 添加token到请求头:', token.substring(0, 8) + '...');
        }
      } else {
        if (API_CONFIG.enableLog) {
          console.warn('[请求拦截] 未找到token，请求将不携带token');
        }
      }
    }

    // 添加Content-Type
    if (!header['Content-Type']) {
      header['Content-Type'] = 'application/json';
    }

    // 打印请求日志
    if (API_CONFIG.enableLog && !silent) {
      console.log(`[请求] ${method} ${fullUrl}`, data);
    }

    // 发起请求
    uni.request({
      url: fullUrl,
      method,
      data,
      header,
      timeout: effectiveTimeout,
      success: (res: any) => {
        // 打印响应日志
        if (API_CONFIG.enableLog && !silent) {
          console.log(`[响应] ${method} ${fullUrl}`, res.data);
        }

        const responseData = res.data as ResponseData<T>;

        // 处理HTTP状态码
        if (res.statusCode !== 200) {
          // HTTP 401 同样触发未授权处理
          if (res.statusCode === 401) {
            handleUnauthorized();
          }
          const errorMsg = `请求失败: HTTP ${res.statusCode}`;
          if (!silent) {
            uni.showToast({ title: errorMsg, icon: 'none' });
          }
          reject(new Error(errorMsg));
          return;
        }

        // 处理业务状态码
        if (responseData.code === 200 || responseData.code === 0) {
          if (API_CONFIG.enableLog) {
            console.log('[响应处理] 业务成功，返回data:', responseData.data);
          }
          resolve(responseData.data as T);
        } else if (responseData.code === 401) {
          handleUnauthorized();
          const authError = new Error(responseData.message || '未登录');
          (authError as any).isAuthError = true;
          reject(authError);
        } else {
          const errorMsg = responseData.message || '操作失败';
          if (!silent) {
            uni.showToast({ title: errorMsg, icon: 'none' });
          }
          reject(new Error(errorMsg));
        }
      },
      fail: (err: any) => {
        console.error(`[请求失败] ${method} ${fullUrl}`, err);

        if (!silent) {
          let errorMsg = '网络请求失败';
          if (err.errMsg) {
            if (err.errMsg.includes('timeout')) {
              errorMsg = '请求超时，请检查网络';
            } else if (err.errMsg.includes('fail')) {
              errorMsg = '网络连接失败，请检查网络';
            }
          }
          uni.showToast({ title: errorMsg, icon: 'none' });
        }

        reject(new Error(err.errMsg || '网络请求失败'));
      }
    });
  });
};

/**
 * GET请求
 */
export const get = <T = any>(url: string, data?: any, options?: { skipAuth?: boolean; silent?: boolean }): Promise<T> => {
  return request<T>({ url, method: 'GET', data, ...options });
};

/**
 * POST请求
 */
export const post = <T = any>(url: string, data?: any, options?: { silent?: boolean }): Promise<T> => {
  return request<T>({ url, method: 'POST', data, ...options });
};

/**
 * PUT请求
 */
export const put = <T = any>(url: string, data?: any, options?: { silent?: boolean }): Promise<T> => {
  return request<T>({ url, method: 'PUT', data, ...options });
};

/**
 * DELETE请求
 */
export const del = <T = any>(url: string, data?: any, options?: { silent?: boolean }): Promise<T> => {
  return request<T>({ url, method: 'DELETE', data, ...options });
};
