<script lang="ts">
	import MenuItem from '$lib/components/meltComponents/MenuItem.svelte'
	import DropdownSubmenuItem from '$lib/components/DropdownSubmenuItem.svelte'
	import { Check, Loader2 } from 'lucide-svelte'
	import { twMerge } from 'tailwind-merge'
	import type { MenubarMenuElements, createDropdownMenu } from '@melt-ui/svelte'
	import type { Item } from '$lib/utils'
	import { Tooltip } from './meltComponents'

	interface Props {
		aiId?: string
		items?: Item[] | (() => Item[]) | (() => Promise<Item[]>)
		meltItem: MenubarMenuElements['item']
		builders?: ReturnType<typeof createDropdownMenu>['builders']
	}

	let { aiId, items = [], meltItem, builders }: Props = $props()

	let computedItems: Item[] | undefined = $state(undefined)
	async function computeItems() {
		if (typeof items === 'function') {
			computedItems = ((await items()) ?? []).filter((item) => !item.hide)
		} else {
			computedItems = items.filter((item) => !item.hide)
		}
	}

	computeItems()
</script>

{#snippet menuItem(item: Item)}
	<MenuItem
		onClick={(e) => item?.action?.(e)}
		href={item?.href}
		target={item?.hrefTarget}
		disabled={item?.disabled}
		class={twMerge(
			'px-4 py-2 text-primary font-normal hover:bg-surface-hover cursor-pointer text-xs transition-colors w-full',
			'data-[highlighted]:bg-surface-hover',
			'flex flex-row gap-2 items-center rounded-sm',
			// `pointer-events-none` lets a hover fall through the natively-disabled button to the
			// wrapper below, so a disabled item's `title` tooltip can still explain *why* it's disabled.
			item?.disabled && 'text-disabled cursor-not-allowed pointer-events-none',
			item?.type === 'delete' &&
				!item?.disabled &&
				'text-red-600 dark:text-red-400 data-[highlighted]:bg-red-500/10 dark:data-[highlighted]:bg-red-900/80 dark:data-[highlighted]:text-red-300 '
		)}
		item={meltItem}
		aiId={`${aiId ? `${aiId}-${item.displayName}` : undefined}`}
		aiDescription={item.displayName}
	>
		{#if item.icon}
			<item.icon size={14} color={item.iconColor} class="shrink-0" />
		{/if}
		<p title={item.displayName} class="truncate grow min-w-0 whitespace-nowrap text-left">
			{item.displayName}
		</p>
		{@render item.extra?.()}
		{#if item.shortcut || item.selected}
			<!-- Single trailing group so `shortcut` and `selected` can coexist:
			     two `ml-auto` siblings would collapse to one right-aligned item. -->
			<div class="ml-auto flex shrink-0 items-center gap-2">
				{#if item.shortcut}
					<span class="pl-4 text-2xs text-secondary">{item.shortcut}</span>
				{/if}
				{#if item.selected}
					<Check size={14} class="text-primary" />
				{/if}
			</div>
		{/if}
		{#if item.tooltip && !item.disabled}
			<!-- Enabled items get the rich ⓘ tooltip. Disabled items can't (a native disabled button
			     swallows subtree pointer events), so they fall back to the wrapper `title` below. -->
			<Tooltip>
				{#snippet text()}
					{item.tooltip}
				{/snippet}
			</Tooltip>
		{/if}
	</MenuItem>
{/snippet}

{#if computedItems}
	<div class="flex flex-col">
		{#each computedItems ?? [] as item}
			{#if item.separatorTop}
				<div class="my-1 border-t border-border-light"></div>
			{/if}
			{#if item.submenuItems && builders}
				<DropdownSubmenuItem {item} {builders} {meltItem} />
			{:else if item.disabled && item.tooltip}
				<!-- Wrapper carries the native `title`; the disabled button's `pointer-events-none`
				     lets the hover reach it so the user learns why the item is disabled. -->
				<div title={item.tooltip} class="w-full">
					{@render menuItem(item)}
				</div>
			{:else}
				{@render menuItem(item)}
			{/if}
		{/each}
	</div>
{:else}
	<Loader2 class="animate-spin mx-auto p-4" size={24} />
{/if}
