<script lang="ts">
	import { clone, pluralize } from '$lib/utils'
	import { Pyramid } from 'lucide-svelte'
	import { twMerge } from 'tailwind-merge'
	import { Popover } from '../meltComponents'
	import S3FilePicker from '../S3FilePicker.svelte'
	import {
		assetsEq,
		formatAssetAccessType,
		formatAssetKind,
		getAccessType,
		type Asset,
		type AssetWithAltAccessType
	} from './lib'
	import DbManagerDrawer from '../DBManagerDrawer.svelte'
	import { untrack } from 'svelte'
	import { ResourceService, WorkspaceService } from '$lib/gen'
	import { workspaceStore } from '$lib/stores'
	import Tooltip from '../meltComponents/Tooltip.svelte'
	import Tooltip2 from '../Tooltip.svelte'
	import ResourceEditorDrawer from '../ResourceEditorDrawer.svelte'
	import type { Placement } from '@floating-ui/core'
	import AssetButtons from './AssetButtons.svelte'
	import ToggleButtonGroup from '../common/toggleButton-v2/ToggleButtonGroup.svelte'
	import ToggleButton from '../common/toggleButton-v2/ToggleButton.svelte'
	import { resource } from 'runed'

	let {
		assets,
		enableChangeAnimation = true,
		size = 'xs',
		noBtnText = false,
		popoverPlacement = 'bottom-end',
		disableLiTooltip = false,
		onHoverLi,
		liSubtitle
	}: {
		assets: AssetWithAltAccessType[]
		enableChangeAnimation?: boolean
		size?: 'xs' | '3xs'
		noBtnText?: boolean
		popoverPlacement?: Placement
		disableLiTooltip?: boolean
		onHoverLi?: (asset: Asset, eventType: 'enter' | 'leave') => void
		liSubtitle?: (asset: Asset) => string
	} = $props()

	let prevAssets = $state<typeof assets>([])
	let blueBgDiv: HTMLDivElement | undefined = $state()

	let s3FilePicker: S3FilePicker | undefined = $state()
	let dbManagerDrawer: DbManagerDrawer | undefined = $state()
	let resourceEditorDrawer: ResourceEditorDrawer | undefined = $state()
	let isOpen = $state(false)
	let resourceDataCache: Record<string, string | undefined> = $state({})

	$effect(() => {
		if (!enableChangeAnimation) {
			if (blueBgDiv) {
				blueBgDiv.classList.remove('animate-fade-out')
			}
		}
	})

	let datatables = resource([], () =>
		WorkspaceService.listDataTables({ workspace: $workspaceStore ?? '' })
	)
	let ducklakes = resource([], () =>
		WorkspaceService.listDucklakes({ workspace: $workspaceStore ?? '' })
	)

	$effect(() => {
		assets
		untrack(() => {
			if (assetsEq(assets, prevAssets)) return
			prevAssets = clone(assets)

			// Replay animation
			if (blueBgDiv && enableChangeAnimation) {
				blueBgDiv.classList.add('animate-fade-out')
				blueBgDiv.style.animation = 'none'
				blueBgDiv.offsetHeight /* trigger reflow */
				blueBgDiv.style.animation = ''
			}

			for (const asset of assets) {
				if (asset.kind == 'resource') {
					let truncatedPath = asset.path.split('/').slice(0, 3).join('/')
					if (truncatedPath in resourceDataCache) continue
					resourceDataCache[truncatedPath] = undefined // avoid fetching multiple times because of async
					ResourceService.getResource({ path: truncatedPath, workspace: $workspaceStore! })
						.then((r) => (resourceDataCache[truncatedPath] = r.resource_type))
						.catch((err) => console.error("Couldn't fetch resource", truncatedPath, err))
				}
			}
		})
	})
</script>

<Popover
	floatingConfig={{ strategy: 'absolute', placement: popoverPlacement }}
	usePointerDownOutside
	closeOnOtherPopoverOpen
	bind:isOpen
	escapeBehavior="ignore"
