// ============================================================
// Infrastructure — HTTP Client
// 替代旧版 src/lib/api-client.ts，作为所有 Repository 的底层实现
// 从 Zustand auth store 读取 token（而非直接操作 localStorage）
// ============================================================

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'https://api.gogenex.com';

class HttpClient {
  private client: AxiosInstance;
  // 防并发刷新锁：多个请求同时 401 时只发一次 refresh
  private refreshPromise: Promise<string> | null = null;

  constructor() {
    this.client = axios.create({
      baseURL: API_BASE_URL,
      timeout: 30000,
      headers: { 'Content-Type': 'application/json' },
    });

    // Request 拦截器：注入 Bearer token
    this.client.interceptors.request.use((config) => {
      if (typeof window !== 'undefined') {
        try {
          const raw = localStorage.getItem('gcx-admin-auth');
          if (raw) {
            const { state } = JSON.parse(raw);
            if (state?.token) {
              config.headers.Authorization = `Bearer ${state.token}`;
            }
          }
        } catch {
          // ignore parse errors
        }
      }
      return config;
    });

    // Response 拦截器：401 → 尝试 refresh token，成功则重试；失败才跳登录
    this.client.interceptors.response.use(
      (response) => response,
      async (error) => {
        const originalRequest = error.config;
        if (error.response?.status !== 401 || originalRequest._retry || typeof window === 'undefined') {
          return Promise.reject(error);
        }

        // 标记已重试，防止无限循环
        originalRequest._retry = true;

        try {
          console.log('[HttpClient] 401 detected, attempting token refresh...');
          const newToken = await this.refreshAccessToken();
          console.log('[HttpClient] Token refreshed, retrying:', originalRequest.url);
          originalRequest.headers.Authorization = `Bearer ${newToken}`;
          return this.client(originalRequest);
        } catch (refreshErr) {
          // refresh 也失败 → 清空登录态，跳转登录
          console.error('[HttpClient] Token refresh failed, redirecting to login:', refreshErr);
          localStorage.removeItem('gcx-admin-auth');
          window.location.href = '/login';
          return Promise.reject(error);
        }
      },
    );
  }

  private async refreshAccessToken(): Promise<string> {
    // 多个并发 401 请求共享同一个 refresh Promise，避免重复刷新
    if (this.refreshPromise) return this.refreshPromise;

    this.refreshPromise = (async () => {
      try {
        const raw = localStorage.getItem('gcx-admin-auth');
        if (!raw) throw new Error('No auth state');
        const { state } = JSON.parse(raw);
        if (!state?.refreshToken) throw new Error('No refresh token');

        console.log('[HttpClient] Calling refresh endpoint...');
        const resp = await axios.post(`${API_BASE_URL}/api/v1/auth/refresh`, {
          refreshToken: state.refreshToken,
        });
        const newAccessToken: string = resp.data?.data?.accessToken ?? resp.data?.accessToken;
        if (!newAccessToken) throw new Error('No access token in refresh response');

        console.log('[HttpClient] Got new access token, updating storage...');
        // 更新 localStorage 中的 token（Zustand store 下次读取时自动感知）
        const updated = JSON.parse(raw);
        updated.state.token = newAccessToken;
        localStorage.setItem('gcx-admin-auth', JSON.stringify(updated));

        return newAccessToken;
      } finally {
        this.refreshPromise = null;
      }
    })();

    return this.refreshPromise;
  }

  async get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
    const response: AxiosResponse = await this.client.get(url, config);
    const raw = response.data;
    const result = raw?.data ?? raw;
    console.log('[HttpClient.get]', url, '→ raw:', raw, '→ result:', result, 'isArray:', Array.isArray(result));
    return result;
  }

  async post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
    const response: AxiosResponse = await this.client.post(url, data, config);
    return response.data?.data ?? response.data;
  }

  async put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
    const response: AxiosResponse = await this.client.put(url, data, config);
    return response.data?.data ?? response.data;
  }

  async patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
    const response: AxiosResponse = await this.client.patch(url, data, config);
    return response.data?.data ?? response.data;
  }

  async delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
    const response: AxiosResponse = await this.client.delete(url, config);
    return response.data?.data ?? response.data;
  }
}

export const httpClient = new HttpClient();
