import axios from "axios";
import { useAuthStore } from "@/store/auth-store";

/**
 * API 클라이언트
 *
 * @description
 * 백엔드 API와 통신하기 위한 axios 전역 인스턴스
 * apiClient는 모든 API 요청을 만들고 baseURL, timeout, 인증 토큰 등을 자동으로 처리
 * 요청/응답 인터셉터를 통해 요청구조 및 응답, 에러 처리를 일관되게 관리
 * 모듈 로드(import)되는 순간 처음 로드될때 인터셉터들이 생성되어 재사용
 */
const apiClient = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000",
  timeout: 60000, // 60초
  headers: {
    "Content-Type": "application/json", // 기본 요청 본문 타입
  },
});

/**
 * 요청 인터셉터(request.use)
 * 모든 요청에 자동으로 JWT 토큰을 추가
 */
apiClient.interceptors.request.use(
  (config) => {
    // 상태 스토어에서 토큰 가져오기 (persist가 관리)
    const token = useAuthStore.getState().accessToken;
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    return config;
  },
  (error) => {
    console.error(" [API 요청 에러]:", error);
    return Promise.reject(error);
  }
);

/**
 * 응답 인터셉터(response.use)
 *
 * @description
 * 1. 백엔드 응답을 자동으로 언래핑(unwrapping)합니다.
 *    래핑 응답을 유지하고 메타정보(success, timestamp) 쓰기
 * 2. 에러를 일관된 형식으로 처리
 *
 */
apiClient.interceptors.response.use(
  (response) => {
    // 백엔드 TransformInterceptor가 래핑한 응답 자동 언래핑 (backend\src\main.ts)
    // axios가 반환하는 response 객체에 기본적으로 서버의 바디가 response.data에 들어감 
    // Nest의 TransformInterceptor가 그 바디를 다시 { success, data, timestamp }로 감싸줌
    // 따라서 data 필드만 반환하도록 처리
    // 응답 형식 변경 시 한 곳(api-client)만 수정하면 전체 반영
    if (
      response.data &&
      typeof response.data === "object" &&
      "data" in response.data
    ) {
      return response.data.data; // 실제 payload 백엔드 래핑 제거
    }

    // 그 외의 경우 data를 그대로 반환
    return response.data;
  },
  (error) => {
    // 에러 처리
    if (error.response) {
      // 서버가 응답한 에러
      const { status, data, config } = error.response;
      const url = config?.url || "unknown";

      switch (status) {
        case 401:
          // 인증 실패 - 로그인 페이지로 리다이렉트
          console.error(` [API 401 에러] ${url} - 인증 실패`);
          console.error(`  - 응답 데이터:`, data);
          console.error(`  - 에러 메시지:`, data?.message || error.message);
          console.error(`  - 상태 초기화 및 로그인 페이지로 리다이렉트`);

          // 스토어 상태 초기화 (persist가 자동으로 저장소 동기화)
          try {
            useAuthStore.getState().clearAuth();
          } catch (e) {
            console.error("  - 상태 초기화 중 오류:", e);
          }

          if (typeof window !== "undefined") {
            console.error(`  -  로그인 페이지로 이동`);
            window.location.href = "/login";
          }
          break;
        case 403:
          console.error(`[API 403] ${url} - 접근 권한이 없습니다.`);
          break;
        case 404:
          console.error(`[API 404] ${url} - 요청한 리소스를 찾을 수 없습니다.`);
          break;
        case 500:
          console.error(`[API 500] ${url} - 서버 오류가 발생했습니다.`);
          break;
        default:
          console.error(`[API ${status}] ${url} - 에러 발생`);
      }

      // 백엔드 에러 메시지 전달
      throw new Error(
        data.message?.[0] || data.message || "요청 처리 중 오류가 발생했습니다."
      );
    } else if (error.request) {
      // 요청은 보냈지만 응답을 받지 못한 경우
      console.error(
        "[API] 서버 응답 없음:",
        error.request?.responseURL || "unknown"
      );
      throw new Error(
        "서버와 통신할 수 없습니다. 네트워크 연결을 확인해주세요."
      );
    } else {
      // 요청 설정 중 오류 발생
      console.error("[API] 요청 설정 오류:", error.message);
      throw new Error(error.message || "알 수 없는 오류가 발생했습니다.");
    }
  }
);

export default apiClient;
