(() => {
  const escapeHtml = value => String(value ?? '').replace(/[&<>'"]/g, char => ({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[char]));
  const debounce = (fn, wait = 250) => { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), wait); }; };

  document.querySelectorAll('[data-medicine-builder]').forEach(builder => {
    if (builder.dataset.editable !== '1') return;
    const search = builder.querySelector('[data-medicine-search]');
    const results = builder.querySelector('[data-medicine-results]');
    const items = builder.querySelector('[data-medicine-items]');
    const template = builder.querySelector('[data-medicine-template]');
    const empty = builder.querySelector('[data-medicine-empty]');
    const addCustom = builder.querySelector('[data-medicine-add-custom]');
    let controller = null;

    const refreshEmpty = () => { if (empty) empty.hidden = items.querySelector('[data-medicine-row]') !== null; };
    const bindRow = row => {
      row.querySelector('[data-medicine-remove]')?.addEventListener('click', () => { row.remove(); refreshEmpty(); });
      row.querySelector('[data-medicine-request-dispense]')?.addEventListener('click', () => {
        const medicineName = row.querySelector('[data-medicine-name]')?.value.trim() || '';
        const genericName = row.querySelector('[data-medicine-generic]')?.value.trim() || '';
        const strength = row.querySelector('[data-medicine-strength]')?.value.trim() || '';
        const quantity = row.querySelector('[name="quantity[]"], [name="medication_quantity[]"]')?.value.trim() || '';
        document.dispatchEvent(new CustomEvent('dental:request-clinic-dispense', { detail: { medicineName, genericName, strength, quantity } }));
      });
      const markCustom = () => {
        const catalog = row.querySelector('[data-medicine-catalog-id]');
        if (!catalog || !catalog.value) return;
        catalog.value = '';
        row.querySelector('[data-medicine-save-catalog]').value = '1';
        const source = row.querySelector('[data-medicine-source]');
        if (source) source.textContent = 'Modified medicine — saved as new when issued';
      };
      row.querySelector('[data-medicine-name]')?.addEventListener('input', event => {
        markCustom();
        const title = row.querySelector('[data-medicine-title]');
        if (title) title.textContent = event.target.value.trim() || 'New medicine';
      });
      row.querySelector('[data-medicine-generic]')?.addEventListener('input', markCustom);
      row.querySelector('[data-medicine-strength]')?.addEventListener('input', markCustom);
    };
    const addRow = medicine => {
      if (!template) return;
      const fragment = template.content.cloneNode(true);
      const row = fragment.querySelector('[data-medicine-row]');
      const catalogId = Number(medicine?.id || 0);
      row.querySelector('[data-medicine-catalog-id]').value = catalogId || '';
      row.querySelector('[data-medicine-save-catalog]').value = catalogId ? '0' : '1';
      row.querySelector('[data-medicine-name]').value = medicine?.display_name || medicine?.name || search?.value.trim() || '';
      row.querySelector('[data-medicine-generic]').value = medicine?.generic_name || '';
      row.querySelector('[data-medicine-strength]').value = medicine?.strength || '';
      row.querySelector('[data-medicine-route]').value = medicine?.route || 'Oral';
      row.querySelector('[data-medicine-title]').textContent = medicine?.display_name || medicine?.name || search?.value.trim() || 'New medicine';
      row.querySelector('[data-medicine-source]').textContent = catalogId ? 'Known medicine catalog' : 'New medicine — saved when issued';
      bindRow(row);
      items.append(fragment);
      refreshEmpty();
      results.hidden = true;
      results.innerHTML = '';
      if (search) search.value = '';
      row.querySelector('[data-medicine-name]')?.focus();
    };

    const renderResults = list => {
      results.innerHTML = '';
      if (!list.length) {
        const q = search.value.trim();
        results.innerHTML = `<button type="button" class="medicine-result medicine-result-new" data-new="1"><strong>Add “${escapeHtml(q)}” as a new medicine</strong><small>It will be saved to the clinic catalog when the prescription is issued.</small></button>`;
      } else {
        list.forEach(item => {
          const button = document.createElement('button');
          button.type = 'button';
          button.className = 'medicine-result';
          button.innerHTML = `<strong>${escapeHtml(item.display_name)}</strong><small>${escapeHtml([item.generic_name, item.strength, item.form, item.route].filter(Boolean).join(' · '))}</small>`;
          button.addEventListener('click', () => addRow(item));
          results.append(button);
        });
      }
      results.hidden = false;
      results.querySelector('[data-new="1"]')?.addEventListener('click', () => addRow({name: search.value.trim()}));
    };

    const runSearch = debounce(async () => {
      const q = search.value.trim();
      if (q.length < 2) { results.hidden = true; results.innerHTML = ''; return; }
      controller?.abort(); controller = new AbortController();
      try {
        const response = await fetch(`${builder.dataset.searchUrl}?q=${encodeURIComponent(q)}`, {headers:{'Accept':'application/json'}, signal:controller.signal});
        if (!response.ok) throw new Error('Search failed');
        const payload = await response.json();
        renderResults(Array.isArray(payload.items) ? payload.items : []);
      } catch (error) {
        if (error.name !== 'AbortError') renderResults([]);
      }
    });

    search?.addEventListener('input', runSearch);
    search?.addEventListener('keydown', event => {
      if (event.key === 'Enter') { event.preventDefault(); const first = results.querySelector('button'); first ? first.click() : addRow({name: search.value.trim()}); }
      if (event.key === 'Escape') { results.hidden = true; }
    });
    addCustom?.addEventListener('click', () => addRow({name: search?.value.trim() || ''}));
    document.addEventListener('click', event => { if (!builder.contains(event.target)) results.hidden = true; });
    items.querySelectorAll('[data-medicine-row]').forEach(bindRow);
    refreshEmpty();
  });
})();
