/**
 * MiniProgram Request Adapter
 *
 * 基于 Taro.request 的请求适配器实现
 */

import type {
  IRequestAdapter,
  RequestConfig,
  RequestResponse,
  RequestInterceptor,
} from './interface';

export class MiniprogramRequestAdapter implements IRequestAdapter {
  private Taro: any;
  private baseURL: string = '';
  private defaultHeaders: Record<string, string> = {
    'Content-Type': 'application/json',
  };
  private interceptors: RequestInterceptor[] = [];

  constructor(Taro: any) {
    this.Taro = Taro;
  }

  private buildURL(url: string, params?: Record<string, any>): string {
    const fullURL = url.startsWith('http') ? url : `${this.baseURL}${url}`;

    if (!params || Object.keys(params).length === 0) {
      return fullURL;
    }

    const queryString = Object.entries(params)
      .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
      .join('&');

    return `${fullURL}${fullURL.includes('?') ? '&' : '?'}${queryString}`;
  }

  async request<T = any>(config: RequestConfig): Promise<RequestResponse<T>> {
    try {
      // 应用请求拦截器
      let modifiedConfig = { ...config };
      for (const interceptor of this.interceptors) {
        if (interceptor.onRequest) {
          modifiedConfig = await interceptor.onRequest(modifiedConfig);
        }
      }

      const url = this.buildURL(modifiedConfig.url, modifiedConfig.params);
      const headers = { ...this.defaultHeaders, ...modifiedConfig.headers };

      const response = await this.Taro.request({
        url,
        method: modifiedConfig.method || 'GET',
        data: modifiedConfig.data,
        header: headers,
        timeout: modifiedConfig.timeout || 30000,
        dataType: 'json',
      });

      const result: RequestResponse<T> = {
        data: response.data,
        status: response.statusCode,
        statusText: response.errMsg || '',
        headers: response.header || {},
      };

      // 应用响应拦截器
      let modifiedResponse = result;
      for (const interceptor of this.interceptors) {
        if (interceptor.onResponse) {
          modifiedResponse = await interceptor.onResponse(modifiedResponse);
        }
      }

      return modifiedResponse;
    } catch (error: any) {
      // 应用错误拦截器
      for (const interceptor of this.interceptors) {
        if (interceptor.onResponseError) {
          await interceptor.onResponseError(error);
        }
      }
      throw error;
    }
  }

  async get<T = any>(
    url: string,
    params?: Record<string, any>,
    config?: Partial<RequestConfig>
  ): Promise<RequestResponse<T>> {
    return this.request<T>({
      url,
      method: 'GET',
      params,
      ...config,
    });
  }

  async post<T = any>(
    url: string,
    data?: any,
    config?: Partial<RequestConfig>
  ): Promise<RequestResponse<T>> {
    return this.request<T>({
      url,
      method: 'POST',
      data,
      ...config,
    });
  }

  async put<T = any>(
    url: string,
    data?: any,
    config?: Partial<RequestConfig>
  ): Promise<RequestResponse<T>> {
    return this.request<T>({
      url,
      method: 'PUT',
      data,
      ...config,
    });
  }

  async delete<T = any>(url: string, config?: Partial<RequestConfig>): Promise<RequestResponse<T>> {
    return this.request<T>({
      url,
      method: 'DELETE',
      ...config,
    });
  }

  addInterceptor(interceptor: RequestInterceptor): void {
    this.interceptors.push(interceptor);
  }

  setBaseURL(baseURL: string): void {
    this.baseURL = baseURL;
  }

  setHeader(key: string, value: string): void {
    this.defaultHeaders[key] = value;
  }
}
