import {CrossDatasetType} from '@sanity/types'
import {ObjectSchemaType} from '@sanity/types'
import {Observable} from 'rxjs'
import {SanityClient} from '@sanity/client'
import {SanityDocumentLike} from '@sanity/types'
import {Schema} from '@sanity/types'
import {SchemaType} from '@sanity/types'

/** @internal */
export declare const createSearch: SearchStrategyFactory<TextSearchResults | WeightedSearchResults>

/**
 * @internal
 */
export declare const getSearchableTypes: (schema: Schema) => ObjectSchemaType[]

/**
 * @internal
 */
declare interface SearchFactoryOptions {
  maxDepth?: number
  filter?: string
  params?: Record<string, unknown>
  tag?: string
  unique?: boolean
  unstable_enableNewSearch?: boolean
}

/**
 * @internal
 */
declare interface SearchHit {
  hit: SanityDocumentLike
}

/**
 * @internal
 */
declare type SearchOptions = {
  __unstable_extendedProjection?: string
  maxDepth?: number
  comments?: string[]
  includeDrafts?: boolean
  skipSortByScore?: boolean
  sort?: SearchSort[]
  cursor?: string
  limit?: number
  isCrossDataset?: boolean
}

/**
 * @internal
 */
declare type SearchSort = {
  direction: SortDirection
  field: string
  mapWith?: string
}

/**
 * @internal
 */
declare interface SearchStory {
  path: string
  score: number
  why: string
}

/**
 * @internal
 */
declare type SearchStrategyFactory<TResult extends TextSearchResults | WeightedSearchResults> = (
  types: (SchemaType | CrossDatasetType)[],
  client: SanityClient,
  commonOpts: SearchFactoryOptions,
) => (searchTerms: string | SearchTerms, searchOpts?: SearchOptions) => Observable<TResult>

/**
 * @internal
 */
declare interface SearchTerms<Type extends SchemaType | CrossDatasetType = SchemaType> {
  filter?: string
  params?: Record<string, unknown>
  query: string
  types: Type[]
}

/**
 * @internal
 */
declare type SortDirection = 'asc' | 'desc'

/**
 * @internal
 */
declare interface TextSearchResults {
  type: 'text'
  hits: SearchHit[]
  nextCursor?: string
}

/** @internal */
export declare function useSearchMaxFieldDepth(overrideClient?: SanityClient): number

/**
 * @internal
 */
declare interface WeightedHit extends SearchHit {
  resultIndex: number
  score: number
  stories: SearchStory[]
}

/**
 * @internal
 */
declare interface WeightedSearchResults {
  type: 'weighted'
  hits: WeightedHit[]
  nextCursor?: never
}

export {}
