<script lang="ts">
  interface ContextResult {
    value: string;
    label: string;
    type: string;
  }

  interface ContextDetail {
    id: string;
    label: string;
    type: string;
    purpose: string;
    content_preview: string;
    edit_url: string;
  }

  let {
    id = '',
    value = '',
    onChange = (_v: unknown) => {},
    required = false,
    ariaDescribedBy = undefined,
  }: {
    id?: string;
    value?: string;
    onChange?: (v: unknown) => void;
    required?: boolean;
    ariaDescribedBy?: string;
  } = $props();

  // State.
  let selectedId = $state(value || '');
  let selectedLabel = $state('');
  let searchQuery = $state('');
  let searchResults: ContextResult[] = $state([]);
  let isSearching = $state(false);
  let showDropdown = $state(false);
  let highlightIndex = $state(-1);
  let debounceTimer: ReturnType<typeof setTimeout> | undefined;

  // All items cache.
  let allItems: ContextResult[] = $state([]);
  let allItemsPromise: Promise<ContextResult[]> | null = null;

  // Add URL.
  let addUrl = $state('');

  // Preview state.
  let itemDetail: ContextDetail | null = $state(null);
  let isLoadingDetail = $state(false);

  // On mount: resolve label for a pre-selected item.
  if (selectedId) {
    loadItemDetail(selectedId);
  }

  fetchAllItems();

  async function fetchAllItems(): Promise<ContextResult[]> {
    if (allItems.length > 0) return allItems;
    if (!allItemsPromise) {
      allItemsPromise = fetch('/api/flowdrop/ai-context/autocomplete?q=')
        .then((res) => (res.ok ? res.json() : { results: [] }))
        .then((json) => {
          if (json.add_url) addUrl = json.add_url;
          return json.results ?? json;
        })
        .catch(() => [] as ContextResult[])
        .finally(() => {
          allItemsPromise = null;
        });
    }
    const data = await allItemsPromise;
    allItems = data;
    return data;
  }

  async function handleFocus() {
    if (searchQuery.trim()) {
      if (searchResults.length) showDropdown = true;
      return;
    }
    isSearching = true;
    const items = await fetchAllItems();
    searchResults = items;
    showDropdown = items.length > 0;
    isSearching = false;
  }

  async function loadItemDetail(itemId: string) {
    if (!itemId) {
      itemDetail = null;
      return;
    }

    isLoadingDetail = true;
    try {
      const res = await fetch(`/api/flowdrop/ai-context/${encodeURIComponent(itemId)}`);
      if (!res.ok) {
        itemDetail = null;
        return;
      }
      const json = await res.json();
      itemDetail = json.data ?? json;
      if (itemDetail && !selectedLabel) {
        selectedLabel = itemDetail.label;
      }
    }
    catch {
      itemDetail = null;
    }
    finally {
      isLoadingDetail = false;
    }
  }

  async function handleSearch(q: string) {
    searchQuery = q;
    highlightIndex = -1;

    if (debounceTimer) clearTimeout(debounceTimer);

    if (!q.trim()) {
      const items = await fetchAllItems();
      searchResults = items;
      showDropdown = items.length > 0;
      return;
    }

    debounceTimer = setTimeout(async () => {
      isSearching = true;
      try {
        const res = await fetch(
          `/api/flowdrop/ai-context/autocomplete?q=${encodeURIComponent(q.trim())}`,
        );
        if (!res.ok) throw new Error('Search failed');
        const json = await res.json();
        searchResults = json.results ?? json;
        showDropdown = searchResults.length > 0;
      }
      catch {
        searchResults = [];
        showDropdown = false;
      }
      finally {
        isSearching = false;
      }
    }, 250);
  }

  function selectItem(item: ContextResult) {
    selectedId = item.value;
    selectedLabel = item.label;
    searchQuery = '';
    searchResults = [];
    showDropdown = false;
    onChange(item.value);
    loadItemDetail(item.value);
  }

  function clearSelection() {
    selectedId = '';
    selectedLabel = '';
    itemDetail = null;
    onChange('');
  }

  function handleSearchKeydown(e: KeyboardEvent) {
    if (!showDropdown) return;

    if (e.key === 'ArrowDown') {
      e.preventDefault();
      highlightIndex = Math.min(highlightIndex + 1, searchResults.length - 1);
    }
    else if (e.key === 'ArrowUp') {
      e.preventDefault();
      highlightIndex = Math.max(highlightIndex - 1, 0);
    }
    else if (e.key === 'Enter' && highlightIndex >= 0) {
      e.preventDefault();
      selectItem(searchResults[highlightIndex]);
    }
    else if (e.key === 'Escape') {
      showDropdown = false;
    }
  }

  function handleClickAway(e: MouseEvent) {
    const target = e.target as HTMLElement;
    if (!target.isConnected) return;
    if (!target.closest('.fd-context-selector')) {
      showDropdown = false;
    }
  }
