<script>
  import { createEventDispatcher } from 'svelte';
  import { escapeMarkdownLabel } from '../../markdown/markdown';
  import { expandKeyboardVariants } from '../../util/keyboardLayout';

  export let visible = false;

  const dispatch = createEventDispatcher();

  // Filter types
  const types = [
    { id: 'case', label: 'Дело' },
    { id: 'note', label: 'Заметка' },
    { id: 'file', label: 'Файл' },
    { id: 'secret', label: 'Секрет' },
  ];

  let activeType = 'note';
  let query = '';
  let results = [];
  let selectedIndex = 0;
  let loading = false;
  let error = '';
  let inputRef;

  // Map node types from backend to our filter types
  function nodeTypeToFilter(type) {
    if (type === 'note') return 'note';
    if (type === 'file') return 'file';
    if (type === 'secret') return 'secret';
    return 'case';
  }

  async function search() {
    if (!query.trim() || query.trim().length < 2) {
      results = [];
      return;
    }
    loading = true;
    error = '';
    try {
      // Expand query with keyboard layout variants for tolerant search
      const variants = expandKeyboardVariants(query.trim());
      // Deduplicate: skip variants identical to the original query's lowercase
      const seen = new Set();
      const queries = [];
      for (const v of variants) {
        if (!seen.has(v)) {
          seen.add(v);
          queries.push(v);
        }
      }
      // Execute all variant queries in parallel
      const allResults = await Promise.all(
        queries.map(q => window['go']['main']['App']['SearchNodes'](q).catch(() => []))
      );
      // Merge and deduplicate by node ID
      const merged = new Map();
      for (const arr of allResults) {
        for (const n of (arr || [])) {
          if (!merged.has(n.id)) {
            merged.set(n.id, n);
          }
        }
      }
      // Filter by active type
      results = Array.from(merged.values()).filter(n => nodeTypeToFilter(n.type) === activeType);
      selectedIndex = 0;
    } catch (e) {
      error = String(e);
      results = [];
    } finally {
      loading = false;
    }
  }

  function handleInput() {
    clearTimeout(searchTimer);
    searchTimer = setTimeout(search, 250);
  }

  function handleKeydown(e) {
    if (e.key === 'ArrowDown') {
      e.preventDefault();
      selectedIndex = Math.min(selectedIndex + 1, results.length - 1);
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      selectedIndex = Math.max(selectedIndex - 1, 0);
    } else if (e.key === 'Enter') {
      e.preventDefault();
      if (results[selectedIndex]) {
        selectResult(results[selectedIndex]);
      }
    } else if (e.key === 'Escape') {
      dispatch('close');
    }
  }

  function selectResult(item) {
    const label = escapeMarkdownLabel(item.title || item.id);
    const md = `[${label}](verstak://${nodeTypeToFilter(item.type)}/${item.id})`;
    dispatch('insert', { markdown: md });
  }

  function handleTypeChange(typeId) {
    activeType = typeId;
    query = '';
    results = [];
    error = '';
    if (inputRef) inputRef.focus();
  }

  let searchTimer;
  $: if (visible && inputRef) {
    setTimeout(() => inputRef.focus(), 50);
  }
</script>

{#if visible}
<div class="picker-modal-overlay" on:click|self={() => dispatch('close')} on:keydown={(e) => e.key === 'Escape' && dispatch('close')}>
  <div class="picker-modal" role="dialog" aria-modal="true" aria-label="Выбрать объект">
    <div class="picker-header">
      <input
        type="text"
        bind:this={inputRef}
        bind:value={query}
        on:input={handleInput}
        on:keydown={handleKeydown}
        placeholder="Поиск..."
        class="picker-search-input"
        autocomplete="off"
      />
    </div>

    <div class="picker-types" role="tablist" aria-label="Тип объекта">
      {#each types as type}
        <button
          type="button"
          class="picker-type-btn"
          class:active={activeType === type.id}
          class:disabled={type.id === 'secret'}
          role="tab"
          aria-selected={activeType === type.id}
          on:click={() => type.id !== 'secret' && handleTypeChange(type.id)}
          disabled={type.id === 'secret'}
        >
          {type.label}
        </button>
      {/each}
    </div>

    {#if activeType === 'secret'}
      <div class="picker-secret-placeholder">
        <p>🔒 Сейф доступов ещё не реализован</p>
      </div>
    {:else}
      <div class="picker-results" role="listbox">
        {#if loading}
          <div class="picker-loading">Загрузка...</div>
        {:else if error}
          <div class="picker-error">{error}</div>
        {:else if query.trim().length >= 2 && results.length === 0}
          <div class="picker-empty">Ничего не найдено</div>
        {:else}
          {#each results as item, i}
            <button
              type="button"
              class="picker-result"
              class:selected={i === selectedIndex}
              role="option"
              aria-selected={i === selectedIndex}
              on:click={() => selectResult(item)}
            >
              <span class="picker-result-title">{item.title}</span>
              {#if item.path}
                <span class="picker-result-path">{item.path}</span>
              {/if}
            </button>
          {/each}
        {/if}
      </div>
    {/if}

    <div class="picker-footer">
      <button type="button" class="btn" on:click={() => dispatch('close')}>Отмена</button>
    </div>
  </div>
</div>
{/if}

<style>
  .picker-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 200;
  }

  .picker-modal {
    background: #1a1a28;
    border: 1px solid #2a2a3c;
    border-radius: 12px;
    width: 480px;
    max-width: 90vw;
    max-height: 70vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .picker-header {
    padding: 12px 16px;
    border-bottom: 1px solid #2a2a3c;
  }

  .picker-search-input {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #2a2a3c;
    border-radius: 6px;
    background: #13131f;
    color: #e4e4ef;
    font-size: 14px;
    font-family: inherit;
    outline: none;
    box-sizing: border-box;
  }

  .picker-search-input:focus {
    border-color: #818cf8;
  }

  .picker-types {
    display: flex;
    gap: 4px;
    padding: 8px 16px;
    border-bottom: 1px solid #2a2a3c;
  }

  .picker-type-btn {
    padding: 4px 12px;
    border: 1px solid #2a2a3c;
    border-radius: 4px;
    background: #13131f;
    color: #999;
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
  }

  .picker-type-btn:hover:not(:disabled) {
    background: #1e1e38;
    color: #ccc;
  }

  .picker-type-btn.active {
    background: #2a2a4a;
    color: #e4e4ef;
    border-color: #6366f1;
  }

  .picker-type-btn.disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }

  .picker-secret-placeholder {
    padding: 32px;
    text-align: center;
    color: #666;
    font-size: 14px;
  }

  .picker-results {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    max-height: 300px;
  }

  .picker-loading,
  .picker-error,
  .picker-empty {
    padding: 24px;
    text-align: center;
    color: #666;
    font-size: 13px;
  }

  .picker-error {
    color: #ff8888;
  }

  .picker-result {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    padding: 10px 16px;
    border: none;
    border-bottom: 1px solid #1e1e30;
    background: transparent;
    color: #e4e4ef;
    font-size: 13px;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
  }

  .picker-result:last-child {
    border-bottom: none;
  }

  .picker-result:hover,
  .picker-result.selected {
    background: #1e1e38;
  }

  .picker-result-title {
    font-weight: 500;
  }

  .picker-result-path {
    font-size: 11px;
    color: #666;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .picker-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid #2a2a3c;
  }
</style>