>
	<svelte:fragment slot="trigger">
		<div
			class={twMerge(
				size === '3xs' ? 'h-[1.6rem]' : 'py-1.5',
				'text-xs flex items-center gap-1.5 px-2 rounded-md relative',
				'border',
				'bg-surface hover:bg-surface-hover active:bg-surface',
				'transition-all hover:text-primary backdrop-blur-md cursor-pointer'
			)}
		>
			<div
				bind:this={blueBgDiv}
				class="absolute pointer-events-none bg-slate-300 dark:bg-[#576278] inset-0 rounded-md opacity-0"
			></div>
			<Pyramid size={size === '3xs' ? 13 : 16} class="z-10" />
			<span
				class={twMerge('z-10 font-normal', size === '3xs' ? 'text-3xs mt-[0.08rem]' : 'text-xs')}
			>
				{noBtnText ? assets.length : pluralize(assets.length, 'asset')}
			</span>
		</div>
	</svelte:fragment>
	<svelte:fragment slot="content">
		<ul class="divide-y rounded-md">
			{#each assets as asset}
				{@const ducklakeNotFound =
					asset.kind === 'ducklake' &&
					ducklakes.current &&
					!ducklakes.current.find((name) => name === asset.path.split('/')[0])}
				{@const datatableNotFound =
					asset.kind === 'datatable' &&
					datatables.current &&
					!datatables.current.find((name) => name === asset.path.split('/')[0])}
				<li
					class="text-sm px-3 h-12 flex gap-3 items-center"
					onmouseenter={() => onHoverLi?.(asset, 'enter')}
					onmouseleave={() => onHoverLi?.(asset, 'leave')}
				>
					<Popover
						contentClasses="py-2 px-4 flex flex-col gap-2"
						disablePopup={!!asset.access_type}
					>
						<svelte:fragment slot="trigger">
							<div
								class={twMerge(
									'text-xs font-normal border text-primary w-10 p-1 text-center rounded-md',
									!asset.access_type ? 'text-orange-600 !border-orange-600' : '',
									!asset.access_type ? 'hover:bg-surface active:opacity-80' : ''
								)}
							>
								{formatAssetAccessType(getAccessType(asset))}
							</div>
						</svelte:fragment>
						<svelte:fragment slot="content">
							{#if !asset.access_type}
								<span class="text-sm text-primary leading-4">
									Could not infer automatically <br />
									<span class="text-xs">Please select manually </span>
								</span>
								<div class="flex items-center gap-2">
									<ToggleButtonGroup
										allowEmpty
										bind:selected={asset.alt_access_type}
										class="max-w-fit"
									>
										{#snippet children({ item })}
											<ToggleButton value="r" label="Read" {item} />
											<ToggleButton value="w" label="Write" {item} />
											<ToggleButton value="rw" label="Read/Write" {item} />
										{/snippet}
									</ToggleButtonGroup>

									<Tooltip2>
										This is used to determine if the asset should be displayed as an input or an
										output node in the flow editor
									</Tooltip2>
								</div>
							{/if}
						</svelte:fragment>
					</Popover>
					<div class="flex flex-col flex-1">
						<Tooltip class="select-none w-48 truncate" disablePopup={disableLiTooltip}>
							{asset.path}
							<svelte:fragment slot="text">
								{asset.path}
							</svelte:fragment>
						</Tooltip>
						<span class="text-xs text-primary select-none">
							{liSubtitle?.(asset) ??
								formatAssetKind({
									...asset,
									...(asset.kind === 'resource'
										? { metadata: { resource_type: resourceDataCache[asset.path] } }
										: {})
								})}
						</span>
					</div>

					<AssetButtons
						onClick={() => (isOpen = false)}
						{asset}
						{resourceDataCache}
						{dbManagerDrawer}
						{resourceEditorDrawer}
						{s3FilePicker}
						{ducklakeNotFound}
						{datatableNotFound}
					/>
				</li>
			{/each}
		</ul>
	</svelte:fragment>
</Popover>
<S3FilePicker bind:this={s3FilePicker} readOnlyMode />
<DbManagerDrawer bind:this={dbManagerDrawer} />
<ResourceEditorDrawer bind:this={resourceEditorDrawer} />
