import config from 'config';

async function get(endpoint, query = {}) {
	const curatedQuery = Object.entries(query).reduce((acc, [key, value]) => (value ? { ...acc, [key]: value } : acc), {}); // remove empty values
	const q = new URLSearchParams(curatedQuery).toString();

	const res = await fetch(`${config.api.url}${endpoint}?${q}`, {
		method: 'GET',
		mode: 'cors',
		credentials: 'same-origin',
	});

	const contentTypes = res.headers.get('content-type');

	if (res.ok && contentTypes?.includes('application/json')) {
		return res.json();
	}

	if (res.ok) {
		return null;
	}

	const errorMsg = await res.text();

	throw new Error(errorMsg);
}

async function post(endpoint, data, method = 'POST') {
	const res = await fetch(`${config.api.url}${endpoint}`, {
		method,
		mode: 'cors',
		headers: {
			'Content-Type': 'application/json',
		},
		credentials: 'same-origin',
		body: JSON.stringify(data),
	});

	const contentTypes = res.headers.get('content-type');

	if (res.ok && contentTypes?.includes('application/json')) {
		return res.json();
	}

	if (res.ok) {
		return null;
	}

	const errorMsg = await res.text();

	throw new Error(errorMsg);
}

async function patch(endpoint, data) {
	return post(endpoint, data, 'PATCH');
}

async function put(endpoint, data) {
	return post(endpoint, data, 'PUT');
}

async function del(endpoint) {
	const res = await fetch(`${config.api.url}${endpoint}`, {
		method: 'DELETE',
		mode: 'cors',
		credentials: 'same-origin',
	});

	const contentTypes = res.headers.get('content-type');

	if (res.ok && contentTypes?.includes('application/json')) {
		return res.json();
	}

	if (res.ok) {
		return true;
	}

	const errorMsg = await res.text();

	throw new Error(errorMsg);
}

async function graphql(query, variables = null) {
	const res = await fetch('/graphql', {
		method: 'POST',
		mode: 'cors',
		headers: {
			'Content-Type': 'application/json',
		},
		credentials: 'same-origin',
		body: JSON.stringify({
			query,
			variables,
		}),
	});

	if (res.ok) {
		const { data } = await res.json();

		return data;
	}

	const errorMsg = await res.text();

	throw new Error(errorMsg);
}

export {
	get,
	post,
	del,
	graphql,
	patch,
	put,
};