<script lang="ts">
  import {derived} from "svelte/store"
  import {sortBy} from "@welshman/lib"
  import {getListTags, getEventTagValues} from "@welshman/util"
  import type {TrustedEvent} from "@welshman/util"
  import {derivePinList, repository} from "@welshman/app"
  import {Router} from "@welshman/router"
  import {load} from "@welshman/net"
  import {deriveEventsById, deriveEventsDesc} from "@welshman/store"
  import {fly} from "@lib/transition"
  import Spinner from "@lib/components/Spinner.svelte"
  import NoteItem from "@app/components/NoteItem.svelte"

  type Props = {
    pubkey: string
    limit?: number
    onViewAll?: () => void
    editable?: boolean
  }

  const {pubkey, limit, onViewAll, editable = false}: Props = $props()

  const pinList = derivePinList(pubkey)

  const pinnedIds = derived(pinList, $pinList => getEventTagValues(getListTags($pinList)))

  const displayIds = derived(pinnedIds, $pinnedIds =>
    limit ? $pinnedIds.slice(0, limit) : $pinnedIds,
  )

  const pinnedEvents = derived(
    displayIds,
    ($displayIds, set) => {
      if ($displayIds.length === 0) {
        set([])

        return
      }

      return deriveEventsDesc(
        deriveEventsById({repository, filters: [{ids: $displayIds}]}),
      ).subscribe(events => {
        set(sortBy(event => -$displayIds.indexOf(event.id), events))
      })
    },
    [] as TrustedEvent[],
  )

  let fetching = $state(false)

  $effect(() => {
    const ids = $displayIds

    if (ids.length === 0) {
      fetching = false

      return
    }

    const missing = ids.filter(id => !repository.getEvent(id))

    if (missing.length === 0) {
      fetching = false

      return
    }

    fetching = true

    const controller = new AbortController()

    load({
      relays: Router.get().FromPubkeys([pubkey]).getUrls(),
      filters: [{ids: missing}],
      signal: controller.signal,
      onClose: () => {
        fetching = false
      },
    })

    return () => controller.abort()
  })

  const loading = $derived(
    fetching || ($displayIds.length > 0 && $pinnedEvents.length < $displayIds.length),
  )
</script>

{#if $displayIds.length > 0 || loading}
  <div class="col-4 border-t border-base-300 pt-4">
    <strong>Pinned notes</strong>
    {#if loading && $pinnedEvents.length === 0}
      <p class="center flex py-8">
        <Spinner loading />
      </p>
    {:else if $pinnedEvents.length > 0}
      <div class="col-2">
        {#each $pinnedEvents as event (event.id)}
          <div in:fly>
            <NoteItem {event} {editable} />
          </div>
        {/each}
      </div>
      {#if onViewAll && limit && $pinnedIds.length > limit}
        <button class="link link-primary row-2 text-sm" onclick={onViewAll}>
          View all pinned notes
          <span aria-hidden="true">→</span>
        </button>
      {/if}
    {/if}
  </div>
{/if}
