import Taro from '@tarojs/taro';
import { config } from '../config';

interface RequestOptions {
  /** 请求路径（不含 baseURL） */
  url: string;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
  data?: Record<string, unknown>;
  params?: Record<string, unknown>;
  /** 是否需要登录 */
  auth?: boolean;
}

interface ApiResponse<T = unknown> {
  code?: number;
  data: T;
  message?: string;
}

/**
 * 构建查询字符串
 */
function buildUrl(url: string, params?: Record<string, unknown>): string {
  if (!params) return url;
  const query = Object.entries(params)
    .filter(([, v]) => v !== undefined && v !== null && v !== '')
    .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
    .join('&');
  return query ? `${url}?${query}` : url;
}

/**
 * 通用请求封装 — 基于 Taro.request
 */
async function request<T = unknown>(options: RequestOptions): Promise<T> {
  const { url, method = 'GET', data, params, auth = true } = options;

  const header: Record<string, string> = {
    'Content-Type': 'application/json',
  };

  if (auth) {
    const token = Taro.getStorageSync(config.TOKEN_KEY);
    if (token) {
      header['Authorization'] = `Bearer ${token}`;
    }
  }

  const fullUrl = buildUrl(`${config.API_BASE_URL}${url}`, params);

  try {
    const response = await Taro.request({
      url: fullUrl,
      method,
      data,
      header,
      timeout: config.REQUEST_TIMEOUT,
    });

    const statusCode = response.statusCode;

    if (statusCode === 401) {
      Taro.removeStorageSync(config.TOKEN_KEY);
      Taro.removeStorageSync(config.USER_KEY);
      Taro.reLaunch({ url: '/pages/login/index' });
      throw new Error('未登录或登录已过期');
    }

    if (statusCode < 200 || statusCode >= 300) {
      const msg = (response.data as ApiResponse)?.message || `请求失败 (${statusCode})`;
      Taro.showToast({ title: msg, icon: 'none', duration: 2000 });
      throw new Error(msg);
    }

    const body = response.data as ApiResponse<T>;
    return (body.data !== undefined ? body.data : body) as T;
  } catch (error: unknown) {
    if (error instanceof Error && error.message === '未登录或登录已过期') {
      throw error;
    }
    const msg = error instanceof Error ? error.message : '网络异常，请稍后重试';
    Taro.showToast({ title: msg, icon: 'none', duration: 2000 });
    throw error;
  }
}

/** GET 请求 */
export function get<T = unknown>(url: string, params?: Record<string, unknown>, auth = true) {
  return request<T>({ url, method: 'GET', params, auth });
}

/** POST 请求 */
export function post<T = unknown>(url: string, data?: Record<string, unknown>, auth = true) {
  return request<T>({ url, method: 'POST', data, auth });
}

/** PUT 请求 */
export function put<T = unknown>(url: string, data?: Record<string, unknown>, auth = true) {
  return request<T>({ url, method: 'PUT', data, auth });
}

/** DELETE 请求 */
export function del<T = unknown>(url: string, data?: Record<string, unknown>, auth = true) {
  return request<T>({ url, method: 'DELETE', data, auth });
}

export default request;
