import type { Pinia } from 'pinia'
import type { XError, XErrors } from '~/types/error'

export interface XfetchResult {
  success: boolean
  status_code: number
  body: object | any
  errors?: XErrors | undefined
  error?: XError | undefined
  message?: string
}

export type XfetchMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'

export async function xfetch(
  url: string,
  method: XfetchMethod = 'GET',
  input?: object | FormData,
  headers?: any,
  _type = 'json',
): Promise<XfetchResult> {
  let success = false
  let body: object | any = {}
  let errors: XErrors = {}
  let error: XError | undefined = {
    code: '',
    message: '',
  }
  let message: string | undefined = ''

  if (!headers) {
    headers = {}
  }
  if (input && !(input instanceof FormData)) {
    headers['Content-Type'] = 'application/json'
  }

  try {
    const res = await $fetch.raw(url, {
      method,
      headers,
      body: input instanceof FormData ? input : JSON.stringify(input),
    })

    body = res._data
    success = true
    return { success, status_code: res.status, body, errors, error, message }
  } catch (fetchError: any) {
    const status = fetchError.response?.status || 500
    const resJson = fetchError.data

    if (status === 401 && import.meta.client) {
      clearStore()
    }

    if (resJson?.errors) {
      errors = resJson.errors
    } else if (resJson?.code && resJson?.message) {
      error = { code: resJson.code, message: resJson.message }
    } else if (resJson?.message) {
      message = resJson.message
    } else {
      message = fetchError.message || 'Something went wrong'
    }

    return { success, status_code: status, body, errors, error, message }
  }
}

function clearStore() {
  const { $pinia } = useNuxtApp()
  const userStore = useUserStore($pinia as Pinia)
  userStore.logout()
  navigateTo('/401')
}
