/**
 * API 客户端 — 统一请求封装
 * 含 JWT 注入 + 401 自动 token 刷新（扒 banana 范式，全新重建）
 * 按契约§0 统一响应包络处理
 */
import { ApiError, ApiResponse } from '@/types/index';
import { ERROR_CODES } from '@/types/errors';

const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || '';

// token 刷新锁，防并发重复刷新
let refreshPromise: Promise<string | null> | null = null;

function getToken(): string | null {
  if (typeof window === 'undefined') return null;
  return localStorage.getItem('clover_token');
}

function setToken(token: string): void {
  localStorage.setItem('clover_token', token);
}

function clearToken(): void {
  localStorage.removeItem('clover_token');
}

async function refreshToken(): Promise<string | null> {
  if (refreshPromise) return refreshPromise;
  refreshPromise = (async () => {
    try {
      // 走 /auth/refresh（二期实现），一期降级跳登录
      clearToken();
      window.location.href = '/login';
      return null;
    } finally {
      refreshPromise = null;
    }
  })();
  return refreshPromise;
}

async function request<T>(
  path: string,
  options: RequestInit = {},
  isFormData = false,
): Promise<T> {
  const token = getToken();
  const headers: Record<string, string> = isFormData
    ? {}  // FormData: 不设 Content-Type，让浏览器填 multipart boundary
    : { 'Content-Type': 'application/json' };
  Object.assign(headers, options.headers as Record<string, string>);
  if (token) headers['Authorization'] = `Bearer ${token}`;

  const res = await fetch(`${BASE_URL}${path}`, { ...options, headers });
  const body: ApiResponse<T> | ApiError = await res.json();

  if ('code' in body && body.code === ERROR_CODES.SUCCESS) {
    return (body as ApiResponse<T>).data;
  }

  const err = body as ApiError;
  if (err.code === ERROR_CODES.UNAUTHENTICATED) {
    const newToken = await refreshToken();
    if (newToken) {
      setToken(newToken);
      return request<T>(path, options, isFormData);
    }
  }

  throw err;
}

// ─── 公开方法 ────────────────────────────────────────────────
export const api = {
  get: <T>(path: string) => request<T>(path, { method: 'GET' }),

  post: <T>(path: string, body?: unknown) =>
    request<T>(path, {
      method: 'POST',
      body: body ? JSON.stringify(body) : undefined,
    }),

  postForm: <T>(path: string, form: FormData) =>
    request<T>(path, { method: 'POST', body: form }, true),

  put: <T>(path: string, body?: unknown) =>
    request<T>(path, {
      method: 'PUT',
      body: body ? JSON.stringify(body) : undefined,
    }),

  delete: <T>(path: string) => request<T>(path, { method: 'DELETE' }),

  /**
   * getBlob — 带 Authorization header 下载二进制文件
   * 用于 C1 修复：download-file 接口需要鉴权，window.open 无法附带 token
   */
  getBlob: async (path: string): Promise<Blob> => {
    const token = getToken();
    const headers: Record<string, string> = {};
    if (token) headers['Authorization'] = `Bearer ${token}`;
    const res = await fetch(`${BASE_URL}${path}`, { method: 'GET', headers });
    if (res.status === 401) {
      await refreshToken();
      throw { code: 40101, message: '认证失败，请重新登录' };
    }
    if (!res.ok) {
      throw { code: 50001, message: `下载失败(${res.status})` };
    }
    return res.blob();
  },

  setToken,
  getToken,
  clearToken,
};
