/**
 * Shared page/block/tag navigation logic used by journal, page, and sidebar
 * components. All navigation goes through this composable so the resolution
 * logic (look up by title → navigate to path, or construct conventional path)
 * is consistent everywhere.
 *
 * Pages that don't exist yet are navigated to by conventional path
 * (`pages/<safe-name>.md`) without creating a file on disk. The file is
 * created lazily when the user types content in the editor (see `[...slug].vue`'s
 * 500ms debounced auto-save).
 */
import { useRouter } from "vue-router"
import { useSettings } from "~/composables/useSettings"
import { createGraphService } from "~/services/graph"
import { useWorkspaceStore } from "~/stores/workspace"

export function usePageNavigation() {
  const router = useRouter()
  const ws = useWorkspaceStore()
  const settings = useSettings()

  /**
   * Navigate to a page by its display name.
   *
   * 1. Look up `title` in the index (titles are always non-empty — indexer
   *    falls back to filename stem when there's no `# Heading 1`).
   * 2. If found, push the page's path.
   * 3. If not found, construct the conventional `{pagesDir}/{safeName}.md`
   *    path and push that. No file is created on disk at this point.
   *
   * @remarks Edge cases & deferred work:
   * - Renaming a page does NOT update existing `[[links]]` in other files.
   *   Backlink confirmation dialog is planned but deferred.
   * - `safeName` strips `<>:?*"\` characters but doesn't handle all Unicode
   *   edge cases (e.g. zero-width spaces, RTL markers). These are rare in
   *    page names but could cause surprising URL paths.
   */
  async function navigateToPage(pageName: string) {
    const db = ws.db
    if (!db) return

    const rows = await db.select<{ path: string }[]>(
      "SELECT path FROM pages WHERE title = ?",
      [pageName],
    )
    if (rows.length > 0) {
      await router.push(`/${rows[0].path}`)
      return
    }

    const pagesDir = await settings.getPagesDir()
    const safeName = pageName.replace(/[/\\:?*"<>|]/g, "_")
    const relativePath = pagesDir
      ? `${pagesDir}/${safeName}.md`
      : `${safeName}.md`
    await router.push(`/${relativePath}`)
  }

  /**
   * Navigate to the page containing the given block ID, with a hash fragment
   * so the page can scroll the target block into view.
   *
   * If the block isn't in the index (e.g. it was deleted), the navigation
   * is silently skipped.
   */
  async function navigateToBlock(blockId: string) {
    const db = ws.db
    if (!db) return
    const graph = createGraphService(db)
    const entity = await graph.getEntity(blockId)
    if (entity?.path) {
      await router.push(`/${entity.path}#block-${blockId}`)
    }
  }

  /**
   * Navigate to a virtual tag aggregation page at `/tag/{tagName}`.
   */
  async function navigateToTag(tag: string) {
    await router.push(`/tag/${encodeURIComponent(tag)}`)
  }

  return { navigateToPage, navigateToBlock, navigateToTag }
}
