import axios, {
  AxiosError,
  AxiosInstance,
  InternalAxiosRequestConfig,
} from 'axios';

/** 后端统一响应体 */
export interface ApiResult<T> {
  code: number;
  msg: string;
  data: T;
  path?: string;
  timestamp?: string;
}

/** 分页结果 */
export interface Paginated<T> {
  list: T[];
  total: number;
  page: number;
  pageSize: number;
}

const API_URL = process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:3001/api';
const TOKEN_KEY = process.env.NEXT_PUBLIC_TOKEN_KEY ?? 'admin_token';

/** ---------- Token 存取（仅浏览器端） ---------- */
export const tokenStorage = {
  get(): string | null {
    if (typeof window === 'undefined') return null;
    return window.localStorage.getItem(TOKEN_KEY);
  },
  set(token: string): void {
    if (typeof window === 'undefined') return;
    window.localStorage.setItem(TOKEN_KEY, token);
  },
  clear(): void {
    if (typeof window === 'undefined') return;
    window.localStorage.removeItem(TOKEN_KEY);
  },
};

/** ---------- axios 实例 ---------- */
export const http: AxiosInstance = axios.create({
  baseURL: API_URL,
  timeout: 15000,
});

// 请求拦截：自动注入 JWT
http.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  const token = tokenStorage.get();
  if (token) {
    config.headers.set('Authorization', `Bearer ${token}`);
  }
  return config;
});

// 响应拦截：拆包 + 401 跳登录
// 注：onFulfilled 在拦截器中返回业务数据（拆包后的 data）而非 AxiosResponse，
// 这是项目约定的解包模式；axios 1.x 的类型签名不灵活，必须 cast 为 any
http.interceptors.response.use(
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  (response): any => {
    const body = response.data as ApiResult<unknown>;
    if (body && typeof body.code === 'number') {
      if (body.code === 200) {
        return body.data;
      }
      // 业务错误：抛出，UI 层 try/catch 处理
      return Promise.reject(new Error(body.msg || '请求失败'));
    }
    return body;
  },
  (error: AxiosError<ApiResult<unknown>>) => {
    const status = error.response?.status;
    const msg =
      error.response?.data?.msg ?? error.message ?? '网络异常，请稍后重试';

    if (status === 401) {
      tokenStorage.clear();
      // 避免循环跳转：仅在 /admin 下跳登录
      if (typeof window !== 'undefined') {
        const path = window.location.pathname;
        if (path.startsWith('/admin') && path !== '/admin/login') {
          window.location.href = '/admin/login?expired=1';
        }
      }
    }
    return Promise.reject(new Error(msg));
  },
);

/** ---------- SWR 通用 fetcher ---------- */
export const fetcher = async <T>(url: string): Promise<T> => {
  return (await http.get<unknown, T>(url)) as T;
};

/** ---------- 工具：表单提交包装 ---------- */
export async function submitForm<T>(fn: () => Promise<T>): Promise<T> {
  return fn();
}
