<script lang="ts">
  import { goto } from "$app/navigation";
  import { page } from "$app/state";
  import { searchMessages } from "$lib/api/endpoints";
  import type { SearchHit } from "$lib/api/types";
  import SearchMessageItem from "$lib/components/search/SearchMessageItem.svelte";
  import EmptyState from "$lib/components/ui/EmptyState.svelte";
  import Icon from "$lib/components/ui/Icon.svelte";
  import Spinner from "$lib/components/ui/Spinner.svelte";
  import { ui } from "$lib/stores/ui.svelte";

  const DEBOUNCE_MS = 250;

  const chatId = $derived(
    page.params.chatId ? Number(page.params.chatId) : null
  );

  let query = $state("");
  let hits = $state<SearchHit[]>([]);
  let loading = $state(false);
  let timer: ReturnType<typeof setTimeout> | null = null;
  let seq = 0;

  async function run(value: string, id: number) {
    const current = ++seq;
    loading = true;
    try {
      const result = await searchMessages(value, { chat_id: id });
      if (current === seq) {
        hits = result;
      }
    } catch {
      if (current === seq) {
        hits = [];
      }
    } finally {
      if (current === seq) {
        loading = false;
      }
    }
  }

  function onInput(event: Event) {
    query = (event.currentTarget as HTMLInputElement).value;
    const value = query.trim();
    if (timer) {
      clearTimeout(timer);
    }
    if (value.length === 0 || chatId === null) {
      seq++;
      hits = [];
      loading = false;
      return;
    }
    const id = chatId;
    loading = true;
    timer = setTimeout(() => {
      run(value, id).catch(() => undefined);
    }, DEBOUNCE_MS);
  }

  function openHit(messageId: number) {
    if (chatId !== null) {
      ui.requestJump(chatId, messageId);
      goto(`/app/${chatId}`);
    }
  }
</script>

<div class="chat-search">
  <div class="search-input">
    <Icon name="search" size="1.25rem" class="chat-search-icon" />
    <input
      type="text"
      placeholder="Поиск в чате"
      value={query}
      oninput={onInput}
    >
  </div>
  <div class="results custom-scroll">
    {#if loading && hits.length === 0}
      <div class="loading"><Spinner /></div>
    {:else if hits.length > 0}
      {#each hits as hit (`${hit.chat_id}:${hit.message_id}`)}
        <SearchMessageItem {hit} onclick={() => openHit(hit.message_id)} />
      {/each}
    {:else if query.trim()}
      <EmptyState title="Ничего не найдено" />
    {/if}
  </div>
</div>

<style lang="scss">
  .chat-search {
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  .search-input {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    gap: 0.5rem;

    height: 2.5rem;
    margin: 0.625rem;
    padding: 0 0.5rem 0 0.75rem;
    border-radius: 1.25rem;

    background-color: var(--color-background-secondary);

    &:focus-within {
      background-color: var(--color-background);
      box-shadow: inset 0 0 0 1.5px var(--color-primary);
    }
  }

  :global(.chat-search .chat-search-icon) {
    flex-shrink: 0;
    color: var(--color-icon-secondary);
  }

  input {
    flex: 1;
    min-width: 0;
    border: 0;

    font-size: 0.9375rem;
    color: var(--color-text);
    background: transparent;

    &::placeholder {
      color: var(--color-text-secondary);
    }

    &:focus {
      outline: none;
    }
  }

  .results {
    overflow-y: auto;
    flex: 1;
    padding: 0.25rem 0.4375rem;
  }

  .loading {
    display: flex;
    justify-content: center;
    padding: 2rem 0;
  }
</style>
