/**
 * A basic api request service
 *
 * It will send basic http requests and returns raw results
 */
import {AssociativeArray} from "~/types/data";
import {HTTP_METHOD} from "~/types/enum/data";
import {$Fetch, FetchOptions} from "ohmyfetch";

class ApiRequestService {
    // TODO: fusionner les paramètres `query` et `params` des méthodes, puisque l'un est un alias de l'autre
    //       dans ohmyfetch : https://github.com/unjs/ofetch#%EF%B8%8F-adding-query-search-params
    private readonly fetch: $Fetch

    public constructor(
        fetch: $Fetch
    ) {
        this.fetch = fetch
    }

    /**
     * Send a GET request
     *
     * @param url
     * @param query
     */
    public async get(
        url: string,
        query: AssociativeArray | null = null
    ) {
        return await this.request(HTTP_METHOD.GET, url, null, null, query)
    }

    /**
     * Send a POST request
     *
     * @param url
     * @param body
     * @param params
     * @param query
     */
    public async post(
        url: string,
        body: string | null = null,
        params: AssociativeArray | null = null,
        query: AssociativeArray | null = null
    ) {
        return await this.request(HTTP_METHOD.POST, url, body, params, query)
    }

    /**
     * Send a PUT request
     *
     * @param url
     * @param body
     * @param params
     * @param query
     */
    public async put(
        url: string,
        body: string | null = null,
        params: AssociativeArray | null = null,
        query: AssociativeArray | null = null
    ) {
        return await this.request(HTTP_METHOD.PUT, url, body, params, query)
    }

    /**
     * Send a DELETE request
     *
     * @param url
     * @param query
     */
    public async delete(
        url: string,
        query: AssociativeArray | null = null
    ) {
        return await this.request(HTTP_METHOD.DELETE, url, null, null, query)
    }

    /**
     * Send an http request
     *
     * @param method
     * @param url
     * @param body
     * @param params
     * @param query
     * @protected
     */
    protected async request(
        method: HTTP_METHOD,
        url: string,
        body: string | null = null,
        params: AssociativeArray | null = null,
        query: AssociativeArray | null = null
    ): Promise<Response> {
        const config: FetchOptions = { method }
        if (params) {
            config.params = params
        }
        if (query) {
            config.query = query
        }
        if (method === HTTP_METHOD.POST || method === HTTP_METHOD.PUT) {
            config.body = body
        }

        // @ts-ignore
        return this.fetch(url, config)
    }
}

export default ApiRequestService
