import axios, {AxiosResponse, Method} from "axios";
import {configs, isDesktop} from "@/lib/configs";

type ContentType = 'application/json' | 'multipart/form-data';

interface ApiRequestConfig {
    method: Method;
    url: string;
    auth: string;
    lang?: string;
    params?: Record<string, unknown>;
    data?: unknown;
    contentType?: ContentType;
}

function handleApiError(error: unknown): never {
    if (axios.isAxiosError(error)) {
        const serverMessage: string = error.response?.data?.message || error.response?.data || error.message;
        throw new Error(serverMessage);
    } else if (error instanceof Error) {
        throw new Error(error.message);
    }
    throw new Error('An unexpected error occurred');
}

async function apiRequest<T>(config: ApiRequestConfig): Promise<T> {
    try {
        const headers: Record<string, string> = {
            'Authorization': `Bearer ${config.auth}`
        };

        if (config.contentType) {
            headers['Content-Type'] = config.contentType;
        }

        const response: AxiosResponse<T> = await axios({
            method: config.method,
            headers,
            params: {
                lang: config.lang ?? 'fr',
                plateforme: isDesktop ? 'desktop' : 'web',
                ...config.params
            },
            url: configs.apiUrl + config.url,
            data: config.data
        });

        return response.data;
    } catch (error: unknown) {
        handleApiError(error);
    }
}

export async function apiGet<T>(url: string, auth: string, lang: string = "fr", params: Record<string, unknown> = {}): Promise<T> {
    return apiRequest<T>({method: 'GET', url, auth, lang, params});
}

export async function apiPost<T>(url: string, data: object, auth: string, lang: string = "fr"): Promise<T> {
    return apiRequest<T>({method: 'POST', url, auth, lang, data, contentType: 'application/json'});
}

export async function apiPut<T>(url: string, data: object, auth: string, lang: string = "fr"): Promise<T> {
    return apiRequest<T>({method: 'PUT', url, auth, lang, data, contentType: 'application/json'});
}

export async function apiPatch<T>(url: string, data: object, auth: string, lang: string = "fr"): Promise<T> {
    return apiRequest<T>({method: 'PATCH', url, auth, lang, data, contentType: 'application/json'});
}

export async function apiDelete<T>(url: string, data: object, auth: string, lang: string = "fr"): Promise<T> {
    return apiRequest<T>({method: 'DELETE', url, auth, lang, data, contentType: 'application/json'});
}

export async function apiPostPublic<T>(url: string, data: object, lang: string = "fr"): Promise<T> {
    try {
        const response: AxiosResponse<T> = await axios({
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            params: {lang, plateforme: isDesktop ? 'desktop' : 'web'},
            url: configs.apiUrl + url,
            data
        });
        return response.data;
    } catch (error: unknown) {
        handleApiError(error);
    }
}

export async function apiUpload<T>(url: string, file: File, auth: string, lang: string = "fr"): Promise<T> {
    const formData: FormData = new FormData();
    formData.append('file', file);

    return apiRequest<T>({method: 'POST', url, auth, lang, data: formData, contentType: 'multipart/form-data'});
}
