/**
 * API 客户端
 * 使用 fetch API 进行 HTTP 请求
 * 支持请求/响应拦截器
 */

import AsyncStorage from '@react-native-async-storage/async-storage';
import { CommonActions } from '@react-navigation/native';
import Constants from 'expo-constants';

// 生产地址 https://bbs.littlelan.cn
const getBaseUrl = () => {
  const configuredBaseUrl = Constants.expoConfig?.extra?.apiBaseUrl;
  if (typeof configuredBaseUrl === 'string' && configuredBaseUrl.trim().length > 0) {
    return configuredBaseUrl;
  }
  return 'https://bbs.littlelan.cn/api/v1';
};

const BASE_URL = getBaseUrl();
const SSE_URL = `${BASE_URL.replace(/\/+$/, '')}/realtime/sse`;

// Token 存储键
const TOKEN_KEY = 'auth_token';
const REFRESH_TOKEN_KEY = 'refresh_token';

// API 响应格式
export interface ApiResponse<T> {
  code: number;
  message: string;
  data: T;
}

// 分页响应格式
export interface PaginatedData<T> {
  list: T[];
  total: number;
  page: number;
  page_size: number;
  total_pages: number;
}

// 错误类型
export class ApiError extends Error {
  code: number;
  message: string;

  constructor(code: number, message: string) {
    super(message);
    this.code = code;
    this.message = message;
    this.name = 'ApiError';
  }
}

