import axios from 'axios'

// Get runtime config for Nuxt 3
const config = useRuntimeConfig()

// Keycloak configuration for token refresh
const KEYCLOAK_TOKEN_URL = (config.public.keycloakUrl as string) || 'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/token'
const KEYCLOAK_CLIENT_ID = (config.public.keycloakClientId as string) || 'akbar-test'
const KEYCLOAK_CLIENT_SECRET = (config.public.keycloakClientSecret as string) || 'FDyv3UYMgJOYPnvzXVVv6diRtcgEevKg'

// Create axios instance for local API
const api = axios.create({
  baseURL: config.public.baseUrl,
  timeout: 10000,
})

// Create axios instance for GoMed API
const apiGomed = axios.create({
  baseURL: config.public.baseUrlGomed,
  timeout: 10000,
})

// Flag to prevent multiple simultaneous refresh attempts
let isRefreshing = false
let failedQueue: any[] = []

const processQueue = (error: any, token: string | null = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error)
    } else {
      prom.resolve(token)
    }
  })
  
  failedQueue = []
}

const refreshAccessToken = async (): Promise<string | null> => {
  try {
    const refreshToken = localStorage.getItem('refreshToken')
    if (!refreshToken) {
      throw new Error('No refresh token available')
    }

    const params = new URLSearchParams()
    params.append('grant_type', 'refresh_token')
    params.append('client_id', KEYCLOAK_CLIENT_ID)
    params.append('client_secret', KEYCLOAK_CLIENT_SECRET)
    params.append('refresh_token', refreshToken)

    const response = await fetch(KEYCLOAK_TOKEN_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: params.toString()
    })

    if (!response.ok) {
      throw new Error('Token refresh failed')
    }

    const data = await response.json()
    
    // Update tokens in localStorage
    if (data.access_token) {
      localStorage.setItem('accessToken', data.access_token)
    }
    if (data.id_token) {
      localStorage.setItem('idToken', data.id_token)
    }
    if (data.refresh_token) {
      localStorage.setItem('refreshToken', data.refresh_token)
    }

    console.log('✅ Token refreshed successfully')
    return data.id_token || data.access_token
  } catch (error) {
    console.error('❌ Token refresh failed:', error)
    return null
  }
}

// Shared request interceptor
const requestInterceptor = (config: any) => {
  // Only access localStorage on client-side (avoid SSR errors)
  if (process.client) {
    const idToken = localStorage.getItem('idToken')
    
    if (idToken) {
      config.headers.Authorization = `Bearer ${idToken}`
    }
  }

  return config
}

// Shared response interceptor
const responseInterceptor = (response: any) => response
const responseErrorInterceptor = async (error: any) => {
  const originalRequest = error.config
  
  // centralized error
  console.error('API Error:', error.response)
  
  // Handle token expiration on client-side
  if (process.client && error.response) {
    const { status } = error.response
    
    // Check if response is 401 (token expired or unauthorized)
    if (status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        // If already refreshing, queue this request
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject })
        })
          .then(token => {
            originalRequest.headers['Authorization'] = 'Bearer ' + token
            return axios(originalRequest)
          })
          .catch(err => {
            return Promise.reject(err)
          })
      }

      originalRequest._retry = true
      isRefreshing = true

      // Try to refresh the token
      const newToken = await refreshAccessToken()
      
      if (newToken) {
        // Token refresh successful, retry original request
        isRefreshing = false
        processQueue(null, newToken)
        
        originalRequest.headers['Authorization'] = 'Bearer ' + newToken
        return axios(originalRequest)
      } else {
        // Token refresh failed (refresh token expired or error), logout user
        isRefreshing = false
        processQueue(new Error('Token refresh failed'), null)
        
        // Clear expired tokens
        localStorage.removeItem('idToken')
        localStorage.removeItem('accessToken')
        localStorage.removeItem('refreshToken')
        
        // Call logout endpoint to clear session
        fetch('/api/auth/logout', { method: 'POST' })
          .catch(err => console.error('Logout failed:', err))
        
        // Redirect to login with error message
        const errorMessage = encodeURIComponent('Token is expired')
        window.location.href = `/auth/login?error=${errorMessage}`
        
        return Promise.reject(error)
      }
    }
  }
  
  return Promise.reject(error)
}

// Apply interceptors to both instances
api.interceptors.request.use(requestInterceptor)
api.interceptors.response.use(responseInterceptor, responseErrorInterceptor)

apiGomed.interceptors.request.use(requestInterceptor)
apiGomed.interceptors.response.use(responseInterceptor, responseErrorInterceptor)

export default api
export { apiGomed }