</script>

<svelte:window onclick={handleClickAway} />

<div class="fd-context-selector" aria-describedby={ariaDescribedBy}>
  {#if selectedId}
    <!-- Selected state -->
    <div class="fd-context-selector__selected">
      <span class="fd-context-selector__selected-label">
        {selectedLabel || selectedId}
      </span>
      <button
        type="button"
        class="fd-context-selector__clear-btn"
        onclick={clearSelection}
        aria-label="Clear selection"
      >
        &times;
      </button>
    </div>

    <!-- Preview panel -->
    {#if isLoadingDetail}
      <div class="fd-context-selector__preview fd-context-selector__preview--loading">
        <span class="fd-context-selector__spinner"></span>
        <span>Loading context item...</span>
      </div>
    {:else if itemDetail}
      <div class="fd-context-selector__preview">
        <div class="fd-context-selector__preview-header">
          <span class="fd-context-selector__preview-label">Context Item</span>
          <span class="fd-context-selector__badge">
            {itemDetail.type}
          </span>
          {#if itemDetail.edit_url}
            <a
              href={itemDetail.edit_url}
              class="fd-context-selector__edit-link"
              target="_blank"
              rel="noopener noreferrer"
            >
              Edit
            </a>
          {/if}
        </div>

        {#if itemDetail.purpose}
          <div class="fd-context-selector__preview-section">
            <div class="fd-context-selector__preview-section-title">AI uses when</div>
            <p class="fd-context-selector__preview-text">{itemDetail.purpose}</p>
          </div>
        {/if}

        {#if itemDetail.content_preview}
          <div class="fd-context-selector__preview-section">
            <div class="fd-context-selector__preview-section-title">Content preview</div>
            <p class="fd-context-selector__preview-text fd-context-selector__content-preview">
              {itemDetail.content_preview}{itemDetail.content_preview.length >= 300 ? '…' : ''}
            </p>
          </div>
        {/if}
      </div>
    {/if}
  {:else}
    <!-- Search state -->
    <div class="fd-context-selector__search-wrap">
      <input
        type="text"
        class="fd-context-selector__search"
        placeholder="Search context items..."
        value={searchQuery}
        {required}
        oninput={(e) => handleSearch((e.target as HTMLInputElement).value)}
        onkeydown={handleSearchKeydown}
        onfocus={handleFocus}
      />
      {#if isSearching}
        <span class="fd-context-selector__spinner fd-context-selector__spinner--inline"></span>
      {/if}
    </div>

    {#if showDropdown}
      <ul class="fd-context-selector__dropdown" role="listbox">
        {#each searchResults as result, i}
          <li
            class="fd-context-selector__option"
            class:fd-context-selector__option--highlighted={i === highlightIndex}
            role="option"
            tabindex="0"
            aria-selected={i === highlightIndex}
            onclick={() => selectItem(result)}
            onkeydown={(e) => { if (e.key === 'Enter') selectItem(result); }}
            onmouseenter={() => (highlightIndex = i)}
          >
            <span class="fd-context-selector__option-label">{result.label}</span>
            <span class="fd-context-selector__option-type">{result.type}</span>
          </li>
        {/each}
      </ul>
    {/if}

    {#if addUrl}
      <a
        href={addUrl}
        target="_blank"
        rel="noopener noreferrer"
        class="fd-context-selector__create-link"
      >
        + Create new context item
      </a>
    {/if}
  {/if}
</div>

<style>
  .fd-context-selector {
    font-family: inherit;
    font-size: 0.875rem;
    line-height: 1.4;
  }

  .fd-context-selector__search-wrap {
    position: relative;
  }

  .fd-context-selector__search {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid var(--fd-border-color, #d0d5dd);
    border-radius: 4px;
    background: var(--fd-bg-color, #fff);
    color: var(--fd-text-color, #344054);
    font-family: inherit;
    font-size: 0.8125rem;
    box-sizing: border-box;
  }

  .fd-context-selector__search:focus {
    outline: none;
    border-color: var(--fd-primary-color, #2563eb);
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.15);
  }

  .fd-context-selector__spinner {
    width: 14px;
    height: 14px;
    border: 2px solid var(--fd-border-color, #d0d5dd);
    border-top-color: var(--fd-primary-color, #2563eb);
    border-radius: 50%;
    animation: fd-context-spin 0.6s linear infinite;
    display: inline-block;
  }

  .fd-context-selector__spinner--inline {
    position: absolute;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    animation-name: fd-context-spin-inline;
  }

  @keyframes fd-context-spin {
    to { transform: rotate(360deg); }
  }

  @keyframes fd-context-spin-inline {
    to { transform: translateY(-50%) rotate(360deg); }
  }

  .fd-context-selector__dropdown {
    list-style: none;
    margin: 0.25rem 0 0;
    padding: 0.25rem 0;
    border: 1px solid var(--fd-border-color, #d0d5dd);
    border-radius: 4px;
    background: var(--fd-bg-color, #fff);
    max-height: 200px;
    overflow-y: auto;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  }

  .fd-context-selector__option {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.375rem 0.5rem;
    cursor: pointer;
    font-size: 0.8125rem;
  }

  .fd-context-selector__option--highlighted {
    background: var(--fd-primary-color-light, #eff6ff);
  }

  .fd-context-selector__option-label {
    color: var(--fd-text-color, #344054);
  }

  .fd-context-selector__option-type {
    font-size: 0.6875rem;
    padding: 0.125rem 0.375rem;
    border-radius: 3px;
    font-weight: 500;
    color: var(--fd-accent, #6941c6);
    background: var(--fd-accent-muted, rgba(105, 65, 198, 0.08));
  }

  .fd-context-selector__selected {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.5rem;
    border: 1px solid var(--fd-primary-color, #2563eb);
    border-radius: 4px;
    background: var(--fd-primary-color-light, #eff6ff);
  }

  .fd-context-selector__selected-label {
    font-weight: 500;
    color: var(--fd-primary-color, #2563eb);
    font-size: 0.8125rem;
  }

  .fd-context-selector__clear-btn {
    background: none;
    border: none;
    color: var(--fd-text-muted, #98a2b3);
    cursor: pointer;
    font-size: 1.125rem;
    padding: 0 0.25rem;
    line-height: 1;
  }

  .fd-context-selector__clear-btn:hover {
    color: var(--fd-text-color, #344054);
  }

  .fd-context-selector__preview {
    margin-top: 0.5rem;
    border: 1px solid var(--fd-border-color, #d0d5dd);
    border-radius: 4px;
    overflow: hidden;
  }

  .fd-context-selector__preview--loading {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem;
    color: var(--fd-text-muted, #667085);
    font-size: 0.8125rem;
  }

  .fd-context-selector__preview-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.375rem 0.5rem;
    background: var(--fd-bg-muted, #f9fafb);
    border-bottom: 1px solid var(--fd-border-color, #d0d5dd);
  }

  .fd-context-selector__preview-label {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--fd-text-muted, #667085);
  }

  .fd-context-selector__edit-link {
    margin-left: auto;
    font-size: 0.6875rem;
    color: var(--fd-primary-color, #2563eb);
    text-decoration: none;
    font-weight: 500;
  }

  .fd-context-selector__edit-link:hover {
    text-decoration: underline;
  }

  .fd-context-selector__badge {
    font-size: 0.6875rem;
    padding: 0.0625rem 0.375rem;
    border-radius: 3px;
    font-weight: 500;
    color: var(--fd-accent, #6941c6);
    background: var(--fd-accent-muted, rgba(105, 65, 198, 0.08));
  }

  .fd-context-selector__preview-section {
    padding: 0.5rem;
    border-bottom: 1px solid var(--fd-border-color, #e4e7ec);
  }

  .fd-context-selector__preview-section:last-child {
    border-bottom: none;
  }

  .fd-context-selector__preview-section-title {
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--fd-text-muted, #667085);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 0.25rem;
  }

  .fd-context-selector__preview-text {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--fd-text-color, #344054);
    line-height: 1.5;
  }

  .fd-context-selector__content-preview {
    font-family: monospace;
    font-size: 0.75rem;
    background: var(--fd-bg-muted, #f9fafb);
    padding: 0.375rem;
    border-radius: 3px;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 8rem;
    overflow-y: auto;
  }

  .fd-context-selector__create-link {
    display: block;
    width: 100%;
    margin-top: 0.5rem;
    padding: 0.375rem;
    border: 1px dashed var(--fd-border-color, #d0d5dd);
    border-radius: 4px;
    color: var(--fd-text-muted, #667085);
    font-size: 0.8125rem;
    text-align: center;
    text-decoration: none;
    box-sizing: border-box;
  }

  .fd-context-selector__create-link:hover {
    border-color: var(--fd-primary-color, #2563eb);
    color: var(--fd-primary-color, #2563eb);
    text-decoration: none;
  }
</style>
