/**
 * HTTP客户端
 * 用于与后端API进行通信
 */

/**
 * HTTP请求方法类型
 */
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';

/**
 * HTTP请求选项
 */
export interface HttpRequestOptions {
  /** 请求方法 */
  method: HttpMethod;
  /** 请求URL */
  url: string;
  /** 请求头 */
  headers?: Record<string, string>;
  /** 请求体 */
  body?: any;
  /** 是否需要认证 */
  needAuth?: boolean;
}

/**
 * HTTP响应类型
 */
export interface HttpResponse<T = any> {
  /** 状态码 */
  status: number;
  /** 状态文本 */
  statusText: string;
  /** 响应体 */
  data: T;
  /** 响应头 */
  headers: Record<string, string>;
}

/**
 * HTTP错误类型
 */
export class HttpError extends Error {
  /** 状态码 */
  public status: number;
  /** 状态文本 */
  public statusText: string;
  /** 错误数据 */
  public data: any;

  /**
   * 构造函数
   * @param message 错误信息
   * @param status 状态码
   * @param statusText 状态文本
   * @param data 错误数据
   */
  constructor(message: string, status: number, statusText: string, data: any) {
    super(message);
    this.name = 'HttpError';
    this.status = status;
    this.statusText = statusText;
    this.data = data;
  }
}

/**
 * HTTP客户端类
 */
export class HttpClient {
  private tokenGetter?: () => string | null;
  private tenantId?: string;

  /**
   * 构造函数
   * @param logout
   * @param tokenGetter Token获取函数
   */
  constructor(tokenGetter?: () => string | null) {
    this.tokenGetter = tokenGetter;

  }

  /**
   * 设置Token获取函数
   * @param tokenGetter Token获取函数
   */
  setTokenGetter(tokenGetter: () => string | null): void {
    this.tokenGetter = tokenGetter;
  }

  /**
   * 设置租户ID
   * @param tenantId 租户ID
   */
  setTenantId(tenantId?: string): void {
    this.tenantId = tenantId;
  }

