/**
 * 认证刷新拦截器
 *
 * 处理 401 错误，自动刷新 token 并重试原请求。
 * 
 */
import type { FetchHook } from "ofetch";
import { ApiPath } from "../../../data/services/api/api_path";
import { ApiError, ErrorCode } from "../../../data/services/api/api_result";
import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { AppEnvUtil, deviceIdentifier, Result } from "@/utils";

/**
 * 不需要 auth token 刷新的路径
 * （这些路径返回 401 时不触发刷新）
 */
const NO_AUTH_REFRESH_PATHS: readonly string[] = [
  ApiPath.sendCode,
  ApiPath.emailLogin,
  ApiPath.register,
  ApiPath.guestLogin,
  ApiPath.refresh,
];

/**
 * 是否正在刷新 token（防止并发刷新）
 */
let isRefreshing = false;

/**
 * 等待中的刷新 Promise
 */
let refreshPromise: Promise<void> | null = null;

/**
 * 获取当前可用的 auth token（登录 token 优先，其次游客 token）
 */
async function getAuthTokenAsync(): Promise<string | null> {
  const storage = AuthStorage.getInstance();
  const loginResult = await storage.getLoginToken();
  if (Result.isOk(loginResult) && loginResult.data && loginResult.data.length > 0) {
    return loginResult.data;
  }
  const guestResult = await storage.getGuestToken();
  if (Result.isOk(guestResult) && guestResult.data && guestResult.data.length > 0) {
    return guestResult.data;
  }
  return null;
}

/**
 * 实际刷新 token（被拦截器调用）
 */
async function refreshToken(
  isGuestMode: boolean,
  baseUrl: string
): Promise<void> {
  if (isGuestMode) {
    await refreshGuestToken(baseUrl);
  } else {
    await refreshLoginToken(baseUrl);
  }
}

/**
 * 刷新登录 token
 */
async function refreshLoginToken(baseUrl: string): Promise<void> {
  const storage = AuthStorage.getInstance();
  const refreshResult = await storage.getRefreshToken();
  if (!Result.isOk(refreshResult) || !refreshResult.data) {
    throw new Error("No refresh token available");
  }

  const response = await fetch(`${baseUrl}${ApiPath.refresh}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ refreshToken: refreshResult.data }),
  });

  if (!response.ok) {
    throw new Error(`Refresh failed: ${response.status}`);
  }

  const json = (await response.json()) as {
    success?: boolean;
    data?: { token?: string; refreshToken?: string };
  };

  if (json.success && json.data) {
    if (json.data.token) await storage.setLoginToken(json.data.token);
    if (json.data.refreshToken) await storage.setRefreshToken(json.data.refreshToken);
  } else {
    throw new Error("Refresh response invalid");
  }
}

/**
 * 刷新游客 token
 */
async function refreshGuestToken(baseUrl: string): Promise<void> {
  const storage = AuthStorage.getInstance();
  const deviceId = await deviceIdentifier.getDeviceId();

  const response = await fetch(`${baseUrl}${ApiPath.guestLogin}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(withTestAccountFlag({ deviceId })),
  });

  if (!response.ok) {
    throw new Error(`Guest refresh failed: ${response.status}`);
  }

  const json = (await response.json()) as {
    success?: boolean;
    data?: { token?: string; deviceId?: string };
  };

  if (json.success && json.data) {
    if (json.data.token) await storage.setGuestToken(json.data.token);
    if (json.data.deviceId) await storage.setDeviceId(json.data.deviceId);
  } else {
    throw new Error("Guest refresh response invalid");
  }
}

function withTestAccountFlag<T extends Record<string, unknown>>(
  payload: T,
): T & { isTestAccount: boolean } {
  return { ...payload, isTestAccount: !AppEnvUtil.isProduction() };
}

/**
 * 401 → 刷新 token 并重试
 */
export const onResponseErrorAuthRefresh: FetchHook = async (ctx) => {
  const status = ctx.response?.status;

  // 只处理 401
  if (status !== ErrorCode.httpUnauthorized) return;

  // 跳过不需要刷新的路径
  const requestUrl =
    ctx.request instanceof Request ? ctx.request.url : ctx.request;
  const path = new URL(requestUrl).pathname;
  if (NO_AUTH_REFRESH_PATHS.some((p) => path.includes(p))) return;

  // 已登录则刷新登录 token，否则刷新游客 token
  const isGuestMode = !AuthStorage.getInstance().hasLoginToken();

  // 并发刷新：等待或启动
  if (isRefreshing && refreshPromise) {
    await refreshPromise;
  } else {
    isRefreshing = true;
    const baseUrl = new URL(requestUrl).origin;
    refreshPromise = (async () => {
      try {
        await refreshToken(isGuestMode, baseUrl);
      } finally {
        isRefreshing = false;
        refreshPromise = null;
      }
    })();
    await refreshPromise;
  }

  // 刷新失败 → 清除数据并抛出
  const newToken = await getAuthTokenAsync();
  if (!newToken) {
    AuthStorage.getInstance().clearAuthData();
    throw new ApiError(
      ErrorCode.unknownError,
      "Token refresh failed",
      status
    );
  }

  // 刷新成功：更新请求头的 token
  if (ctx.request instanceof Request) {
    ctx.request.headers.set("Authorization", `Bearer ${newToken}`);
  }
};

/**
 * 兼容旧接口的 FetchHooks 形式
 */
export const authRefreshInterceptor = {
  onResponseError: onResponseErrorAuthRefresh,
};
