import { useAuthStore } from '@/stores/auth'

const API_BASE = '/api'

interface RequestOptions {
  method?: string
  body?: unknown
  headers?: Record<string, string>
}

let isRefreshing = false
let refreshPromise: Promise<void> | null = null

/**
 * Composable for making authenticated API requests.
 * Automatically attaches JWT token and handles token refresh.
 */
export function useApi() {
  const auth = useAuthStore()

  async function attemptRefresh(): Promise<void> {
    if (isRefreshing && refreshPromise) {
      return refreshPromise
    }

    isRefreshing = true
    refreshPromise = (async () => {
      try {
        const response = await fetch(`${API_BASE}/auth/refresh`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ refresh_token: auth.refreshToken }),
        })

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

        const data = await response.json()
        auth.setAuth({
          access_token: data.access_token,
          refresh_token: data.refresh_token,
          user: auth.user!,
        })
      } catch {
        auth.logout()
        window.location.href = '/login'
        throw new Error('Session expired')
      } finally {
        isRefreshing = false
        refreshPromise = null
      }
    })()

    return refreshPromise
  }

  async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {
    const headers: Record<string, string> = {
      'Content-Type': 'application/json',
      ...options.headers,
    }

    if (auth.accessToken) {
      headers['Authorization'] = `Bearer ${auth.accessToken}`
    }

    let response = await fetch(`${API_BASE}${path}`, {
      method: options.method || 'GET',
      headers,
      body: options.body ? JSON.stringify(options.body) : undefined,
    })

    if (response.status === 401 && auth.refreshToken) {
      await attemptRefresh()

      // Retry original request with new token
      headers['Authorization'] = `Bearer ${auth.accessToken}`
      response = await fetch(`${API_BASE}${path}`, {
        method: options.method || 'GET',
        headers,
        body: options.body ? JSON.stringify(options.body) : undefined,
      })
    }

    if (!response.ok) {
      const error = await response.json().catch(() => ({ message: 'Request failed' }))
      throw new Error(error.message || `HTTP ${response.status}`)
    }

    return response.json()
  }

  function get<T>(path: string) {
    return request<T>(path)
  }

  function post<T>(path: string, body?: unknown) {
    return request<T>(path, { method: 'POST', body })
  }

  function put<T>(path: string, body?: unknown) {
    return request<T>(path, { method: 'PUT', body })
  }

  function del<T>(path: string) {
    return request<T>(path, { method: 'DELETE' })
  }

  /**
   * Upload a FormData payload (multipart/form-data).
   * Does NOT set Content-Type — browser must set it with the correct boundary.
   */
  async function upload<T>(path: string, formData: FormData): Promise<T> {
    const headers: Record<string, string> = {}

    if (auth.accessToken) {
      headers['Authorization'] = `Bearer ${auth.accessToken}`
    }

    let response = await fetch(`${API_BASE}${path}`, {
      method: 'POST',
      headers,
      body: formData,
    })

    if (response.status === 401 && auth.refreshToken) {
      await attemptRefresh()
      headers['Authorization'] = `Bearer ${auth.accessToken}`
      response = await fetch(`${API_BASE}${path}`, {
        method: 'POST',
        headers,
        body: formData,
      })
    }

    if (!response.ok) {
      const error = await response.json().catch(() => ({ message: 'Upload failed' }))
      throw new Error(error.message || `HTTP ${response.status}`)
    }

    return response.json()
  }

  return { request, get, post, put, del, upload }
}
