<svelte:options runes={true} />

<script lang="ts">
	import { onMount } from 'svelte';
	import sanitizeHtml from 'sanitize-html';
	import { Skeleton } from '$lib/components/ui/skeleton/index.js';
	import { DoubleArrowUp } from 'radix-icons-svelte';

	let {
		account,
		maxToots,
		accountId,
		excludeReplies
	}: { account: string; maxToots?: number; accountId?: string; excludeReplies: boolean } = $props();

	let toots: Toot[] = $state([]);
	let loading = $state(false);

	onMount(() => {
		loading = true;
		loadToots(account, accountId, maxToots, excludeReplies);
	});

	interface Toot {
		created_at: string;
		in_reply_to_id: string | null;
		content: string;
		url: string;
		account: {
			username: string;
			display_name: string;
			avatar: string;
			url: string;
		};
		reblog?: Toot;
		media_attachments: {
			type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio';
			url: string;
			preview_url: string;
			description: string;
			blurhash: string;
		}[];
	}

	export async function getToots(
		userURL: string,
		limit: number,
		excludeReplies: boolean,
		accountId?: string
	): Promise<Toot[]> {
		const url = new URL(userURL);

		// Either use the account id specified or look it up based on the username
		// in the link.
		const userId: string =
			accountId ??
			(await (async () => {
				// Extract username from URL.
				const parts = /@(\w+)$/.exec(url.pathname);
				if (!parts) {
					throw 'not a Mastodon user URL';
				}
				const username = parts[1];

				// Look up user ID from username.
				const lookupURL = Object.assign(new URL(url), {
					pathname: '/api/v1/accounts/lookup',
					search: `?acct=${username}`
				});
				return (await (await fetch(lookupURL)).json())['id'];
			})());

		// Fetch toots.
		const tootURL = Object.assign(new URL(url), {
			pathname: `/api/v1/accounts/${userId}/statuses`,
			search: `?limit=${limit ?? 5}&exclude_replies=${!!excludeReplies}`
		});

		return await (await fetch(tootURL)).json();
	}

	function loadToots() {
		getToots(account, maxToots ?? 5, excludeReplies === true, accountId).then((data) => {
			toots = data;
			loading = false;
		});
	}
</script>

{#snippet avatar(toot)}
	<a class="flex flex-row gap-2" href={toot.account.url}>
		<img
			class="rounded-md"
			width="48px"
			height="48px"
			src={toot.account.avatar}
			alt="{toot.account.username} avatar"
		/>
		<div class="flex flex-col items-start">
			<span class="h-6 font-bold hover:underline">{toot.account.display_name}</span>
			<span class="h-4 text-sm text-muted">@{toot.account.username}</span>
		</div>
	</a>
{/snippet}

{#snippet body(toot)}
	<div>
		<div class="[&>p>span>a]:hover:underline">
			{@html sanitizeHtml(toot.content)}
		</div>
		{#each toot.media_attachments.filter((att) => att.type === 'image') as image}
			<a
				class="block aspect-16/9 w-full overflow-hidden rounded-md"
				href={image.url}
				target="_blank"
				rel="noopener noreferrer"
			>
				<img class="h-full w-full object-cover" src={image.preview_url} alt={image.description} />
			</a>
		{/each}
	</div>
{/snippet}

<ol class="w-full">
	{#if loading}
		{#each Array(maxToots ?? 5) as placeholder}
			<li class="flex flex-col gap-3 px-4 py-3">
				<div class="flex flex-row justify-between">
					<div class="flex flex-row gap-2">
						<Skeleton class="h-12 w-12 rounded-md" />
						<div class="flex flex-col items-start gap-1">
							<Skeleton class="h-6 w-24"></Skeleton>
							<Skeleton class="h-4 w-20"></Skeleton>
						</div>
					</div>
					<Skeleton class="h-10 w-16" />
				</div>
				<Skeleton class="h-36 w-full"></Skeleton>
			</li>
		{/each}
	{:else}
		{#each toots as toot}
			<li class="flex flex-col gap-3 px-4 py-3">
				{#if toot.reblog}
					<div class="flex flex-row justify-between">
						<div class="flex flex-col gap-1">
							<a class="flex flex-row items-center gap-1" href={toot.account.url}>
								<DoubleArrowUp />
								<img
									class="rounded-md"
									width="23px"
									height="23px"
									src={toot.account.avatar}
									alt="{toot.account.username} avatar"
								/>
								<span class="h-6 font-bold hover:underline">{toot.account.display_name}</span>
							</a>
							{@render avatar(toot.reblog)}
						</div>
						<a
							class="flex flex-col items-center text-sm text-muted hover:underline"
							href={toot.url}
						>
							<time datetime={toot.created_at}>
								{new Date(toot.created_at).toLocaleDateString()}
							</time>
							<time datetime={toot.created_at}>
								{new Date(toot.created_at).toLocaleTimeString()}
							</time>
						</a>
					</div>
					{@render body(toot.reblog)}
				{:else}
					<div class="flex flex-row justify-between">
						{@render avatar(toot)}
						<a
							class="flex flex-col items-center text-sm text-muted hover:underline"
							href={toot.url}
						>
							<time datetime={toot.created_at}>
								{new Date(toot.created_at).toLocaleDateString()}
							</time>
							<time datetime={toot.created_at}>
								{new Date(toot.created_at).toLocaleTimeString()}
							</time>
						</a>
					</div>
					{@render body(toot)}
				{/if}
			</li>
		{/each}
	{/if}
</ol>