// API 客户端类
class ApiClient {
  private baseUrl: string;
  private navigation: any = null;

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }

  // 设置导航对象（用于处理401跳转）
  setNavigation(navigation: any) {
    this.navigation = navigation;
  }

  // 获取 token
  async getToken(): Promise<string | null> {
    try {
      return await AsyncStorage.getItem(TOKEN_KEY);
    } catch (error) {
      console.error('获取token失败:', error);
      return null;
    }
  }

  // 保存 token
  async setToken(token: string): Promise<void> {
    try {
      await AsyncStorage.setItem(TOKEN_KEY, token);
    } catch (error) {
      console.error('保存token失败:', error);
    }
  }

  // 获取刷新 token
  async getRefreshToken(): Promise<string | null> {
    try {
      return await AsyncStorage.getItem(REFRESH_TOKEN_KEY);
    } catch (error) {
      console.error('获取刷新token失败:', error);
      return null;
    }
  }

  // 保存刷新 token
  async setRefreshToken(token: string): Promise<void> {
    try {
      await AsyncStorage.setItem(REFRESH_TOKEN_KEY, token);
    } catch (error) {
      console.error('保存刷新token失败:', error);
    }
  }

  // 清除 token
  async clearToken(): Promise<void> {
    try {
      await AsyncStorage.multiRemove([TOKEN_KEY, REFRESH_TOKEN_KEY]);
    } catch (error) {
      console.error('清除token失败:', error);
    }
  }

  // 统一请求方法
  private async request<T>(
    method: string,
    path: string,
    params?: Record<string, any>,
    body?: any
  ): Promise<ApiResponse<T>> {
    const url = new URL(`${this.baseUrl}${path}`);
    
    // 添加查询参数
    if (params) {
      Object.keys(params).forEach(key => {
        if (params[key] !== undefined && params[key] !== null) {
          url.searchParams.append(key, String(params[key]));
        }
      });
    }

    // 构建请求头
    const headers: HeadersInit = {
      'Content-Type': 'application/json',
    };

    // 添加认证 token
    const token = await this.getToken();
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }

    // 构建请求配置
    const config: RequestInit = {
      method,
      headers,
    };

    // 添加请求体
    if (body && method !== 'GET') {
      config.body = JSON.stringify(body);
    }

    try {
      const response = await fetch(url.toString(), config);
      
      // 处理 401 未授权
      if (response.status === 401) {
        // 尝试刷新 token
        const refreshed = await this.refreshToken();
        if (!refreshed) {
          // 刷新失败，清除 token 并跳转登录
          await this.clearToken();
          if (this.navigation) {
            this.navigation.dispatch(
              CommonActions.reset({
                index: 0,
                routes: [{ name: 'Login' }],
              })
            );
          }
          throw new ApiError(401, '登录已过期，请重新登录');
        }
        
        // 刷新成功后重试请求
        return this.request(method, path, params, body);
      }

      // 解析响应（兼容非 JSON 返回，避免 SyntaxError 被误判为网络错误）
      const contentType = response.headers.get('content-type') || '';
      let parsedBody: any = null;
      let rawText = '';

      if (contentType.includes('application/json')) {
        parsedBody = await response.json();
      } else {
        rawText = await response.text();
        if (rawText) {
          try {
            parsedBody = JSON.parse(rawText);
          } catch {
            parsedBody = null;
          }
        }
      }

      // 优先处理标准 API 结构
      if (parsedBody && typeof parsedBody === 'object' && 'code' in parsedBody) {
        const data = parsedBody as ApiResponse<T>;
        if (data.code !== 0) {
          throw new ApiError(data.code, data.message || '请求失败');
        }
        return data;
      }

      // 非标准结构：先按 HTTP 状态处理失败
      if (!response.ok) {
        const fallbackMessage = rawText || response.statusText || `请求失败(${response.status})`;
        throw new ApiError(response.status, fallbackMessage);
      }

      // 非标准结构但 HTTP 成功：兜底为成功响应（兼容部分纯文本成功接口）
      return {
        code: 0,
        message: 'success',
        data: (parsedBody as T) ?? (undefined as T),
      };
    } catch (error) {
      // 如果是 ApiError，直接抛出
      if (error instanceof ApiError) {
        throw error;
      }
      
      // 网络错误
      console.error('API请求失败:', error);
      throw new ApiError(500, '网络请求失败，请检查网络连接');
    }
  }

  // 刷新 token
  private async refreshToken(): Promise<boolean> {
    try {
      const refreshToken = await this.getRefreshToken();
      if (!refreshToken) {
        return false;
      }

      const response = await fetch(`${this.baseUrl}/auth/refresh`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${refreshToken}`,
        },
      });

      if (!response.ok) {
        return false;
      }

      const data = await response.json();
      if (data.code === 0 && data.data?.token) {
        await this.setToken(data.data.token);
        // 后端返回refresh_token (snake_case)，兼容两种命名
        if (data.data.refresh_token || data.data.refreshToken) {
          await this.setRefreshToken(data.data.refresh_token || data.data.refreshToken);
        }
        return true;
      }

      return false;
    } catch (error) {
      console.error('刷新token失败:', error);
      return false;
    }
  }

  // GET 请求
  async get<T>(path: string, params?: Record<string, any>): Promise<ApiResponse<T>> {
    return this.request<T>('GET', path, params);
  }

  // POST 请求
  async post<T>(path: string, body?: any): Promise<ApiResponse<T>> {
    return this.request<T>('POST', path, undefined, body);
  }

  // PUT 请求
  async put<T>(path: string, body?: any): Promise<ApiResponse<T>> {
    return this.request<T>('PUT', path, undefined, body);
  }

  // DELETE 请求
  async delete<T>(path: string, body?: any): Promise<ApiResponse<T>> {
    return this.request<T>('DELETE', path, undefined, body);
  }

  // 上传文件
  async upload<T>(
    path: string,
    file: { uri: string; name: string; type: string },
    additionalData?: Record<string, string>
  ): Promise<ApiResponse<T>> {
    const formData = new FormData();
    
    // 添加文件（使用image字段名）
    formData.append('image', {
      uri: file.uri,
      name: file.name,
      type: file.type,
    } as any);

    // 添加额外数据
    if (additionalData) {
      Object.keys(additionalData).forEach(key => {
        formData.append(key, additionalData[key]);
      });
    }

    const token = await this.getToken();
    const headers: HeadersInit = {};
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }

    const response = await fetch(`${this.baseUrl}${path}`, {
      method: 'POST',
      headers,
      body: formData,
    });

    const data: ApiResponse<T> = await response.json();
    
    if (data.code !== 0) {
      throw new ApiError(data.code, data.message);
    }

    return data;
  }
}

// 导出 API 客户端实例
export const api = new ApiClient(BASE_URL);

export { SSE_URL, TOKEN_KEY, REFRESH_TOKEN_KEY };
