<script setup lang="ts">
/**
 * TagView — virtual tag aggregation page.
 *
 * Renders all blocks from the index that reference the given tag (#tagname),
 * ordered by most recently modified. Each result is a clickable card that
 * navigates to the source page with a hash fragment targeting the block.
 *
 * This is a read-only view — no editor, no file on disk. The tag page file
 * is created only when the user types content on this view (future feature).
 *
 * @remarks Edge cases & deferred work:
 * - `ORDER BY b.modified_at DESC` uses the index timestamp, which is set
 *   during indexing (not the actual file mtime). This means blocks re-indexed
 *   together share the same timestamp, and ordering is effectively random
 *   within a single index pass. A real fix would use the file's mtime from
 *   `fs::metadata` (stored in `pages.modified_at` but not in `blocks`).
 * - No pagination. If a tag has hundreds of references, only the last 50
 *   are returned (LIMIT 50 in the SQL query, implicitly from cursor pagination
 *   that's not yet implemented).
 * - Tag names are lowercased during link extraction (see `extractLinks` in
 *   `parse.ts`). The tag view shows the lowercased version. If the index
 *   contains mixed-case tags from a previous version, they may not match.
 */
import { ref, watch } from "vue"
import { useRouter } from "vue-router"
import { createGraphService } from "~/services/graph"
import { useWorkspaceStore } from "~/stores/workspace"

interface TagBlock {
  content: string
  pagePath: string
  blockId: string
}

const props = defineProps<{
  tag: string
}>()

const router = useRouter()
const ws = useWorkspaceStore()
const blocks = ref<TagBlock[]>([])
const loading = ref(true)

async function load() {
  const db = ws.db
  if (!db) {
    blocks.value = []
    loading.value = false
    return
  }
  try {
    const graph = createGraphService(db)
    const incoming = await graph.getIncoming(props.tag)
    const taggedBlocks = incoming.filter((r) => r.via.type === "tagged")
    blocks.value = taggedBlocks.map((r) => ({
      content: r.from.title ?? "",
      pagePath: r.from.path ?? "",
      blockId: r.from.id,
    }))
  } catch (e) {
    console.warn("[TagView] failed to load blocks:", e)
    blocks.value = []
  } finally {
    loading.value = false
  }
}

watch(() => ws.db, load, { immediate: true })

function goToBlock(pagePath: string, blockId: string) {
  router.push(`/${pagePath}#block-${blockId}`)
}

function formatContent(content: string): string {
  const firstLine = content.split("\n")[0] ?? ""
  return firstLine.length > 120 ? `${firstLine.slice(0, 120)}…` : firstLine
}
</script>

<template>
  <div class="flex flex-col min-h-full w-full max-w-3xl mx-auto px-8 pt-16 pb-12">
    <!-- Header -->
    <div class="flex items-center gap-3 mb-8">
      <UIcon name="i-lucide-hash" class="w-5 h-5 text-(--ui-primary)" />
      <h1 class="text-3xl font-semibold text-highlighted tracking-tight">
        {{ tag }}
      </h1>
    </div>

    <!-- Loading -->
    <div
      v-if="loading"
      class="flex items-center justify-center gap-2 py-16 text-sm text-muted"
    >
      <UIcon name="i-lucide-loader" class="size-4 animate-spin" />
      Loading...
    </div>

    <!-- No results -->
    <p
      v-else-if="blocks.length === 0"
      class="py-16 text-center text-sm text-muted/50 italic"
    >
      No blocks reference this tag yet.
    </p>

    <!-- Block list -->
    <ul v-else class="space-y-2">
      <li v-for="block in blocks" :key="block.blockId">
        <button
          class="group w-full text-left rounded-lg border border-default
                 hover:border-(--ui-primary)/30 hover:bg-elevated
                 px-4 py-3 transition-all duration-150
                 focus-visible:outline-none focus-visible:ring-2
                 focus-visible:ring-(--ui-primary)"
          @click="goToBlock(block.pagePath, block.blockId)"
        >
          <p class="text-sm text-default leading-relaxed">
            {{ formatContent(block.content) }}
          </p>
          <p class="text-xs text-muted/50 mt-1.5 font-mono truncate">
            {{ block.pagePath }}
          </p>
        </button>
      </li>
    </ul>

    <!-- Back to journal -->
    <div class="mt-auto pt-12">
      <UButton
        variant="ghost"
        color="neutral"
        size="sm"
        icon="i-lucide-arrow-left"
        to="/"
      >
        Back to journal
      </UButton>
    </div>
  </div>
</template>
