import { requireEl, optionalEl, warnOnce } from '../core/app-dom.js';

const input = requireEl('#side-search', { module: 'global-search' });
const resultsEl = requireEl('[data-global-search-results]', { module: 'global-search' });

if (input && resultsEl) {
  const emptyStateEl = optionalEl('[data-global-search-empty]');
  const emptyHintEl = optionalEl('[data-search-empty-hint-template]');
  const shortcutEl = optionalEl('[data-search-shortcut]');
  const panel = optionalEl('#aside-panel-search');
  const toggleButton = optionalEl('[data-search-details-toggle]');
  const toggleIcon = optionalEl('[data-search-details-icon]');
  const appBase = window.APP_BASE || document.baseURI;
  const endpoint = new URL('admin/search/data', appBase);
  const resultsPage = new URL('search', appBase);
  const minLength = 2;
  let pending = null;
  const shortcutLabel = /(Mac|iPhone|iPad|iPod)/i.test(navigator.platform || navigator.userAgent)
    ? '⌘K'
    : 'Ctrl+K';

  if (emptyHintEl) {
    const template = emptyHintEl.getAttribute('data-search-empty-hint-template') || '';
    emptyHintEl.textContent = template.replace('{shortcut}', shortcutLabel);
  }
  if (shortcutEl) {
    shortcutEl.textContent = shortcutLabel;
  }

  const itemsByKey = new Map();
  resultsEl.querySelectorAll('[data-search-key]').forEach((item) => {
    const key = item.getAttribute('data-search-key');
    if (key) {itemsByKey.set(key, item);}
  });
  if (itemsByKey.size === 0) {
    warnOnce('UI_EL_MISSING', 'No [data-search-key] elements found in results container', { module: 'global-search' });
  }

  const setLoadingState = (value) => {
    resultsEl.querySelectorAll('[data-search-count]').forEach((el) => {
      el.textContent = value;
    });
  };

  const setIdleState = (idle) => {
    if (emptyStateEl) {
      emptyStateEl.hidden = !idle;
    }
    resultsEl.hidden = idle;
  };

  const render = (items, query) => {
    const renderedKeys = new Set();
    items.forEach((item) => {
      const li = itemsByKey.get(item.key);
      if (!li) {
        warnOnce('UI_EL_MISSING', `No element found for key: ${item.key}`, { module: 'global-search' });
        return;
      }
      renderedKeys.add(item.key);
      const countEl = li.querySelector('[data-search-count]');
      const link = li.querySelector('a');
      const previewEl = li.querySelector('[data-search-preview]');
      const base = item.key === 'pages' && item.url ? item.url : (li.getAttribute('data-search-base') || item.url);
      const url = new URL(base, appBase);
      if (item.key !== 'pages') {
        url.searchParams.set('search', query);
      }
      if (countEl) {countEl.textContent = item.count.toString();}
      if (link) {
        link.href = item.count > 0 ? url.toString() : base;
        link.setAttribute('aria-disabled', item.count > 0 ? 'false' : 'true');
      }
      if (previewEl) {
        previewEl.innerHTML = '';
        if (Array.isArray(item.items) && item.items.length > 0) {
          item.items.forEach((previewItem, idx) => {
            if (!previewItem || !previewItem.url) {
              warnOnce('UI_DATA_MISSING', `Preview item missing url at index ${idx} for key: ${item.key}`, {
                module: 'global-search',
                item: previewItem
              });
              return;
            }
            const previewLi = document.createElement('li');
            const previewLink = document.createElement('a');
            previewLink.href = previewItem.url;
            previewLink.textContent = previewItem.label || '';
            previewLi.appendChild(previewLink);
            previewEl.appendChild(previewLi);
          });
        }
      }
      if (item.count > 0) {
        li.hidden = false;
      } else {
        li.hidden = true;
      }
    });

    itemsByKey.forEach((li, key) => {
      if (renderedKeys.has(key)) {
        return;
      }
      const countEl = li.querySelector('[data-search-count]');
      const link = li.querySelector('a');
      const previewEl = li.querySelector('[data-search-preview]');
      const base = li.getAttribute('data-search-base') || '#';
      if (countEl) {countEl.textContent = '0';}
      if (link) {
        link.href = base;
        link.setAttribute('aria-disabled', 'true');
      }
      if (previewEl) {
        previewEl.innerHTML = '';
      }
      li.hidden = true;
    });
  };

  const clear = () => {
    setIdleState(true);
    setLoadingState('0');
    resultsEl.querySelectorAll('a').forEach((link) => {
      link.setAttribute('aria-disabled', 'true');
      const base = link.closest('[data-search-base]')?.getAttribute('data-search-base');
      link.setAttribute('href', base || '#');
    });
    resultsEl.querySelectorAll('[data-search-preview]').forEach((list) => {
      list.innerHTML = '';
    });
    resultsEl.querySelectorAll('[data-search-key]').forEach((li) => {
      li.hidden = false;
    });
  };

  const fetchCounts = async (value) => {
    setIdleState(false);
    const url = new URL(endpoint.toString());
    url.searchParams.set('q', value);
    setLoadingState('…');
    const response = await fetch(url.toString(), { headers: { 'Accept': 'application/json' } });
    if (!response.ok) {
      warnOnce('FETCH_FAILED', `Global search failed: ${response.status} ${response.statusText}`, {
        module: 'global-search'
      });
      clear();
      return;
    }
    const data = await response.json();
    if (Array.isArray(data)) {
      render(data, value);
    } else {
      warnOnce('FETCH_INVALID', `Invalid response format for global search`, {
        module: 'global-search',
        type: typeof data
      });
      clear();
    }
  };

  const onInput = () => {
    const value = input.value.trim();
    if (value.length < minLength) {
      clear();
      return;
    }
    if (pending) {window.clearTimeout(pending);}
    pending = window.setTimeout(() => {
      fetchCounts(value).catch((err) => {
        warnOnce('FETCH_ERROR', 'Global search fetch error', { module: 'global-search', err });
        clear();
      });
    }, 300);
  };

  input.addEventListener('input', onInput);
  const submitSearch = () => {
    const value = input.value.trim();
    if (value.length < minLength) {return;}
    resultsPage.searchParams.set('search', value);
    window.location.href = resultsPage.toString();
  };

  input.addEventListener('keydown', (event) => {
    if (event.key !== 'Enter') {return;}
    event.preventDefault();
    submitSearch();
  });

  const isEditableTarget = (target) => {
    if (!target) {return false;}
    if (target.isContentEditable) {return true;}
    const tag = target.tagName;
    return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';
  };

  const focusSearch = () => {
    if (!input) {return;}
    window.requestAnimationFrame(() => {
      input.focus();
      input.select();
    });
  };

  const openSearch = () => {
    if (window.AppAsidePanels?.open) {
      window.AppAsidePanels.open('search');
    } else {
      document.querySelector('[data-aside-target="search"]')?.click();
    }
    focusSearch();
  };

  if (emptyStateEl) {
    emptyStateEl.addEventListener('click', () => {
      focusSearch();
    });
  }

  document.addEventListener('keydown', (event) => {
    if (!(event.metaKey || event.ctrlKey)) {return;}
    const key = event.key.toLowerCase();
    if (key !== 'k' && key !== '/') {return;}
    if (isEditableTarget(event.target) && event.target !== input) {return;}
    event.preventDefault();
    openSearch();
  });

  const form = input.closest('form');
  if (form) {
    form.addEventListener('submit', (event) => {
      event.preventDefault();
      submitSearch();
    });
  }

  if (toggleButton && panel) {
    toggleButton.addEventListener('click', () => {
      panel.classList.toggle('search-details-hidden');
      if (toggleIcon) {
        toggleIcon.classList.toggle('bi-dash-square');
        toggleIcon.classList.toggle('bi-plus-square');
      }
    });
  }

  // Seed from current URL search param if present.
  const currentUrl = new URL(window.location.href);
  const preset = (currentUrl.searchParams.get('search') || '').trim();
  if (preset && !input.value) {
    input.value = preset;
  }

  const initialValue = input.value.trim();
  if (initialValue.length >= minLength) {
    fetchCounts(initialValue).catch((err) => {
      warnOnce('FETCH_ERROR', 'Global search fetch error', { module: 'global-search', err });
      clear();
    });
  } else {
    clear();
  }
}
