import { toast } from 'vue3-toastify'

import { normalizeApiError } from './api-error'

export function humanizeError(error) {
  let currentError
  if (error?.response || error?.request) {
    currentError = normalizeApiError(error)
  } else if (error instanceof Error) {
    currentError = error
    currentError.errorType = 'logic'
  } else {
    currentError = new Error('something unexpected', { cause: error })
    currentError.errorType = 'unknown'
  }

  if (!currentError.statusCode) {
    currentError.statusCode = 500
  }
  return currentError
}

export function handleApiError(error_) {
  const data = error_?.response?.data
  const status = error_?.response?.status

  if (error_?.code === 'ECONNABORTED') {
    toast.error(
      'زمان بارگذاری فایل به پایان رسید. لطفاً اتصال اینترنت را بررسی و دوباره تلاش کنید.'
    )
    return
  }

  if (status === 413) {
    toast.error('حجم فایل از حداکثر مجاز بیشتر است.')
    return
  }

  if (status === 422 && data?.errors) {
    Object.values(data.errors).forEach((messages) => {
      const list = Array.isArray(messages) ? messages : [messages]
      list.forEach((msg) => toast.error(msg))
    })
    return
  }

  if (data?.message) {
    toast.error(data.message)
    return
  }

  toast.error('عملیات با خطا مواجه شد')
}

// Walks a typed validation error response (e.g. Laravel 422 with `errors`
// keyed by field) and pushes the first message for each field into the
// caller's form via setFieldError. Falls back to a toast when the error
// isn't a field-level validation failure.
export function applyValidationErrors(error, setFieldError) {
  const data = error?.response?.data
  const fieldErrors = data?.errors

  if (fieldErrors && typeof fieldErrors === 'object' && !Array.isArray(fieldErrors)) {
    Object.entries(fieldErrors).forEach(([field, messages]) => {
      const message = Array.isArray(messages) ? messages[0] : messages
      if (typeof setFieldError === 'function' && field && message) {
        setFieldError(field, message)
      }
    })
    return
  }

  toast.error(data?.message || 'عملیات با خطا مواجه شد')
}

export function handleUnknownError(options) {
  const { showToast } = { showToast: true, ...options }
  if (showToast) {
    toast.error('مشکلی در انجام عملیات رخ داد. لطفا دوباره امتحان کنید.')
  }
}

export function handleError(error, options) {
  try {
    const { showToast } = { showToast: true, ...options }
    const currentError = humanizeError(error)
    if (currentError.errorType === 'logic') {
      if (showToast) toast.error(currentError.message)
      return
    }
    if (showToast && currentError.errorType === 'api') {
      handleApiError(error)
      return
    }
    if (showToast) handleUnknownError(options)
  } catch {
    handleUnknownError(options)
  }
}
