<template>
  <div>
    <div class="page-header">
      <div class="header-left">
        <h2>Knowledge Base</h2>
        <span v-if="stats" class="stats-badge">
          {{ stats.totalarticles }} articles | {{ stats.totalclicks.toLocaleString() }} total clicks
        </span>
      </div>
      <router-link to="/knowledgebase/new" class="btn btn-primary">Add Article</router-link>
    </div>

    <!-- Filters -->
    <div class="filters">
      <input
        v-model="search"
        type="text"
        class="form-control"
        placeholder="Search articles..."
        @input="debouncedSearch"
      />
      <select v-model="topicFilter" class="form-control" @change="applyFilter">
        <option value="">All Topics</option>
        <option
          v-for="app in topics"
          :key="app.appid"
          :value="app.appid"
        >
          {{ app.appname }}
        </option>
      </select>
    </div>

    <div class="card">
      <div v-if="loading" class="loading">Loading...</div>

      <template v-else>
        <div class="table-container">
          <table>
            <thead>
              <tr>
                <th class="sortable" @click="toggleSort('topic')">
                  Topic
                  <span v-if="sort === 'topic'" class="sort-arrow">{{ order === 'asc' ? '&#9650;' : '&#9660;' }}</span>
                </th>
                <th class="sortable" @click="toggleSort('description')">
                  Description
                  <span v-if="sort === 'description'" class="sort-arrow">{{ order === 'asc' ? '&#9650;' : '&#9660;' }}</span>
                </th>
                <th class="sortable" style="width: 100px;" @click="toggleSort('clicks')">
                  Clicks
                  <span v-if="sort === 'clicks'" class="sort-arrow">{{ order === 'asc' ? '&#9650;' : '&#9660;' }}</span>
                </th>
                <th style="width: 120px;">Actions</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="article in articles" :key="article.linkid">
                <td>
                  <router-link
                    v-if="article.application"
                    :to="`/applications/${article.application.appid}`"
                  >
                    {{ article.application.appname }}
                  </router-link>
                  <span v-else class="text-muted">-</span>
                </td>
                <td>
                  <a
                    href="#"
                    class="article-link"
                    @click.prevent="openArticle(article)"
                    :title="article.linkurl"
                  >
                    {{ truncate(article.shortdescription, 95) }}
                  </a>
                </td>
                <td style="text-align: center; font-weight: 500;">{{ article.clicks }}</td>
                <td class="actions">
                  <router-link :to="`/knowledgebase/${article.linkid}`" class="btn btn-sm btn-secondary">
                    View
                  </router-link>
                  <router-link :to="`/knowledgebase/${article.linkid}/edit`" class="btn btn-sm btn-secondary">
                    Edit
                  </router-link>
                </td>
              </tr>
              <tr v-if="articles.length === 0">
                <td colspan="4" style="text-align: center; color: var(--text-light);">
                  No articles found
                  <SearchSuggestion :suggestion="suggestion" @pick="applySuggestion" />
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <!-- Pagination -->
        <PaginationBar
          :page="page"
          :totalPages="totalPages"
          :perPage="perPage"
          @update:page="goToPage"
          @update:perPage="changePerPage"
        />
      </template>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { knowledgebaseApi, applicationsApi } from '@/api'
import PaginationBar from '@/components/PaginationBar.vue'
import { useListQuery } from '@/composables/listQuery'
import SearchSuggestion from '@/components/SearchSuggestion.vue'

const loading = ref(true)
const articles = ref([])
const topics = ref([])
const stats = ref(null)
const { page, search, setPage, setSearch, suggestion, reportCount } = useListQuery({ onChange: loadArticles })

// Take the offered spelling. setSearch only syncs the URL and the watcher
// that reloads is suppressed because search.value already holds the new
// term, so load directly.
function applySuggestion(word) {
  search.value = word
  setSearch(word)
  loadArticles()
}
const perPage = ref(20)
const totalPages = ref(1)
const topicFilter = ref('')
const sort = ref('clicks')
const order = ref('desc')

let searchTimeout = null

onMounted(async () => {
  await Promise.all([
    loadArticles(),
    loadTopics(),
    loadStats()
  ])
})

// A filter change must go back to page 1. Selecting a filter while on page 5
// asked the server for page 5 of a result set that now has one page, and the
// list came back empty as though the filter matched nothing.
//
// setPage(1) writes the URL, which the composable's watcher picks up and
// answers with onChange - so calling the loader as well would fetch twice.
// Load directly only when already on page 1, where nothing changes and the
// watcher stays silent.
function applyFilter() {
  if (page.value > 1) setPage(1)
  else loadArticles()
}

async function loadArticles() {
  loading.value = true
  try {
    const params = {
      page: page.value,
      perpage: perPage.value,
      sort: sort.value,
      order: order.value
    }
    if (search.value) params.search = search.value
    if (topicFilter.value) params.appid = topicFilter.value

    const response = await knowledgebaseApi.list(params)
    articles.value = response.data.data || []
    reportCount(articles.value.length)
    totalPages.value = response.data.meta?.pagination?.totalpages || response.data.meta?.pagination?.total_pages || 1
  } catch (error) {
    console.error('Error loading articles:', error)
  } finally {
    loading.value = false
  }
}

async function loadTopics() {
  try {
    // listAll, not list: the backend clamps perpage to 100 without saying so,
    // and the catalogue is past that, so topics sorting late in the alphabet
    // were silently missing from this filter.
    // isactive is the only filter that applies to a topic: ishidden governs
    // whether an application shows on the tiles page, which says nothing about
    // whether it can be the subject of an article.
    topics.value = await applicationsApi.listAll({ showhidden: true })
  } catch (error) {
    console.error('Error loading topics:', error)
  }
}

async function loadStats() {
  try {
    const response = await knowledgebaseApi.getStats()
    stats.value = response.data.data
  } catch (error) {
    console.error('Error loading stats:', error)
  }
}

function debouncedSearch() {
  clearTimeout(searchTimeout)
  searchTimeout = setTimeout(() => {
    setSearch(search.value)
    loadArticles()
  }, 300)
}

function goToPage(p) {
  setPage(p)
  loadArticles()
}

function changePerPage(newPerPage) {
  perPage.value = newPerPage
  setPage(1)
  loadArticles()
}

function toggleSort(column) {
  if (sort.value === column) {
    order.value = order.value === 'desc' ? 'asc' : 'desc'
  } else {
    sort.value = column
    order.value = 'desc'
  }
  loadArticles()
}

function truncate(text, length) {
  if (!text) return ''
  if (text.length <= length) return text
  return text.substring(0, length) + '...'
}

async function openArticle(article) {
  try {
    await knowledgebaseApi.trackClick(article.linkid)
    article.clicks = (article.clicks || 0) + 1
    if (stats.value) {
      stats.value.totalclicks++
    }
    if (article.linkurl) {
      window.open(article.linkurl, '_blank')
    }
  } catch (error) {
    console.error('Error tracking click:', error)
    if (article.linkurl) {
      window.open(article.linkurl, '_blank')
    }
  }
}
</script>

<style scoped>
/* Knowledge Base specific styles only */
.header-left {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.header-left h2 {
  margin: 0;
}

.stats-badge {
  background: var(--bg);
  color: var(--link);
  padding: 0.5rem 1rem;
  border-radius: 6px;
  font-size: 1rem;
  font-weight: 500;
}

.article-link {
  color: var(--text);
}

.article-link:hover {
  color: var(--link);
}

.text-muted {
  color: var(--text-light);
}
</style>
