import axios from 'axios'
import type { AxiosInstance, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'

const request: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE || '/api',
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json',
  },
  // Session tokens live in HttpOnly cookies — send them along.
  withCredentials: true,
})

// Response interceptor
request.interceptors.response.use(
  (response: AxiosResponse) => {
    // Backend wraps everything in { data, success } — unwrap to data
    const body = response.data
    if (body && typeof body === 'object' && 'success' in body && 'data' in body) {
      return body.data
    }
    return body
  },
  async (error: AxiosError) => {
    // Access token expired: try the refresh cookie once, then retry the
    // original request. A second 401 (refresh failed) logs the user out.
    const config = error.config as (InternalAxiosRequestConfig & { _retried?: boolean }) | undefined
    if (
      error.response?.status === 401 &&
      config &&
      !config._retried &&
      !config.url?.includes('/auth/login') &&
      !config.url?.includes('/auth/refresh')
    ) {
      config._retried = true
      try {
        await axios.post(
          `${import.meta.env.VITE_API_BASE || '/api'}/auth/refresh`,
          {},
          { withCredentials: true },
        )
        return request.request(config)
      } catch {
        // fall through to the 401 handling below
      }
    }

    if (error.response) {
      const { status, data } = error.response

      switch (status) {
        case 401:
          ElMessage.error('Unauthorized, please login')
          router.push('/login')
          break
        case 403:
          ElMessage.error('Forbidden')
          break
        case 404:
          ElMessage.error('Resource not found')
          break
        case 500:
          ElMessage.error('Server error')
          break
        default:
          const errorMessage = (data as any)?.message || 'Request failed'
          ElMessage.error(errorMessage)
      }
    } else if (error.request) {
      ElMessage.error('Network error')
    } else {
      ElMessage.error('Request failed')
    }

    return Promise.reject(error)
  }
)

export default request
