<script lang="ts">
	import Star from "$icon/star";
	import { getAuth } from "$lib/auth.svelte";
	import { createStar, deleteStar } from "$lib/api/graph";
	import Button from "$lib/components/ui/Button.svelte";
	import ButtonGroup from "$lib/components/ui/ButtonGroup.svelte";
	import { getProfileCounts } from "$lib/components/profile/counts.svelte";
	import { createOptimisticRelation, createOptimisticCount } from "$lib/optimistic.svelte";

	interface Props {
		repoDid: string;
		repoOwnerHandle: string;
		repoName: string;
		initialCount?: number;
		initialRkey?: string | null;
	}

	let { repoDid, repoOwnerHandle, repoName, initialCount, initialRkey }: Props = $props();

	const auth = getAuth();
	const profileCounts = getProfileCounts();
	const signedIn = $derived(Boolean(auth.currentDid));
	const relation = createOptimisticRelation({
		key: () => `${auth.currentDid ?? ""}:${repoDid}`,
		loadedRkey: () => initialRkey
	});
	const starCount = createOptimisticCount({
		key: () => repoDid,
		loaded: () => initialCount
	});

	let busy = $state(false);
	const starred = $derived(relation.active);
	const failed = $derived(relation.failed || starCount.failed);

	const toggle = async () => {
		const agent = auth.agent;
		if (!agent || busy || !relation.known || !repoDid) return;
		busy = true;
		relation.resetFailure();
		starCount.resetFailure();
		try {
			if (relation.active && relation.rkey) {
				await deleteStar(agent, relation.rkey);
				relation.deleted();
				starCount.adjust(-1);
				profileCounts?.adjust(agent.sub, "stars", -1);
			} else {
				const rkey = await createStar(agent, repoDid);
				relation.created(rkey);
				starCount.adjust(1);
				profileCounts?.adjust(agent.sub, "stars", 1);
			}
		} catch {
			relation.fail();
			starCount.fail();
		} finally {
			busy = false;
		}
	};
</script>

{#if signedIn && repoDid}
	<div class="flex flex-col items-end">
		<ButtonGroup>
			<Button
				variant="default"
				size="sm"
				class="flex-1"
				loading={busy}
				disabled={!relation.known}
				onclick={toggle}
			>
				<Star
					class={`size-4 shrink-0 ${starred ? "[&_path]:fill-[currentColor]" : ""}`}
					aria-hidden="true"
				/>
				<span>{starred ? "Unstar" : "Star"}</span>
			</Button>
			<Button
				href={`/${repoOwnerHandle}/${repoName}/stars`}
				variant="default"
				size="sm"
				title="Starred by"
			>
				{starCount.value}
			</Button>
		</ButtonGroup>
		{#if failed}
			<p class="mt-1 text-paragraph-small text-foreground-danger">
				Something went wrong. Try again.
			</p>
		{/if}
	</div>
{/if}
