import { type ElapsedTime, type Orama, type Result, type SearchParams } from '@orama/orama';
import type { Sitemap, SitemapPage, SitemapSection, SitemapPart, SitemapExport, SitemapSectionData } from "../createSitemap/types.mjs";
/**
 * Base search result structure that can be extended by consumers
 */
export interface BaseSearchResult {
  id?: string;
  title?: string;
  description?: string;
  slug: string;
  path: string;
  sectionTitle: string;
  prefix: string;
  keywords?: string;
  score?: number;
  group?: string;
}
/**
 * Page search result (top-level documentation page)
 */
export interface PageSearchResult extends BaseSearchResult {
  type: 'page';
  page?: string;
  pageKeywords?: string;
  types?: string;
  sections?: string;
  subsections?: string;
}
/**
 * Part search result (component part with API documentation)
 */
export interface PartSearchResult extends BaseSearchResult {
  type: 'part';
  part: string;
  export: string;
  props?: string;
  dataAttributes?: string;
  cssVariables?: string;
}
/**
 * Export search result (exported function/component with API documentation)
 */
export interface ExportSearchResult extends BaseSearchResult {
  type: 'export';
  export: string;
  props?: string;
  dataAttributes?: string;
  cssVariables?: string;
}
/**
 * Section search result (top-level heading within a page)
 */
export interface SectionSearchResult extends BaseSearchResult {
  type: 'section';
  section: string;
}
/**
 * Subsection search result (nested heading within a page)
 */
export interface SubsectionSearchResult extends BaseSearchResult {
  type: 'subsection';
  subsection: string;
}
/**
 * Union type of all common search result variants
 */
export type SearchResult = PageSearchResult | PartSearchResult | ExportSearchResult | SectionSearchResult | SubsectionSearchResult;
export type { SitemapPage, SitemapSection, SitemapPart, SitemapExport, SitemapSectionData, Sitemap };
export type SearchResults = {
  group: string;
  items: SearchResult[];
}[];
/**
 * Options for configuring search behavior
 */
export interface UseSearchOptions {
  /** Function that returns a promise resolving to sitemap data */
  sitemap: () => Promise<{
    sitemap?: Sitemap;
  }>;
  /** Maximum number of default results to show */
  maxDefaultResults?: number;
  /** Search tolerance for fuzzy matching */
  tolerance?: number;
  /** Maximum number of search results */
  limit?: number;
  /** Enable stemming and stopwords (uses English by default) */
  enableStemming?: boolean;
  /** Boost values for different result types and fields */
  boost?: Partial<Record<string, number>>;
  /** Include page categories in groups: "Overview Pages" vs "Pages" */
  includeCategoryInGroup?: boolean;
  /**
   * When true, pages with `audience: 'private'` are included in the search index
   * and default results. Use this for internal deployments where private pages
   * should be discoverable.
   *
   * Typically driven by an environment variable:
   * ```ts
   * showPrivatePages: process.env.SHOW_PRIVATE_PAGES === 'true'
   * ```
   *
   * @default false
   */
  showPrivatePages?: boolean;
  /**
   * When true, excludes `sections` and `subsections` fields from page-type results.
   * The individual section and subsection entries are still created.
   * @default false
   */
  excludeSections?: boolean;
  /**
   * Custom function to convert heading text to URL-friendly slugs.
   * Use this to match your site's slug generation (e.g., rehype-slug).
   * Only applied to section/subsection slugs from the sitemap.
   *
   * If not provided, the original slugs from the sitemap are used as-is.
   *
   * The second parameter `parentTitles` contains the original text of parent headings,
   * useful for pages that concatenate parent context into child heading IDs
   * (e.g., Releases pages: `v1.0.0-rc.0-autocomplete` where the version is prepended).
   *
   * @example
   * ```ts
   * // Simple generateSlug (ignores parent context)
   * generateSlug: (text) => text.toLowerCase().replace(/[^a-z0-9]+/g, '-')
   *
   * // generateSlug with parent concatenation for subsections (e.g., Releases page)
   * generateSlug: (text, parentTitles) => {
   *   const slug = stringToUrl(text);
   *   // If parent is a semver version, prepend it to match rehypeConcatHeadings
   *   if (parentTitles?.[0]?.match(/^v\d+\.\d+\.\d+/)) {
   *     return `${parentTitles[0]}-${slug}`;
   *   }
   *   return slug;
   * }
   * ```
   */
  generateSlug?: (text: string, parentTitles?: string[]) => string;
  /** Custom function to flatten sitemap pages into search results */
  flattenPage?: (page: SitemapPage, sectionData: SitemapSectionData) => SearchResult[];
  /** Custom function to format Orama search hits into typed results */
  formatResult?: <TDocument = unknown>(hit: Result<TDocument>) => SearchResult;
}
export type SearchBy<T> = Pick<SearchParams<Orama<T>>, 'facets' | 'groupBy' | 'limit' | 'offset' | 'where'>;
/**
 * Return value from useSearch hook
 */
export interface UseSearchResult<T> {
  /**
   * Current search results
   */
  results: {
    results: SearchResults;
    count: number;
    elapsed: ElapsedTime;
  };
  /**
   * Whether the search index is ready
   */
  isReady: boolean;
  /**
   * Function to update search value and get new results
   */
  search: (value: string, by?: SearchBy<T>) => Promise<void>;
  /**
   * Default results shown when search is empty
   */
  defaultResults: {
    results: SearchResults;
    count: number;
    elapsed: ElapsedTime;
  };
  /**
   * Build a URL from a search result
   * Handles path normalization and hash fragments for different result types
   */
  buildResultUrl: (result: SearchResult) => string;
}