import {Rule} from '@sanity/types'
import {SanityDocument} from '@sanity/types'
import {Schema} from '@sanity/types'
import {SchemaType} from '@sanity/types'
import {SchemaType as SchemaType_2} from 'groq-js'
import {SchemaTypeDefinition} from '@sanity/types'
import {SchemaValidationProblem} from '@sanity/types'
import {SchemaValidationProblemGroup} from '@sanity/types'
import {SetSynchronization} from '@sanity/descriptors'
import {SynchronizationRequest} from '@sanity/descriptors'
import {SynchronizationResult} from '@sanity/descriptors'

export declare const ALL_FIELDS_GROUP_NAME = 'all-fields'

export declare const builtinTypes: (
  | {
      title: string
      name: string
      type: string
      fields: {
        name: string
        type: string
        title: string
      }[]
    }
  | {
      name: string
      title: string
      type: string
      fieldsets: {
        name: string
        title: string
        description: string
      }[]
      fields: (
        | {
            name: string
            type: string
            title: string
            readOnly: boolean
            fieldset?: undefined
            hidden?: undefined
          }
        | {
            name: string
            type: string
            title: string
            readOnly?: undefined
            fieldset?: undefined
            hidden?: undefined
          }
        | {
            name: string
            type: string
            title: string
            readOnly: boolean
            fieldset: string
            hidden?: undefined
          }
        | {
            name: string
            type: string
            readOnly: boolean
            hidden: boolean
            fieldset: string
            title?: undefined
          }
      )[]
      preview: {
        select: {
          id: string
          title: string
          mimeType: string
          size: string
          media: string
        }
        prepare(doc: Partial<SanityDocument>): {
          title: {}
          media: {
            media?: {} | undefined
            asset: {
              _ref: unknown
            }
          }
          subtitle: string
        }
      }
      orderings: {
        title: string
        name: string
        by: {
          field: string
          direction: string
        }[]
      }[]
    }
  | {
      name: string
      title: string
      type: string
      fieldsets: {
        name: string
        title: string
        description: string
      }[]
      fields: (
        | {
            name: string
            type: string
            title: string
            readOnly: boolean
            fieldset?: undefined
            hidden?: undefined
          }
        | {
            name: string
            type: string
            title: string
            readOnly?: undefined
            fieldset?: undefined
            hidden?: undefined
          }
        | {
            name: string
            type: string
            title: string
            readOnly: boolean
            fieldset: string
            hidden?: undefined
          }
        | {
            name: string
            type: string
            readOnly: boolean
            hidden: boolean
            fieldset: string
            title?: undefined
          }
      )[]
      preview: {
        select: {
          title: string
          path: string
          mimeType: string
          size: string
        }
        prepare(doc: Record<string, any>): {
          title: any
          subtitle: string
        }
      }
      orderings: {
        title: string
        name: string
        by: {
          field: string
          direction: string
        }[]
      }[]
    }
  | {
      name: string
      title: string
      type: string
      fields: {
        name: string
        type: string
        validation: (Rule: Rule) => Rule
      }[]
    }
  | {
      name: string
      title: string
      type: string
      fieldsets: {
        name: string
        title: string
        options: {
          collapsable: boolean
        }
      }[]
      fields: (
        | {
            name: string
            type: string
            title?: undefined
            fieldset?: undefined
            readOnly?: undefined
          }
        | {
            name: string
            title: string
            type: string
            fieldset: string
            readOnly?: undefined
          }
        | {
            name: string
            title: string
            type: string
            readOnly: boolean
            fieldset?: undefined
          }
      )[]
    }
)[]

export declare function createSchemaFromManifestTypes(schemaDef: {
  name: string
  types: unknown[]
}): Schema_2

export declare const DEFAULT_MAX_FIELD_DEPTH = 5

export declare class DescriptorConverter {
  cache: WeakMap<Schema, SetSynchronization<RegistryType>>
  /**
   * Returns a synchronization object for a schema.
   *
   * This is automatically cached in a weak map.
   */
  get(
    schema: Schema,
    opts?: {
      /**
       * If present, this will use an idle scheduler which records duration into this array.
       * This option will be ignored if the `scheduler` option is passed in.
       **/
      pauseDurations?: number[]
      /** An explicit scheduler to do the work. */
      scheduler?: Scheduler
    },
  ): Promise<SetSynchronization<RegistryType>>
}

export declare function extractSchema(
  schemaDef: Schema,
  extractOptions?: ExtractSchemaOptions,
): SchemaType_2

declare interface ExtractSchemaOptions {
  enforceRequiredFields?: boolean
}

