export const TOKEN_KEY = "catalogger-token";

export type HttpMethod = "GET" | "POST" | "PATCH" | "PUT" | "DELETE";

export async function fastFetch(
	method: HttpMethod,
	path: string,
	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	body: any = null,
): Promise<void> {
	const token = localStorage.getItem(TOKEN_KEY);
	const headers = {
		...(body != null
			? { "Content-Type": "application/json; charset=utf-8" }
			: {}),
		...(token ? { Authorization: token } : {}),
	};

	const reqBody = body ? JSON.stringify(body) : undefined;

	console.debug("Sending", method, "request to", path, "with body", reqBody);

	const resp = await fetch(path, {
		method,
		body: body ? JSON.stringify(body) : undefined,
		headers,
	});
	if (resp.status < 200 || resp.status > 299)
		throw (await resp.json()) as ApiError;
}

export default async function apiFetch<T>(
	method: HttpMethod,
	path: string,
	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	body: any = null,
): Promise<T> {
	const token = localStorage.getItem(TOKEN_KEY);
	const headers = {
		...(body != null
			? { "Content-Type": "application/json; charset=utf-8" }
			: {}),
		...(token ? { Authorization: token } : {}),
	};

	const reqBody = body ? JSON.stringify(body) : undefined;

	console.debug("Sending", method, "request to", path, "with body", reqBody);

	const resp = await fetch(path, {
		method,
		body: body ? JSON.stringify(body) : undefined,
		headers,
	});
	if (resp.status < 200 || resp.status > 299)
		throw (await resp.json()) as ApiError;

	return (await resp.json()) as T;
}

export type User = {
	id: string;
	tag: string;
	avatar_url: string;
};

export type PartialGuild = {
	id: string;
	name: string;
	icon_url: string;
	bot_in_guild: boolean;
};

export type FullGuild = {
	id: string;
	name: string;
	icon_url: string;
	categories: GuildCategory[];
	channels_without_category: GuildChannel[];
	roles: GuildRole[];
	ignored_channels: string[];
	ignored_roles: string[];
	messages: MessageConfig;
	channels: ChannelConfig;
	key_roles: string[];
};

export type GuildCategory = {
	id: string;
	name: string;
	channels: GuildChannel[];
};

export type GuildChannel = {
	id: string;
	name: string;
	can_log_to: boolean;
	can_redirect_from: boolean;
};

export type GuildRole = {
	id: string;
	name: string;
	position: string;
	colour: string;
};

export type CurrentUser = {
	user: User;
	guilds: PartialGuild[];
};

export type AuthCallback = CurrentUser & { token: string };

export type ApiError = {
	error_code: string;
	message: string;
};

export type MessageConfig = {
	ignored_channels: string[];
	ignored_users: string[];
	ignored_roles: string[];
	ignored_users_per_channel: Record<string, string[]>;
};

export type ChannelConfig = {
	redirects: Record<string, string>;
	guild_update: string;
	guild_emojis_update: string;
	guild_role_create: string;
	guild_role_update: string;
	guild_role_delete: string;
	channel_create: string;
	channel_update: string;
	channel_delete: string;
	guild_member_add: string;
	guild_member_update: string;
	guild_key_role_update: string;
	guild_member_nick_update: string;
	guild_member_avatar_update: string;
	guild_member_timeout: string;
	guild_member_remove: string;
	guild_member_kick: string;
	guild_ban_add: string;
	guild_ban_remove: string;
	invite_create: string;
	invite_delete: string;
	message_update: string;
	message_delete: string;
	message_delete_bulk: string;
};

export type Meta = {
	guilds: number;
	invite_url: string;
	news: NewsMessage[];
};

export type NewsMessage = {
	author: string;
	content: string;
	attachment_urls: string[];
	posted_at: string;
	edited_at: string | null;
};
