<script lang="ts">
	import { fastFetch, type ApiError, type GuildRole } from "$lib/api";
	import { addToast } from "$lib/toast";
	import { makeFullOptions } from "$lib/util";
	import { Button, ListGroup, ListGroupItem } from "@sveltestrap/sveltestrap";
	import ChannelSelect from "../ChannelSelect.svelte";
	import type { PageData } from "./$types";
	import RemovableListItem from "$lib/components/RemovableListItem.svelte";
	import RoleSelect from "../RoleSelect.svelte";
	import RoleListItem from "$lib/components/RoleListItem.svelte";

	export let data: PageData;

	$: ignoredChannels = data.guild.ignored_channels;
	$: channelOptions = makeFullOptions(data.guild, ignoredChannels);

	$: ignoredRoles = data.guild.ignored_roles;
	$: roleOptions = data.guild.roles
		.filter((r) => ignoredRoles.indexOf(r.id) === -1)
		.map((r) => ({ label: r.name, value: r.id }));

	$: allChannels = [
		...data.guild.channels_without_category.map((c) => ({
			id: c.id,
			name: `#${c.name}`,
		})),
		...data.guild.categories.map((cat) => ({ id: cat.id, name: cat.name })),
		...data.guild.categories.flatMap((cat) =>
			cat.channels.map((c) => ({ id: c.id, name: `#${c.name}` })),
		),
	];

	const channelName = (id: string) =>
		allChannels.find((c) => c.id === id)?.name || `(unknown channel ${id})`;

	const roleName = (id: string) =>
		data.guild.roles.find((r) => r.id === id)?.name || `(unknown role ${id})`;

	const roleObject = (id: string): GuildRole | string =>
		data.guild.roles.find((r) => r.id === id) || id;

	let channelToIgnore: string | null = null;
	let roleToIgnore: string | null = null;

	const addChannelIgnore = async () => {
		if (!channelToIgnore) return;

		try {
			await fastFetch(
				"PUT",
				`/api/guilds/${data.guild.id}/ignored-entities/channels/${channelToIgnore}`,
			);
			ignoredChannels.push(channelToIgnore);
			ignoredChannels = ignoredChannels;
			addToast({
				header: "Ignored channel",
				body: `Added ${channelName(channelToIgnore)} to the list of ignored channels.`,
			});
			channelToIgnore = null;
		} catch (e) {
			addToast({
				header: "Error ignoring channel",
				body:
					(e as ApiError).message || "Unknown error. Please try again later.",
			});
		}
	};

	const removeChannelIgnore = async (id: string) => {
		try {
			await fastFetch(
				"DELETE",
				`/api/guilds/${data.guild.id}/ignored-entities/channels/${id}`,
			);
			const idx = ignoredChannels.indexOf(id);
			if (idx > -1) ignoredChannels.splice(idx, 1);
			ignoredChannels = ignoredChannels;
			addToast({
				header: "Stopped ignoring channel",
				body: `Removed ${channelName(id)} from the list of ignored channels.`,
			});
		} catch (e) {
			addToast({
				header: "Error removing channel",
				body:
					(e as ApiError).message || "Unknown error. Please try again later.",
			});
		}
	};

	const addRoleIgnore = async () => {
		if (!roleToIgnore) return;

		try {
			await fastFetch(
				"PUT",
				`/api/guilds/${data.guild.id}/ignored-entities/roles/${roleToIgnore}`,
			);
			ignoredRoles.push(roleToIgnore);
			ignoredRoles = ignoredRoles;
			addToast({
				header: "Ignored role",
				body: `Added ${roleName(roleToIgnore)} to the list of ignored roles.`,
			});
			roleToIgnore = null;
		} catch (e) {
			addToast({
				header: "Error ignoring role",
				body:
					(e as ApiError).message || "Unknown error. Please try again later.",
			});
		}
	};

	const removeRoleIgnore = async (id: string) => {
		try {
			await fastFetch(
				"DELETE",
				`/api/guilds/${data.guild.id}/ignored-entities/roles/${id}`,
			);
			const idx = ignoredRoles.indexOf(id);
			if (idx > -1) ignoredRoles.splice(idx, 1);
			ignoredRoles = ignoredRoles;
			addToast({
				header: "Stopped ignoring role",
				body: `Removed ${roleName(id)} from the list of ignored roles.`,
			});
		} catch (e) {
			addToast({
				header: "Error removing role",
				body:
					(e as ApiError).message || "Unknown error. Please try again later.",
			});
		}
	};
</script>

<h3>Ignored channels and roles</h3>

<p>
	Events related to these channels and roles (such as them being edited, them
	being deleted, and them being added to users) will not be logged.
</p>

<p>
	If you want to ignore <em>messages</em> from channels and roles, go to
	<a href="/dash/{data.guild.id}/ignored-messages">ignored messages</a> instead.
</p>

<h4 class="mt-4">Channels</h4>

<div>
	<ChannelSelect bind:value={channelToIgnore} options={channelOptions} />
</div>

<div class="mt-2 mb-3 d-grid d-md-block">
	<Button
		color="primary"
		on:click={() => addChannelIgnore()}
		disabled={!channelToIgnore}
	>
		Ignore this channel
	</Button>
</div>

<ListGroup>
	{#each ignoredChannels as id}
		<RemovableListItem
			on:click={() => removeChannelIgnore(id)}
			buttonText="Stop ignoring"
		>
			{channelName(id)}
		</RemovableListItem>
	{:else}
		<ListGroupItem>No channels are being ignored right now.</ListGroupItem>
	{/each}
</ListGroup>

<h4 class="mt-4">Roles</h4>

<div>
	<RoleSelect bind:value={roleToIgnore} options={roleOptions} />
</div>

<div class="mt-2 mb-3 d-grid d-md-block">
	<Button
		color="primary"
		on:click={() => addRoleIgnore()}
		disabled={!roleToIgnore}
	>
		Ignore this role
	</Button>
</div>

<ListGroup>
	{#each ignoredRoles as id}
		<RoleListItem
			role={roleObject(id)}
			on:click={() => removeRoleIgnore(id)}
			buttonText="Stop ignoring"
		/>
	{:else}
		<ListGroupItem>No roles are being ignored right now.</ListGroupItem>
	{/each}
</ListGroup>
