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

interface RequestOptions {
  uri: string
  params?: Record<string, string>
  body?: any
  auth?: boolean
  method?: string
}

export class NetworkService {
  private API_URL = import.meta.env.VITE_API_URL
  private auth = useAuthStore()

  async post(options: RequestOptions) {
    options.method = 'POST'
    return await this.request(options)
  }

  async get(options: RequestOptions) {
    options.method = 'GET'
    return await this.request(options)
  }

  async patch(options: RequestOptions) {
    options.method = 'PATCH'
    return await this.request(options)
  }

  async delete(options: RequestOptions) {
    options.method = 'DELETE'
    return await this.request(options)
  }

  async request(options: RequestOptions) {
    const { uri, params } = options
    if (!uri) {
      throw new Error('URL is required')
    }
    const fetchOptions = this.getFetchOptions(options)
    const urlParams = this.getURLParams(params)
    const res = await fetch(`${this.API_URL}${uri}${urlParams}`, fetchOptions)

    if (!res.ok) {
      throw new Error('Network response was not ok')
    }
    const text = await res.text()

    if (text === '') {
      return
    } else {
      return JSON.parse(text)
    }
  }

  getURLParams(params: any) {
    if (!params) {
      return ''
    }
    const urlParams = new URLSearchParams()
    Object.keys(params).forEach((key) => urlParams.append(key, params[key]))
    return `?${urlParams.toString()}`
  }

  getFetchOptions(opts: RequestOptions): any {
    const { body, auth, method = 'GET' } = opts
    const options: any = {
      method,
      headers: this.getHeaders({ auth })
    }
    if (!['GET', 'HEAD'].includes(method) && body) {
      options.body = typeof body === 'string' ? body : JSON.stringify(body)
    }

    return options
  }

  getHeaders({ auth = true }): any {
    const { jwt } = storeToRefs(this.auth)
    const headers: any = {
      'Content-Type': 'application/json'
    }
    if (auth) {
      headers.Authorization = jwt
    }
    return headers
  }
}
