import { useToast } from './useToast'
import { humanizeError, extractApiErrorMessage } from '~/shared/utils/errorMessages'

export interface ApiResponse<T = any> {
  success: boolean
  data?: T
  error?: string
  status?: number
}

interface ApiCallOptions extends RequestInit {
  headers?: Record<string, string>
}

export function useApi() {
  const { showError } = useToast()
  const { public: publicConfig } = useRuntimeConfig()
  const API_BASE_URL = (publicConfig.apiBaseUrl as string) || 'http://localhost:3000'
  const parsedApiTimeout = Number(publicConfig.apiTimeout ?? 30000)
  const API_TIMEOUT = Number.isNaN(parsedApiTimeout) ? 30000 : parsedApiTimeout

  const apiCall = async <T = any>(endpoint: string, options: ApiCallOptions = {}): Promise<ApiResponse<T>> => {
    const url = `${API_BASE_URL}${endpoint}`
    const isFormData = options.body instanceof FormData
    const defaultOptions: ApiCallOptions = {
      credentials: 'include',
      headers: isFormData ? {} : { 'Content-Type': 'application/json' },
    }

    // Ajouter un timeout à la requête
    const controller = new AbortController()
    const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT)

    try {
      const response = await fetch(url, {
        ...defaultOptions,
        ...options,
        headers: {
          ...defaultOptions.headers,
          ...options.headers,
        },
        signal: controller.signal,
      })

      clearTimeout(timeoutId)

      if (response.ok) {
        let data: T | null = null
        if (response.status !== 204) {
          const contentType = response.headers.get('content-type') || ''
          if (contentType.includes('application/json') || contentType.includes('application/ld+json') || contentType.includes('+json')) {
            const text = await response.text()
            data = text ? JSON.parse(text) : null
          } else {
            const text = await response.text()
            data = (text || null) as T | null
          }
        }
        return { success: true, data: data as T }
      } else {
        const contentType = response.headers.get('content-type') || ''
        let errorData: Record<string, unknown> = {}
        if (contentType.includes('json')) {
          errorData = await response.json().catch(() => ({}))
        } else {
          const text = await response.text().catch(() => '')
          errorData = text ? { message: text } : {}
        }
        const rawMessage = response.status === 403
          ? 'Permissions insuffisantes pour cette action.'
          : extractApiErrorMessage(errorData) || `Erreur ${response.status}: ${response.statusText}`
        const errorMessage = humanizeError(rawMessage)
        showError(errorMessage)
        return { success: false, error: errorMessage, status: response.status }
      }
    } catch (error) {
      clearTimeout(timeoutId)
      const err = error as Error & { name?: string }
      const errorMessage = err.name === 'AbortError'
        ? 'La requête a pris trop de temps. Veuillez réessayer.'
        : 'Impossible de contacter le serveur. Vérifiez votre connexion.'
      showError(errorMessage)
      return { success: false, error: errorMessage }
    }
  }

  const get = async <T = any>(endpoint: string): Promise<ApiResponse<T>> => {
    return apiCall<T>(endpoint, { method: 'GET' })
  }

  const post = async <T = any>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> => {
    return apiCall<T>(endpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/ld+json',
      },
      body: data !== undefined ? JSON.stringify(data) : undefined,
    })
  }

  const patch = async <T = any>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> => {
    return apiCall<T>(endpoint, {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/merge-patch+json',
      },
      body: data !== undefined ? JSON.stringify(data) : undefined,
    })
  }

  const put = async <T = any>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> => {
    return apiCall<T>(endpoint, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/ld+json',
      },
      body: data !== undefined ? JSON.stringify(data) : undefined,
    })
  }

  const postFormData = async <T = any>(endpoint: string, formData: FormData): Promise<ApiResponse<T>> => {
    return apiCall<T>(endpoint, {
      method: 'POST',
      body: formData,
    })
  }

  const del = async <T = any>(endpoint: string): Promise<ApiResponse<T>> => {
    return apiCall<T>(endpoint, { method: 'DELETE' })
  }

  return {
    apiCall,
    get,
    post,
    postFormData,
    patch,
    put,
    delete: del,
  }
}
