<script lang="ts">
  import { Combobox, useCombobox, useListCollection } from '@ark-ui/svelte/combobox'
  import { Portal } from '@ark-ui/svelte/portal'
  import styles from 'styles/combobox.module.css'
  import { useAsync } from './use-async.svelte.ts'

  interface Character {
    name: string
    height: string
    mass: string
    created: string
    edited: string
    url: string
  }

  const { collection, set } = useListCollection<Character>({
    initialItems: [],
    itemToString: (item) => item.name,
    itemToValue: (item) => item.name,
  })

  let inputValue = $state('')

  const combobox = useCombobox(() => ({
    collection: collection(),
    defaultValue: ['C-3PO'],
    placeholder: 'Example: Dexter',
    inputValue,
    onInputValueChange: (e) => {
      inputValue = e.inputValue
    },
  }))

  const fetchData = $derived(async (signal: AbortSignal | null) => {
    const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue}`, { signal })
    const data = await response.json()
    set(data.results)
  })

  const _state = useAsync(() => fetchData)

  $effect(() => {
    void inputValue
    void _state.load()
  })

  let hydrated = false
  $effect.pre(() => {
    if (combobox().value.length && combobox().collection.size && !hydrated) {
      combobox().syncSelectedItems()
      hydrated = true
    }
  })
</script>

<Combobox.RootProvider class={styles.Root} value={combobox}>
  <Combobox.Label class={styles.Label}>Search Star Wars Characters</Combobox.Label>
  <Combobox.Control class={styles.Control}>
    <Combobox.Input class={styles.Input} placeholder="e.g. Luke" />
  </Combobox.Control>

  <Portal>
    <Combobox.Positioner>
      <Combobox.Content class={styles.Content}>
        {#if _state.loading()}
          <span style="padding: 0.5rem">Loading...</span>
        {:else if _state.error()}
          <span style="padding: 0.5rem">{_state.error()?.message}</span>
        {:else}
          {#each collection().items as item (item.name)}
            <Combobox.Item class={styles.Item} {item}>
              <Combobox.ItemText class={styles.ItemText}>
                {item.name} - {item.height}cm / {item.mass}kg
              </Combobox.ItemText>
              <Combobox.ItemIndicator class={styles.ItemIndicator}>✓</Combobox.ItemIndicator>
            </Combobox.Item>
          {/each}
        {/if}
      </Combobox.Content>
    </Combobox.Positioner>
  </Portal>
</Combobox.RootProvider>
