import { BASE_API_URL } from '@/constants';

export type NetworkResponse<T> =
	| {
			result: true;
			data: T;
	  }
	| {
			result: false;
			error: string | null;
	  };

export type NetworkPromise<T> = Promise<NetworkResponse<T>>;

export namespace API {
	export const url = BASE_API_URL;

	let token: string | null = localStorage.getItem('token') || null;

	export const getToken = () => token;

	export const setToken = (token: string | null) => {
		token = token;
		if (token) {
			localStorage.setItem('token', token);
		} else {
			localStorage.removeItem('token');
		}
	};

	const cleanParams = (params: Record<string, any>) => {
		return Object.fromEntries(Object.entries(params).filter(([_, v]) => v !== undefined));
	};

	const get: (path: string, qs?: Record<string, any>) => Promise<any> = async (path, qs) => {
		const searchParams = new URLSearchParams(cleanParams(qs || {})).toString();
		const response = await fetch(`${url}${path}${searchParams ? `?${searchParams}` : ''}`, {
			credentials: 'include',
			headers: {
				'Content-Type': 'application/json',
				'Authorization': `Bearer ${token}`,
			},
		});
		return await response.json();
	};

	const post: (path: string, data: any, qs?: Record<string, any>) => Promise<any> = async (path, data, qs) => {
		const searchParams = new URLSearchParams(cleanParams(qs || {})).toString();
		const response = await fetch(`${url}${path}${searchParams ? `?${searchParams}` : ''}`, {
			method: 'POST',
			body: data instanceof FormData ? data : JSON.stringify(data),
			headers:
				data instanceof FormData
					? {
							Authorization: `Bearer ${token}`,
						}
					: {
							'Content-Type': 'application/json',
							'Authorization': `Bearer ${token}`,
						},
			credentials: 'include',
		});
		return await response.json();
	};

	const delete_: (path: string, qs?: Record<string, any>) => Promise<any> = async (path, qs) => {
		const searchParams = new URLSearchParams(cleanParams(qs || {})).toString();
		const response = await fetch(`${url}${path}${searchParams ? `?${searchParams}` : ''}`, {
			method: 'DELETE',
			headers: {
				Authorization: `Bearer ${token}`,
			},
			credentials: 'include',
		});
		return await response.json();
	};

	export namespace Telegram {
		export const getLoginStateId = async (
			key: string,
			back: string,
			platform?: 'desktop' | 'mobile',
			fail?: string,
			origin?: string,
		): NetworkPromise<{ stateId: string; bot: string }> => {
			return await get(`/auth/telegram/login-state`, { key, back, fail, origin, platform });
		};
	}

	export namespace Auth {
		export const me = async (): NetworkPromise<{
			id: string;
			username: string | null;
			throughCredential: { provider: string; id: string };
		} | null> => {
			return await get('/auth/me');
		};
	}

	export namespace Projects {
		export const list = async (): NetworkPromise<any[]> => {
			return await get('/projects');
		};

		export const create = async (data: any): NetworkPromise<any & { privateKey: string }> => {
			return await post('/projects', data);
		};

		export const update = async (id: string, data: any): NetworkPromise<any> => {
			return await post(`/projects/${id}`, data);
		};

		export const archive = async (id: string): NetworkPromise<void> => {
			return await delete_(`/projects/${id}`);
		};
	}
}
