import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios';
import { Toast } from 'antd-mobile';

export interface ApiResponse<T> {
  success: boolean;
  code: string;
  message: string;
  data: T;
  timestamp: string;
}

export interface PageResponse<T> {
  list: T[];
  pageNum: number;
  pageSize: number;
  total: number;
  pages: number;
}

const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL ?? '',
  timeout: 30_000,
});

api.interceptors.request.use((config) => {
  const token = localStorage.getItem('mobile.accessToken');
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});

// ── 401 → refreshToken 으로 access 갱신 후 원 요청 재시도 ──
// 동시 401 다발 시 단일 refresh 호출로 합치고, 그 결과를 모두에 broadcast.
let refreshing: Promise<string | null> | null = null;

async function refreshAccessToken(): Promise<string | null> {
  const refreshToken = localStorage.getItem('mobile.refreshToken');
  if (!refreshToken) return null;
  try {
    const res = await axios.post<ApiResponse<{ accessToken: string }>>(
      '/api/auth/refresh',
      { refreshToken },
      { timeout: 10_000 },
    );
    const body = res.data;
    if (!body?.success || !body.data?.accessToken) return null;
    const next = body.data.accessToken;
    localStorage.setItem('mobile.accessToken', next);
    return next;
  } catch {
    return null;
  }
}

function clearSessionAndRedirect() {
  localStorage.removeItem('mobile.accessToken');
  localStorage.removeItem('mobile.refreshToken');
  localStorage.removeItem('mobile.profile');
  if (!window.location.pathname.startsWith('/login')) {
    window.location.href = '/login';
  }
}

api.interceptors.response.use(
  (res) => {
    const body = res.data;
    if (body && typeof body === 'object' && 'success' in body && body.success === false) {
      Toast.show({ icon: 'fail', content: body.message ?? '오류가 발생했습니다' });
      return Promise.reject(body);
    }
    return res;
  },
  async (err: AxiosError<ApiResponse<unknown>>) => {
    const status = err.response?.status;
    const body = err.response?.data;
    const config = err.config as (InternalAxiosRequestConfig & { _retried?: boolean }) | undefined;

    if (status === 401 && config && !config._retried) {
      // 무한 재시도 차단 + refresh 호출 자체의 401 차단
      if (config.url?.includes('/api/auth/refresh') || config.url?.includes('/api/auth/login')) {
        clearSessionAndRedirect();
        return Promise.reject(err);
      }

      config._retried = true;
      if (!refreshing) {
        refreshing = refreshAccessToken().finally(() => {
          refreshing = null;
        });
      }
      const newAccess = await refreshing;
      if (newAccess) {
        config.headers = config.headers ?? ({} as any);
        (config.headers as Record<string, string>).Authorization = `Bearer ${newAccess}`;
        return api.request(config);
      }
      clearSessionAndRedirect();
      return Promise.reject(err);
    }

    if (status === 401) {
      clearSessionAndRedirect();
    } else if (status === 403) {
      Toast.show({ icon: 'fail', content: body?.message ?? '권한이 없습니다' });
    } else {
      Toast.show({ icon: 'fail', content: body?.message ?? err.message ?? '서버 오류' });
    }
    return Promise.reject(err);
  },
);

export default api;

export async function unwrap<T>(p: Promise<{ data: ApiResponse<T> }>): Promise<T> {
  const res = await p;
  return res.data.data;
}