/**
 * @internal
 */
export declare type FIXME = any

/**
 * @internal
 */
export declare function groupProblems(types: SchemaTypeDefinition[]): SchemaValidationProblemGroup[]

export declare const isActionEnabled: (schemaType: SchemaType, action: string) => boolean

declare interface Options {
  transformTypeVisitors?: (visitors: typeof typeVisitors) => Partial<typeof typeVisitors>
  transformCommonVisitors?: (visitors: any[]) => any[]
}

/**
 * @internal
 */
export declare type ProblemPath = ProblemPathSegment[]

/**
 * @internal
 */
export declare interface ProblemPathPropertySegment {
  kind: 'property'
  name: string
}

/**
 * @internal
 */
export declare type ProblemPathSegment = ProblemPathTypeSegment | ProblemPathPropertySegment

/**
 * @internal
 */
export declare interface ProblemPathTypeSegment {
  kind: 'type'
  type: string
  name: string
}

/**
 * Returns the next request that should be generated for synchronizing the
 * schema, based on the previous response from the /synchronize endpoint.
 *
 * @param response - The previous response, or `null` if it's the first request.
 * @returns The next request, or `null` if it's been fully synchronized.
 */
export declare function processSchemaSynchronization(
  sync: SetSynchronization<RegistryType>,
  response: SchemaSynchronizationResult | null,
): SchemaSynchronizationRequest | null

declare type RegistryType = 'sanity.schema.registry'

/**
 * @internal
 */
export declare function resolveSearchConfig(type: any, maxDepth?: number): any

export declare function resolveSearchConfigForBaseFieldPaths(type: any, maxDepth?: number): any

/** The scheduler is capable of executing work in different ways. */
declare type Scheduler = {
  map<T, U>(arr: T[], fn: (val: T) => U): Promise<U[]>
  forEach<T>(arr: T[], fn: (val: T) => void): Promise<void>
  forEachIter<T>(iter: Iterable<T>, fn: (val: T) => void): Promise<void>
}

/**
 * @beta
 */
declare class Schema_2 {
  #private
  _original: {
    name: string
    types: any[]
    parent?: Schema_2
  }
  _registry: {
    [typeName: string]: any
  }
  static compile(schemaDef: any): Schema_2
  constructor(schemaDef: any)
  get name(): string
  /**
   * Returns the parent schema.
   */
  get parent(): Schema_2 | undefined
  get(name: string): any
  has(name: string): boolean
  getTypeNames(): string[]
  getLocalTypeNames(): string[]
}

export declare type SchemaSynchronizationRequest = SynchronizationRequest

export declare type SchemaSynchronizationResult = SynchronizationResult

/**
 * @internal
 */
declare interface SchemaValidationResult {
  severity: 'warning' | 'error'
  message: string
  helpId?: string
}
export {SchemaValidationResult as Problem}
export {SchemaValidationResult as ValidationResult}

declare const typeVisitors: {
  array: (typeDef: any, visitorContext: any) => any
  object: (typeDef: any, visitorContext: any) => any
  slug: (typeDef: any, visitorContext: any) => any
  file: (typeDef: any, visitorContext: any) => any
  image: (typeDef: any, visitorContext: any) => any
  block: typeof validateBlockType
  document: (typeDefinition: any, visitorContext: any) => any
  reference: (typeDef: any, visitorContext: any) => any
  crossDatasetReference: (typeDef: any, visitorContext: any) => any
  globalDocumentReference: (typeDef: any, visitorContext: any) => any
}

/**
 * @internal
 */
export declare interface TypeWithProblems {
  path: ProblemPath
  problems: SchemaValidationResult[]
}

declare function validateBlockType(
  typeDef: any,
  visitorContext: any,
): {
  marks: any
  styles: any
  name: any
  of: any
  _problems: SchemaValidationResult[]
}

/**
 * Ensure that the provided value is a valid Media Library asset aspect that can be safely deployed.
 *
 * @internal
 */
export declare function validateMediaLibraryAssetAspect(
  maybeAspect: unknown,
): [isValidMediaLibraryAspect: boolean, validationErrors: SchemaValidationProblem[][]]

/**
 * @internal
 */
export declare function validateSchema(
  schemaTypes: FIXME,
  {transformTypeVisitors, transformCommonVisitors}?: Options,
): {
  get(typeName: string): any
  has(typeName: string): boolean
  getTypeNames(): string[]
  getTypes(): any[]
  toJSON(): any[]
}

export declare class ValidationError extends Error {
  problems: SchemaValidationProblemGroup[]
  constructor(problems: SchemaValidationProblemGroup[])
}

export {}
