{% extends "base.html" %}
{% block title %}{{ _("search.page_title") }} - DocuElevate{% endblock %}

{% block head_extra %}
  <script src="/static/js/common.js"></script>
  <style>
    .search-container { max-width: 800px; margin: 0 auto; }
    .search-box {
      display: flex; gap: 0.5rem; align-items: center;
      margin-bottom: 0.75rem;
    }
    .search-box input {
      flex: 1; padding: 0.75rem 1rem;
      border: 1px solid #d1d5db; border-radius: 0.5rem;
      font-size: 1rem; outline: none;
    }
    .search-box input:focus {
      border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
    }
    .search-box button {
      padding: 0.75rem 1.5rem; background-color: #3b82f6;
      color: white; border: none; border-radius: 0.5rem;
      font-size: 1rem; cursor: pointer; font-weight: 600;
      white-space: nowrap;
    }
    .search-box button:hover { background-color: #2563eb; }
    .search-filters {
      display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-end;
      margin-bottom: 0.75rem; padding: 0.75rem;
      border: 1px solid #e5e7eb; border-radius: 0.5rem;
      background: #f9fafb;
    }
    .search-filter-item { display: flex; flex-direction: column; gap: 0.2rem; }
    .search-filter-item label {
      font-size: 0.75rem; font-weight: 600; color: #4b5563;
    }
    .search-filter-item select,
    .search-filter-item input {
      padding: 0.4rem 0.5rem; border: 1px solid #d1d5db;
      border-radius: 0.375rem; font-size: 0.8rem; min-width: 120px;
    }
    .search-saved-bar {
      display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
      margin-bottom: 1rem; font-size: 0.85rem;
    }
    .search-saved-bar .saved-label {
      font-weight: 600; white-space: nowrap;
    }
    .saved-search-tag {
      display: inline-flex; align-items: center; gap: 0.25rem;
      background: #e5e7eb; padding: 0.2rem 0.5rem; border-radius: 0.25rem;
      font-size: 0.8rem;
    }
    .saved-search-tag a { text-decoration: none; color: inherit; }
    .saved-search-tag button {
      border: none; background: none; cursor: pointer; color: #6b7280;
      padding: 0; line-height: 1;
    }
    .btn-save-search {
      margin-left: auto; font-size: 0.8rem; padding: 0.25rem 0.5rem;
      cursor: pointer; border: 1px solid #d1d5db; border-radius: 0.25rem;
      background: white; color: #374151; white-space: nowrap;
    }
    .btn-save-search:hover { background: #f3f4f6; }
    .search-summary {
      font-size: 0.875rem; color: #6b7280;
      margin-bottom: 1rem;
    }
    .search-result {
      margin-bottom: 1.5rem;
    }
    .search-result-title a {
      font-size: 1.125rem; font-weight: 600;
      color: #1a0dab; text-decoration: none;
    }
    .search-result-title a:hover { text-decoration: underline; }
    .search-result-url {
      font-size: 0.8rem; color: #006621; margin-top: 0.1rem;
      word-break: break-all;
    }
    .search-result-meta {
      display: flex; flex-wrap: wrap; gap: 0.4rem;
      margin-top: 0.3rem;
    }
    .search-result-badge {
      display: inline-block; padding: 0.1rem 0.5rem;
      border-radius: 9999px; font-size: 0.7rem; font-weight: 500;
    }
    .badge-type { background: #eff6ff; color: #1d4ed8; }
    .badge-tag  { background: #f0fdf4; color: #15803d; }
    .badge-sender { background: #fef3c7; color: #92400e; }
    .search-result-snippet {
      font-size: 0.875rem; color: #4d5156;
      line-height: 1.5; margin-top: 0.35rem;
      word-break: break-word;
    }
    .search-result-snippet mark {
      background: #fef08a; font-weight: 600;
      border-radius: 2px; padding: 0 1px;
    }
    .search-pagination {
      display: flex; justify-content: center;
      gap: 0.5rem; margin-top: 2rem;
    }
    .search-pagination button {
      padding: 0.4rem 1rem; border: 1px solid #d1d5db;
      border-radius: 0.375rem; font-size: 0.875rem;
      cursor: pointer; background: white; color: #374151;
    }
    .search-pagination button:hover { background: #f3f4f6; }
    .search-pagination span {
      padding: 0.4rem 0.75rem; font-size: 0.875rem; color: #6b7280;
    }
    .search-empty {
      text-align: center; padding: 3rem 1rem; color: #9ca3af;
    }
    .search-empty i { font-size: 3rem; margin-bottom: 1rem; display: block; }
  </style>
{% endblock %}

{% block content %}
<div class="container mx-auto px-4 py-8">
  <div class="search-container">
    <h1 class="text-3xl font-bold mb-6"><i class="fas fa-search text-blue-500" aria-hidden="true"></i> {{ _("search.heading") }}</h1>

    <!-- Search box -->
    <div class="search-box" role="search">
      <label for="search-input" class="sr-only">{{ _("search.input_aria_label") }}</label>
      <input
        type="search"
        id="search-input"
        placeholder="{{ _('search.input_placeholder') }}"
        value="{{ query }}"
        autofocus
      >
      <button type="button" id="search-btn" aria-label="{{ _('search.input_aria_label') }}">
        <i class="fas fa-search" aria-hidden="true"></i> {{ _("search.button") }}
      </button>
    </div>

    <!-- Content-finding filters -->
    <div class="search-filters" id="search-filters">
      <div class="search-filter-item">
        <label for="filter-document-type">{{ _("search.filter_document_type") }}</label>
        <input type="text" id="filter-document-type" placeholder="{{ _('search.filter_document_type_placeholder') }}" aria-label="{{ _('search.filter_aria_document_type') }}">
      </div>
      <div class="search-filter-item">
        <label for="filter-tags">{{ _("search.filter_tags") }}</label>
        <input type="text" id="filter-tags" placeholder="{{ _('search.filter_tags_placeholder') }}" aria-label="{{ _('search.filter_aria_tag') }}">
      </div>
      <div class="search-filter-item">
        <label for="filter-sender">{{ _("search.filter_sender") }}</label>
        <input type="text" id="filter-sender" placeholder="{{ _('search.filter_sender_placeholder') }}" aria-label="{{ _('search.filter_aria_sender') }}">
      </div>
      <div class="search-filter-item">
        <label for="filter-language">{{ _("search.filter_language") }}</label>
        <input type="text" id="filter-language" placeholder="{{ _('search.filter_language_placeholder') }}" aria-label="{{ _('search.filter_aria_language') }}">
      </div>
      <div class="search-filter-item">
        <label for="filter-text-quality">{{ _("search.filter_text_quality") }}</label>
        <select id="filter-text-quality" aria-label="{{ _('search.filter_aria_text_quality') }}">
          <option value="">{{ _("search.filter_text_quality_all") }}</option>
          <option value="high">{{ _("search.filter_text_quality_high") }}</option>
          <option value="medium">{{ _("search.filter_text_quality_medium") }}</option>
          <option value="low">{{ _("search.filter_text_quality_low") }}</option>
          <option value="no_text">{{ _("search.filter_text_quality_no_text") }}</option>
        </select>
      </div>
      <div class="search-filter-item">
        <label for="filter-date-from">{{ _("search.filter_date_from") }}</label>
        <input type="date" id="filter-date-from" aria-label="{{ _('search.filter_aria_date_from') }}">
      </div>
      <div class="search-filter-item">
        <label for="filter-date-to">{{ _("search.filter_date_to") }}</label>
        <input type="date" id="filter-date-to" aria-label="{{ _('search.filter_aria_date_to') }}">
      </div>
      <div class="search-filter-item" style="align-self: flex-end;">
        <button type="button" id="clear-filters-btn" style="padding: 0.4rem 0.75rem; border: 1px solid #d1d5db; border-radius: 0.375rem; font-size: 0.8rem; cursor: pointer; background: white; color: #374151;" aria-label="{{ _('search.filter_aria_clear') }}">
          {{ _("search.filter_clear_button") }}
        </button>
      </div>
    </div>

    <!-- Saved Searches -->
    <div class="search-saved-bar" id="saved-searches-bar">
      <span class="saved-label"><i class="fas fa-bookmark" aria-hidden="true"></i> {{ _("search.saved_label") }}:</span>
      <span id="saved-searches-list" aria-live="polite" style="display: flex; gap: 0.25rem; flex-wrap: wrap;">
        <span style="color: #9ca3af; font-size: 0.85rem;">{{ _("search.saved_loading") }}</span>
      </span>
      <button type="button" id="save-search-btn" class="btn-save-search" aria-label="{{ _('search.saved_aria_save') }}">
        <i class="fas fa-plus" aria-hidden="true"></i> {{ _("search.saved_button") }}
      </button>
    </div>

    <!-- Summary -->
    <div id="search-summary" class="search-summary" style="display:none;" aria-live="polite"></div>

    <!-- Results -->
    <div id="search-results" aria-live="polite" aria-relevant="additions removals"></div>

    <!-- Pagination -->
    <div id="search-pagination" class="search-pagination" style="display:none;"></div>
  </div>
</div>

<script>
  const searchInput  = document.getElementById('search-input');
  const searchBtn    = document.getElementById('search-btn');
  const resultsDiv   = document.getElementById('search-results');
  const summaryDiv   = document.getElementById('search-summary');
  const paginationDiv = document.getElementById('search-pagination');

  // Filter elements
  const filterDocType    = document.getElementById('filter-document-type');
  const filterTags       = document.getElementById('filter-tags');
  const filterSender     = document.getElementById('filter-sender');
  const filterLanguage   = document.getElementById('filter-language');
  const filterTextQuality = document.getElementById('filter-text-quality');
  const filterDateFrom   = document.getElementById('filter-date-from');
  const filterDateTo     = document.getElementById('filter-date-to');

  let _debounce = null;
  let _currentPage = 1;
  const PER_PAGE = 20;

  /** Collect active filter values into an object. */
  function getActiveFilters() {
    const filters = {};
    const dt = filterDocType.value.trim();
    if (dt) filters.document_type = dt;
    const tg = filterTags.value.trim();
    if (tg) filters.tags = tg;
    const sn = filterSender.value.trim();
    if (sn) filters.sender = sn;
    const ln = filterLanguage.value.trim();
    if (ln) filters.language = ln;
    const tq = filterTextQuality.value;
    if (tq) filters.text_quality = tq;
    const df = filterDateFrom.value;
    if (df) filters.date_from = Math.floor(new Date(df + 'T00:00:00Z').getTime() / 1000);
    const dTo = filterDateTo.value;
    if (dTo) filters.date_to = Math.floor(new Date(dTo + 'T23:59:59Z').getTime() / 1000);
    return filters;
  }

  /** Apply filter values from an object to the UI inputs. */
  function applyFiltersToUI(filters) {
    filterDocType.value = filters.document_type || '';
    filterTags.value = filters.tags || '';
    filterSender.value = filters.sender || '';
    filterLanguage.value = filters.language || '';
    filterTextQuality.value = filters.text_quality || '';
    filterDateFrom.value = filters.date_from || '';
    filterDateTo.value = filters.date_to || '';
  }

  function doSearch(page) {
    const q = searchInput.value.trim();
    if (!q) {
      resultsDiv.innerHTML = '';
      summaryDiv.style.display = 'none';
      paginationDiv.style.display = 'none';
      return;
    }
    _currentPage = page || 1;

    // Update URL without reload
    const url = new URL(window.location);
    url.searchParams.set('q', q);
    // Sync filter params to URL
    const activeFilters = getActiveFilters();
    Object.keys(activeFilters).forEach(function(key) {
      url.searchParams.set(key, activeFilters[key]);
    });
    // Remove filter keys not in activeFilters
    ['document_type', 'tags', 'sender', 'language', 'text_quality', 'date_from', 'date_to'].forEach(function(key) {
      if (!activeFilters[key]) url.searchParams.delete(key);
    });
    window.history.replaceState({}, '', url);

    // Loading indicator
    resultsDiv.innerHTML = '<div style="text-align:center;padding:2rem;color:#6b7280;"><i class="fas fa-spinner fa-spin fa-2x"></i><p style="margin-top:0.75rem;">Searching…</p></div>';
    summaryDiv.style.display = 'none';
    paginationDiv.style.display = 'none';

    const params = new URLSearchParams({ q: q, page: _currentPage, per_page: PER_PAGE });
    // Append filter params (date_from/date_to already converted to timestamps)
    Object.keys(activeFilters).forEach(function(key) {
      params.set(key, activeFilters[key]);
    });

    fetch('/api/search?' + params.toString())
      .then(function(r) { if (!r.ok) throw new Error('Search returned ' + r.status); return r.json(); })
      .then(function(data) { renderResults(data, q); })
      .catch(function(err) {
        resultsDiv.innerHTML = '<div style="text-align:center;padding:2rem;color:#dc2626;"><i class="fas fa-exclamation-triangle fa-2x"></i><p style="margin-top:0.5rem;">Search is temporarily unavailable. Please try again in a moment.</p><p style="font-size:0.75rem;color:#9ca3af;margin-top:0.25rem;">' + escapeHtml(err.message) + '</p></div>';
      });
  }

  function escapeHtml(str) {
    const d = document.createElement('div');
    d.textContent = str;
    return d.innerHTML;
  }

  /**
   * Sanitize Meilisearch highlighted HTML: allow only <mark> tags,
   * escape everything else to prevent XSS from indexed content.
   */
  function sanitizeHighlight(html) {
    let safe = html
      .replace(/<mark>/gi,  '\x00MARK_OPEN\x00')
      .replace(/<\/mark>/gi, '\x00MARK_CLOSE\x00');
    safe = escapeHtml(safe);
    safe = safe
      .replace(/\x00MARK_OPEN\x00/g,  '<mark>')
      .replace(/\x00MARK_CLOSE\x00/g, '</mark>');
    return safe;
  }

  function renderResults(data, q) {
    const results = data.results;
    const total = data.total;
    const page = data.page;
    const pages = data.pages;

    summaryDiv.textContent = total + ' result' + (total !== 1 ? 's' : '') + ' for "' + q + '"';
    summaryDiv.style.display = 'block';

    if (!results || results.length === 0) {
      resultsDiv.innerHTML = '<div class="search-empty"><i class="fas fa-search" aria-hidden="true"></i><p>No documents found matching your query.</p></div>';
      paginationDiv.style.display = 'none';
      return;
    }

    resultsDiv.innerHTML = results.map(function(hit) {
      const fmt = hit._formatted || {};
      const title = fmt.document_title || hit.document_title || hit.original_filename || '(untitled)';
      const filename = hit.original_filename || '';
      const snippet = fmt.ocr_text || '';
      const tags = Array.isArray(hit.tags) ? hit.tags : (hit.tags ? [hit.tags] : []);
      const docType = hit.document_type || '';
      const sender = hit.sender || hit.absender || '';
      const fileUrl = '/files/' + hit.file_id;

      let badges = '';
      if (docType) badges += '<span class="search-result-badge badge-type">' + escapeHtml(docType) + '</span>';
      if (sender)  badges += '<span class="search-result-badge badge-sender"><i class="fas fa-user" aria-hidden="true"></i> ' + escapeHtml(sender) + '</span>';
      tags.forEach(function(t) { badges += '<span class="search-result-badge badge-tag">' + escapeHtml(t) + '</span>'; });

      let snippetHtml = '';
      if (snippet) {
        const trimmed = snippet.length > 500 ? snippet.substring(0, 500) + '…' : snippet;
        snippetHtml = '<div class="search-result-snippet">…' + sanitizeHighlight(trimmed) + '…</div>';
      }

      const safeTitle = (fmt.document_title) ? sanitizeHighlight(title) : escapeHtml(title);

      return '<div class="search-result">' +
        '<div class="search-result-title"><a href="' + escapeHtml(fileUrl) + '">' + safeTitle + '</a></div>' +
        '<div class="search-result-url">' + escapeHtml(filename) + '</div>' +
        (badges ? '<div class="search-result-meta">' + badges + '</div>' : '') +
        snippetHtml +
        '</div>';
    }).join('');

    if (pages > 1) {
      const btns = [];
      if (page > 1) btns.push('<button data-page="' + (page - 1) + '">« Previous</button>');
      btns.push('<span>Page ' + page + ' of ' + pages + '</span>');
      if (page < pages) btns.push('<button data-page="' + (page + 1) + '">Next »</button>');
      paginationDiv.innerHTML = btns.join('');
      paginationDiv.style.display = 'flex';
    } else {
      paginationDiv.style.display = 'none';
    }
  }

  // Event delegation for pagination buttons
  paginationDiv.addEventListener('click', function(e) {
    const btn = e.target.closest('button[data-page]');
    if (btn) doSearch(parseInt(btn.getAttribute('data-page'), 10));
  });

  // Event listeners for search
  searchBtn.addEventListener('click', function() { doSearch(1); });
  searchInput.addEventListener('keydown', function(e) {
    if (e.key === 'Enter') { doSearch(1); }
  });
  searchInput.addEventListener('input', function() {
    clearTimeout(_debounce);
    const val = searchInput.value.trim();
    if (val.length < 2) {
      resultsDiv.innerHTML = '';
      summaryDiv.style.display = 'none';
      paginationDiv.style.display = 'none';
      return;
    }
    _debounce = setTimeout(function() { doSearch(1); }, 400);
  });

  // Clear filters button
  document.getElementById('clear-filters-btn').addEventListener('click', function() {
    applyFiltersToUI({});
    if (searchInput.value.trim().length >= 2) doSearch(1);
  });

  // Re-run search when filters change
  const filterInputs = [filterDocType, filterTags, filterSender, filterLanguage, filterTextQuality, filterDateFrom, filterDateTo];
  filterInputs.forEach(function(el) {
    el.addEventListener('change', function() {
      if (searchInput.value.trim().length >= 2) doSearch(1);
    });
  });

  // ---- Saved searches functionality ----
  function loadSavedSearches() {
    fetch('/api/saved-searches')
      .then(function(response) { return response.json(); })
      .then(function(searches) {
        const container = document.getElementById('saved-searches-list');
        if (!container) return;
        if (!searches || searches.length === 0) {
          container.innerHTML = '<span style="color: #9ca3af; font-size: 0.85rem;">No saved searches yet</span>';
          return;
        }
        container.innerHTML = searches.map(function(s) {
          const params = new URLSearchParams(s.filters);
          return '<span class="saved-search-tag">' +
            '<a href="/search?' + escapeHtml(params.toString()) + '">' + escapeHtml(s.name) + '</a>' +
            '<button type="button" onclick="deleteSavedSearch(' + s.id + ')" aria-label="Delete saved search ' + escapeHtml(s.name) + '">' +
            '<i class="fas fa-times" aria-hidden="true"></i>' +
            '</button>' +
            '</span>';
        }).join('');
      })
      .catch(function() {
        const container = document.getElementById('saved-searches-list');
        if (container) container.innerHTML = '<span style="color: #9ca3af; font-size: 0.85rem;">Could not load saved searches</span>';
      });
  }

  document.getElementById('save-search-btn').addEventListener('click', function() {
    const filters = getActiveFilters();
    const q = searchInput.value.trim();
    // For saved searches on this page, store date_from/date_to as ISO strings
    // instead of timestamps so the URL params are human-readable.
    if (filterDateFrom.value) filters.date_from = filterDateFrom.value;
    if (filterDateTo.value) filters.date_to = filterDateTo.value;
    if (q) filters.q = q;

    if (Object.keys(filters).length === 0) {
      alert('No search query or filters to save. Please enter a query or set at least one filter.');
      return;
    }
    const name = prompt('Enter a name for this saved search:');
    if (!name || !name.trim()) return;
    fetch('/api/saved-searches', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: name.trim(), filters: filters })
    })
    .then(function(response) {
      if (!response.ok) return response.json().then(function(d) { throw new Error(d.detail || 'Failed to save'); });
      return response.json();
    })
    .then(function() { loadSavedSearches(); })
    .catch(function(error) { alert(error.message); });
  });

  function deleteSavedSearch(id) {
    if (!confirm('Delete this saved search?')) return;
    fetch('/api/saved-searches/' + id, { method: 'DELETE' })
      .then(function(response) {
        if (!response.ok) throw new Error('Failed to delete');
        loadSavedSearches();
      })
      .catch(function(error) { alert(error.message); });
  }

  // ---- Initialize from URL params ----
  (function() {
    const urlParams = new URLSearchParams(window.location.search);
    // Populate filters from URL params (for saved search links)
    if (urlParams.get('document_type')) filterDocType.value = urlParams.get('document_type');
    if (urlParams.get('tags')) filterTags.value = urlParams.get('tags');
    if (urlParams.get('sender')) filterSender.value = urlParams.get('sender');
    if (urlParams.get('language')) filterLanguage.value = urlParams.get('language');
    if (urlParams.get('text_quality')) filterTextQuality.value = urlParams.get('text_quality');
    if (urlParams.get('date_from')) filterDateFrom.value = urlParams.get('date_from');
    if (urlParams.get('date_to')) filterDateTo.value = urlParams.get('date_to');

    // Load saved searches
    loadSavedSearches();

    // If q was provided via URL, search immediately
    if (searchInput.value.trim().length >= 2) {
      doSearch(1);
    }
  })();
</script>
{% endblock %}
