import axios, { AxiosError, type InternalAxiosRequestConfig } from "axios";
import { notifyPointBalanceChanged } from "@/utils/pointBalance";
const http = axios.create({ baseURL: "/api/web", timeout: 20000 });
let refreshing: Promise<string> | null = null;
let lastActiveTaskSync = 0;
const activeTaskStatuses = new Set([
  "pending_submission",
  "submitting",
  "submitted",
  "queued",
  "running",
  "processing",
  "retry_wait",
  "cancel_requested",
  "analyzing",
]);
const pointMutationPattern =
  /\/(?:parse|reparse|analyze|reanalyze|redraw-analyze|redraw-reanalyze|redraw-script|reinfer|redraw-reinfer|generate|cancel)(?:\?|$)/;

function containsActivePointTask(value: unknown): boolean {
  if (Array.isArray(value)) return value.some(containsActivePointTask);
  if (!value || typeof value !== "object") return false;
  const item = value as Record<string, unknown>;
  if (
    typeof item.id === "string" &&
    typeof item.status === "string" &&
    activeTaskStatuses.has(item.status) &&
    ("estimated_points" in item || "prepaid_points" in item || "actual_points" in item)
  )
    return true;
  return Object.values(item).some(containsActivePointTask);
}

function shouldSyncPointBalance(response: { config: InternalAxiosRequestConfig; data: unknown }) {
  const method = response.config.method?.toLowerCase();
  const url = response.config.url || "";
  if (method === "post" && pointMutationPattern.test(url)) return true;
  if (!containsActivePointTask(response.data)) return false;
  const now = Date.now();
  if (now - lastActiveTaskSync < 1500) return false;
  lastActiveTaskSync = now;
  return true;
}
http.interceptors.request.use((config) => {
  const token = localStorage.getItem("web_access_token");
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});
http.interceptors.response.use(
  (response) => {
    if (shouldSyncPointBalance(response)) notifyPointBalanceChanged();
    return response;
  },
  async (error: AxiosError) => {
    const request = error.config as (InternalAxiosRequestConfig & { _retried?: boolean }) | undefined;
    if (error.response?.status === 401 && request && !request._retried && !request.url?.includes("/auth/")) {
      request._retried = true;
      try {
        const token = await refresh();
        request.headers.Authorization = `Bearer ${token}`;
        return http(request);
      } catch {
        clearAuth();
        if (location.pathname != "/login")
          location.href = `/login?redirect=${encodeURIComponent(location.pathname + location.search)}`;
      }
    }
    return Promise.reject(error);
  },
);
async function refresh() {
  if (!refreshing)
    refreshing = axios
      .post("/api/web/auth/refresh", { refresh_token: localStorage.getItem("web_refresh_token") })
      .then(({ data }) => {
        saveTokens(data.data);
        return data.data.access_token as string;
      })
      .finally(() => (refreshing = null));
  return refreshing;
}
export function saveTokens(data: { access_token: string; refresh_token: string; user?: unknown }) {
  localStorage.setItem("web_access_token", data.access_token);
  localStorage.setItem("web_refresh_token", data.refresh_token);
  if (data.user) localStorage.setItem("web_profile", JSON.stringify(data.user));
}
export function clearAuth() {
  localStorage.removeItem("web_access_token");
  localStorage.removeItem("web_refresh_token");
  localStorage.removeItem("web_profile");
}
export function apiError(error: unknown) {
  const e = error as AxiosError<{ code?: string; message?: string; trace_id?: string }>;
  const body = e.response?.data;
  const message = body?.message || e.message || "请求失败";
  return {
    message,
    copyText: `错误码：${body?.code || "request_failed"}\n错误描述：${message}\n请求追踪 ID：${body?.trace_id || e.response?.headers?.["x-request-id"] || "无"}`,
  };
}
export default http;
