import axios, {
  type AxiosInstance,
  type AxiosResponse,
  type InternalAxiosRequestConfig,
} from 'axios'

// 표준 응답 포맷 타입 (Global Response Wrapper) — 백엔드 TransformInterceptor와 동일 구조
export interface StandardResponse<T = unknown> {
  success: boolean
  data?: T
  error?: {
    code: string
    message: string
  }
}

// 에러 코드 사전 — CLAUDE.md / 백엔드 HttpExceptionFilter 와 1:1 매핑
const ErrorCodeLexicon: Record<string, string> = {
  SYS_001: '일시적인 시스템 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.',
  AUTH_001: '로그인이 필요한 서비스입니다. 로그인 후 이용해 주세요.',
  AUTH_002: '안전을 위해 로그아웃 되었습니다. 다시 로그인해 주세요.',
  AUTH_003: '해당 메뉴나 기능에 접근할 수 있는 권한이 없습니다.',
  VAL_001: '입력하신 정보를 다시 확인해 주세요. (필수값 누락 또는 형식 오류)',
  RES_001: '요청하신 정보나 페이지를 찾을 수 없습니다.',
  BIZ_001: '요청하신 작업을 완료하지 못했습니다. 다시 시도해 주세요.',
}

// 사용자 노출용 알림 — Toast 라이브러리 도입 시 이 함수만 교체하면 됨
// SSG 프리렌더(서버) 단계에서는 window 가 없으므로 클라이언트에서만 동작
const showErrorUI = (message: string) => {
  if (import.meta.client) {
    window.alert(message)
  }
}

// 싱글턴 인스턴스 — 최초 호출 시 1회만 생성
let apiInstance: AxiosInstance | null = null

const createApi = (): AxiosInstance => {
  // 런타임 환경변수에서 API 베이스 URL 주입 (NUXT_PUBLIC_API_BASE_URL)
  const config = useRuntimeConfig()

  const api = axios.create({
    baseURL: (config.public.apiBaseUrl as string) || '/api',
    timeout: 10000,
    // HttpOnly/Secure 쿠키 인증 시 자격 증명을 함께 전송
    withCredentials: true,
  })

  // 요청 인터셉터 — CSRF, 추가 헤더 등 필요 시 확장
  api.interceptors.request.use(
    (cfg: InternalAxiosRequestConfig) => cfg,
    (error: unknown) => Promise.reject(error),
  )

  // 응답 인터셉터 — Global Response Wrapper 언래핑 + 에러코드 → 메시지 매핑
  api.interceptors.response.use(
    (response: AxiosResponse<StandardResponse>) => {
      const payload = response.data

      if (payload && typeof payload.success === 'boolean') {
        if (payload.success) {
          // 성공 시 data 만 언래핑하여 반환
          return payload.data as never
        }
        // HTTP 200 이지만 비즈니스 로직상 실패인 경우
        const errCode = payload.error?.code || 'BIZ_001'
        showErrorUI(ErrorCodeLexicon[errCode] || ErrorCodeLexicon.SYS_001)
        return Promise.reject(payload.error)
      }
      return payload as never
    },
    (error) => {
      let errCode = 'SYS_001'

      if (error?.response) {
        const status: number = error.response.status
        const payload = error.response.data as StandardResponse | undefined

        if (payload?.error?.code) {
          errCode = payload.error.code
        } else if (status === 401) errCode = 'AUTH_001'
        else if (status === 403) errCode = 'AUTH_003'
        else if (status === 400 || status === 422) errCode = 'VAL_001'
        else if (status === 404) errCode = 'RES_001'
      }

      showErrorUI(ErrorCodeLexicon[errCode] || ErrorCodeLexicon.SYS_001)
      return Promise.reject(error)
    },
  )

  return api
}

/**
 * useApi — 컴포넌트/스토어에서 axios 인스턴스를 가져올 때 사용하는 composable
 * 직접 import 대신 useApi() 사용을 권장 (테스트 시 모킹 용이)
 */
export function useApi(): AxiosInstance {
  if (!apiInstance) {
    apiInstance = createApi()
  }
  return apiInstance
}