  /**
   * 发送HTTP请求
   * @param options 请求选项
   * @returns Promise<HttpResponse<T>> 响应结果
   */
  async request<T = any>(options: HttpRequestOptions): Promise<HttpResponse<T>> {
    const {
      method,
      url,
      headers = {},
      body,
      needAuth = true
    } = options;

    // 构建请求头
    const requestHeaders: Record<string, string> = {
      'Content-Type': 'application/json',
      ...headers
    };

    // 添加认证头
    const addAuthHeader = () => {
      if (needAuth && this.tokenGetter) {
        const token = this.tokenGetter();
        if (token) {
          requestHeaders.Authorization = `${token}`;
        }
      }
    };

    // 添加租户ID头
    if (this.tenantId) {
      requestHeaders['tenant-id'] = this.tenantId;
    }

    addAuthHeader();

    // 构建请求配置
    const fetchOptions: RequestInit = {
      method,
      headers: requestHeaders,
      credentials: 'include' // 包含cookie
    };

    // 添加请求体
    if (body && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {
      fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
    }

    try {
      // 发送请求
      const response = await fetch(url, fetchOptions);
      const responseData = await this.parseResponse(response);

      // 检查响应状态
      if (!response.ok) {
        // 如果是401错误，尝试刷新Token并重试
        if (response.status === 401) {
          return {
            status: response.status,
            statusText: response.statusText,
            data: '' as T,
            headers: this.parseHeaders(response.headers)
          }
        }
        
        // 其他错误，直接抛出
        const errorMsg = this.getErrorMessage(responseData);
        throw new HttpError(
          errorMsg,
          response.status,
          response.statusText,
          responseData
        );
      }

      // 处理成功响应的业务逻辑
      return this.handleResponse(response, responseData);
    } catch (error) {
      if (error instanceof HttpError) {
        throw error;
      }

      // 网络错误或其他错误
      throw new HttpError(
        error instanceof Error ? error.message : 'Network Error',
        0,
        'Network Error',
        null
      );
    }
  }
  


  /**
   * 处理响应数据
   * @param response 响应对象
   * @param responseData 响应数据
   * @returns HttpResponse<T> 处理后的响应
   */
  private handleResponse<T = any>(response: Response, responseData: any): HttpResponse<T> {
    // 检查是否为业务响应结构
    if (this.isBusinessResponse(responseData)) {
      // 业务响应结构：{ code, msg, data }
      const { code, msg, data } = responseData;
      
      // 检查业务状态码
      if (code !== 0 && code !== 200 && code !== '0' && code !== '200') {
        // 业务错误，抛出HttpError
        throw new HttpError(
          msg || `Business Error: ${code}`,
          response.status,
          response.statusText,
          responseData
        );
      }
      
      // 业务成功，返回data字段作为实际数据
      return {
        status: response.status,
        statusText: response.statusText,
        data: data as T,
        headers: this.parseHeaders(response.headers)
      };
    }
    
    // 非业务响应结构，直接返回原始数据
    return {
      status: response.status,
      statusText: response.statusText,
      data: responseData as T,
      headers: this.parseHeaders(response.headers)
    };
  }

  /**
   * 检查是否为业务响应结构
   * @param responseData 响应数据
   * @returns boolean 是否为业务响应结构
   */
  private isBusinessResponse(responseData: any): boolean {
    return typeof responseData === 'object' && 
           responseData !== null && 
           ('code' in responseData) && 
           ('msg' in responseData) && 
           ('data' in responseData);
  }

  /**
   * 获取错误信息
   * @param responseData 响应数据
   * @returns string 错误信息
   */
  private getErrorMessage(responseData: any): string {
    // 如果是业务响应结构
    if (this.isBusinessResponse(responseData)) {
      return responseData.msg || `Business Error: ${responseData.code}`;
    }
    
    // 其他错误结构
    return responseData.message || responseData.error || `HTTP Error`;
  }

  /**
   * GET请求
   * @param url 请求URL
   * @param options 请求选项
   * @returns Promise<HttpResponse<T>> 响应结果
   */
  async get<T = any>(url: string, options?: Omit<HttpRequestOptions, 'method' | 'url'>): Promise<HttpResponse<T>> {
    return this.request<T>({
      method: 'GET',
      url,
      ...options
    });
  }

  /**
   * POST请求
   * @param url 请求URL
   * @param body 请求体
   * @param options 请求选项
   * @returns Promise<HttpResponse<T>> 响应结果
   */
  async post<T = any>(url: string, body?: any, options?: Omit<HttpRequestOptions, 'method' | 'url' | 'body'>): Promise<HttpResponse<T>> {
    return this.request<T>({
      method: 'POST',
      url,
      body,
      ...options
    });
  }

  /**
   * PUT请求
   * @param url 请求URL
   * @param body 请求体
   * @param options 请求选项
   * @returns Promise<HttpResponse<T>> 响应结果
   */
  async put<T = any>(url: string, body?: any, options?: Omit<HttpRequestOptions, 'method' | 'url' | 'body'>): Promise<HttpResponse<T>> {
    return this.request<T>({
      method: 'PUT',
      url,
      body,
      ...options
    });
  }

  /**
   * DELETE请求
   * @param url 请求URL
   * @param options 请求选项
   * @returns Promise<HttpResponse<T>> 响应结果
   */
  async delete<T = any>(url: string, options?: Omit<HttpRequestOptions, 'method' | 'url'>): Promise<HttpResponse<T>> {
    return this.request<T>({
      method: 'DELETE',
      url,
      ...options
    });
  }

  /**
   * PATCH请求
   * @param url 请求URL
   * @param body 请求体
   * @param options 请求选项
   * @returns Promise<HttpResponse<T>> 响应结果
   */
  async patch<T = any>(url: string, body?: any, options?: Omit<HttpRequestOptions, 'method' | 'url' | 'body'>): Promise<HttpResponse<T>> {
    return this.request<T>({
      method: 'PATCH',
      url,
      body,
      ...options
    });
  }

  /**
   * 解析响应体
   * @param response 响应对象
   * @returns Promise<any> 解析后的响应体
   */
  private async parseResponse(response: Response): Promise<any> {
    const contentType = response.headers.get('content-type') || '';
    
    if (contentType.includes('application/json')) {
      return response.json();
    } else if (contentType.includes('text/')) {
      return response.text();
    } else {
      return response.blob();
    }
  }

  /**
   * 解析响应头
   * @param headers 响应头对象
   * @returns Record<string, string> 解析后的响应头
   */
  private parseHeaders(headers: Headers): Record<string, string> {
    const result: Record<string, string> = {};
    headers.forEach((value, key) => {
      result[key] = value;
    });
    return result;
  }
}
