<script setup lang="ts">
import { PlusIcon, XIcon } from '@modrinth/assets'
import {
	Accordion,
	ButtonStyled,
	injectNotificationManager,
	NewModal,
	ServerNotice,
	TagItem,
} from '@modrinth/ui'
import type { ServerNotice as ServerNoticeType } from '@modrinth/utils'
import { ref } from 'vue'

import { useServersFetch } from '~/composables/servers/servers-fetch.ts'

const { addNotification } = injectNotificationManager()

const modal = ref<InstanceType<typeof NewModal>>()

const emit = defineEmits<{
	(e: 'close'): void
}>()

const notice = ref<ServerNoticeType>()

const assigned = ref<ServerNoticeType['assigned']>([])

const assignedServers = computed(() => assigned.value.filter((n) => n.kind === 'server') ?? [])
const assignedNodes = computed(() => assigned.value.filter((n) => n.kind === 'node') ?? [])

const inputField = ref('')

async function refresh() {
	await useServersFetch('notices').then((res) => {
		const notices = res as ServerNoticeType[]
		assigned.value = notices.find((n) => n.id === notice.value?.id)?.assigned ?? []
	})
}

async function assign(server: boolean = true) {
	const input = inputField.value.trim()

	if (input !== '' && notice.value) {
		await useServersFetch(
			`notices/${notice.value.id}/assign?${server ? 'server' : 'node'}=${input}`,
			{
				method: 'PUT',
			},
		).catch((err) => {
			addNotification({
				title: 'Error assigning notice',
				text: err,
				type: 'error',
			})
		})
	} else {
		addNotification({
			title: 'Error assigning notice',
			text: 'No server or node specified',
			type: 'error',
		})
	}
	await refresh()
}

async function unassignDetect() {
	const input = inputField.value.trim()

	const server = assignedServers.value.some((assigned) => assigned.id === input)
	const node = assignedNodes.value.some((assigned) => assigned.id === input)

	if (!server && !node) {
		addNotification({
			title: 'Error unassigning notice',
			text: 'ID is not an assigned server or node',
			type: 'error',
		})
		return
	}

	await unassign(input, server)
}

async function unassign(id: string, server: boolean = true) {
	if (notice.value) {
		await useServersFetch(
			`notices/${notice.value.id}/unassign?${server ? 'server' : 'node'}=${id}`,
			{
				method: 'PUT',
			},
		).catch((err) => {
			addNotification({
				title: 'Error unassigning notice',
				text: err,
				type: 'error',
			})
		})
	}
	await refresh()
}

function show(currentNotice: ServerNoticeType) {
	notice.value = currentNotice
	assigned.value = currentNotice?.assigned ?? []
	modal.value?.show()
}

function hide() {
	modal.value?.hide()
}

defineExpose({ show, hide })
</script>
<template>
	<NewModal ref="modal" :on-hide="() => emit('close')">
		<template #title>
			<span class="text-lg font-extrabold text-contrast">
				Editing assignments of notice #{{ notice?.id }}
			</span>
		</template>
		<div class="flex flex-col gap-4">
			<ServerNotice
				v-if="notice"
				:level="notice.level"
				:message="notice.message"
				:dismissable="notice.dismissable"
				:title="notice.title"
				preview
			/>
			<div class="flex flex-col gap-2">
				<label for="server-assign-field" class="flex flex-col gap-1">
					<span class="text-lg font-semibold text-contrast"> Assigned servers </span>
				</label>
				<Accordion
					v-if="assignedServers.length > 0"
					class="mb-2"
					open-by-default
					button-class="text-primary m-0 p-0 border-none bg-transparent active:scale-95"
				>
					<template #title> {{ assignedServers.length }} servers </template>
					<div class="mt-2 flex flex-wrap gap-2">
						<TagItem
							v-for="server in assignedServers"
							:key="`server-${server.id}`"
							:action="() => unassign(server.id, true)"
						>
							<XIcon />
							{{ server.id }}
						</TagItem>
					</div>
				</Accordion>
				<span v-else class="mb-2"> No servers assigned yet </span>

				<div class="flex flex-col gap-2">
					<label for="server-assign-field" class="flex flex-col gap-1">
						<span class="text-lg font-semibold text-contrast"> Assigned nodes </span>
					</label>
					<Accordion
						v-if="assignedNodes.length > 0"
						class="mb-2"
						open-by-default
						button-class="text-primary m-0 p-0 border-none bg-transparent active:scale-95"
					>
						<template #title> {{ assignedNodes.length }} nodes </template>
						<div class="mt-2 flex flex-wrap gap-2">
							<TagItem
								v-for="node in assignedNodes"
								:key="`node-${node.id}`"
								:action="
									() => {
										unassign(node.id, false)
									}
								"
							>
								<XIcon />
								{{ node.id }}
							</TagItem>
						</div>
					</Accordion>
					<span v-else class="mb-2"> No nodes assigned yet </span>
				</div>
				<div class="flex w-[45rem] items-center gap-2">
					<input
						id="server-assign-field"
						v-model="inputField"
						class="w-full"
						type="text"
						autocomplete="off"
					/>
					<ButtonStyled color="green" color-fill="text">
						<button class="shrink-0" @click="() => assign(true)">
							<PlusIcon />
							Add server
						</button>
					</ButtonStyled>
					<ButtonStyled color="blue" color-fill="text">
						<button class="shrink-0" @click="() => assign(false)">
							<PlusIcon />
							Add node
						</button>
					</ButtonStyled>
					<ButtonStyled color="red" color-fill="text">
						<button class="shrink-0" @click="() => unassignDetect()">
							<XIcon />
							Remove
						</button>
					</ButtonStyled>
				</div>
			</div>
		</div>
	</NewModal>
</template>
