<script lang="ts">
	import { ATTR_IN, ATTR_LABEL } from '@upnd/upend/constants';
	import api from '$lib/api';
	import { i18n } from '../i18n';
	import Spinner from './utils/Spinner.svelte';
	import UpObject from './display/UpObject.svelte';

	const groups = (async () => {
		const data = await api.query(`(matches ? "${ATTR_IN}" ?)`);

		const addresses = data.entries
			.filter((e) => e.value.t === 'Address')
			.map((e) => e.value.c) as string[];

		const sortedAddresses = [...new Set(addresses)]
			.map((address) => ({
				address,
				count: addresses.filter((a) => a === address).length
			}))
			.sort((a, b) => b.count - a.count);

		const addressesString = sortedAddresses.map(({ address }) => `@${address}`).join(' ');
		const labels = (
			await api.query(`(matches (in ${addressesString}) "${ATTR_LABEL}" ? )`)
		).entries.filter((e) => e.value.t === 'String');

		const display = sortedAddresses.map(({ address, count }) => ({
			address,
			labels: labels
				.filter((e) => e.entity === address)
				.map((e) => e.value.c)
				.sort() as string[],
			count
		}));

		display
			.sort((a, b) => (a.labels[0] || '').localeCompare(b.labels[0] || ''))
			.sort((a, b) => b.count - a.count);

		const labelsToGroups = new Map<string, string[]>();
		labels.forEach((e) => {
			const groups = labelsToGroups.get(e.value.c as string) || [];
			if (!groups.includes(e.entity)) {
				groups.push(e.entity);
			}
			labelsToGroups.set(e.value.c as string, groups);
		});
		const duplicates = [...labelsToGroups.entries()]
			.filter(([_, groups]) => groups.length > 1)
			.map(([label, groups]) => ({ label, groups }));

		return {
			groups: display,
			total: sortedAddresses.length,
			duplicateGroups: duplicates
		};
	})();

	let clientWidth: number;
</script>

<div class="groups" bind:clientWidth class:small={clientWidth < 600}>
	<h2>{$i18n.t('Groups')}</h2>
	<div class="main">
		{#await groups}
			<Spinner centered />
		{:then data}
			<ul>
				{#each data.groups as group}
					<li class="group" data-address={group.address}>
						<UpObject link address={group.address} labels={group.labels} />
						<div class="count">{group.count}</div>
					</li>
				{:else}
					<li>No groups?</li>
				{/each}
				{#if data.groups && data.total > data.groups.length}
					<li>+ {data.total - data.groups.length}...</li>
				{/if}
			</ul>
			{#if data.duplicateGroups.length > 0}
				<h3>{$i18n.t('Duplicate groups')}</h3>
				<ul class="duplicate">
					{#each data.duplicateGroups as { label, groups }}
						<li class="duplicate-group">
							<div class="label">{label}</div>
							<ul>
								{#each groups as group}
									<li>
										<UpObject link address={group} backpath={2} />
									</li>
								{/each}
							</ul>
						</li>
					{/each}
				</ul>
			{/if}
		{/await}
	</div>
</div>

<style lang="scss">
	@use '../styles/colors';

	.groups {
		text-align: center;

		flex-grow: 1;
		height: 0;

		display: flex;
		flex-direction: column;
	}

	.main {
		overflow: hidden auto;
	}

	h2 {
		margin-top: -0.66em;
	}

	ul {
		list-style: none;
		padding: 0;
		margin: 0;

		display: flex;
		flex-wrap: wrap;
		gap: 0.5em;
		justify-content: space-between;
	}

	.group {
		display: flex;
	}

	.count {
		display: inline-block;
		font-size: 0.66em;
		margin-left: 0.25em;
	}

	.label {
		font-weight: bold;
		margin-bottom: 1em;
	}

	.duplicate {
		display: flex;
		gap: 1rem;
		flex-wrap: wrap;
		justify-content: center;
	}

	.duplicate-group {
		flex-basis: 49%;
		border-radius: 4px;
		border: 1px solid var(--foreground);
		padding: 0.5rem;
		overflow-x: auto;
		max-width: 100%;

		ul {
			flex-direction: column;
		}
	}

	.groups.small {
		ul {
			flex-direction: column;
		}
	}
</style>
