declare module "mongoose-mpath" {
  import { Schema, Document, Types } from "mongoose"

  export interface MpathOptions {
    /**
     * Name of the model to use for queries
     */
    modelName?: string

    /**
     * Field name to use for path storage. Defaults to 'path'
     */
    pathSeparator?: string

    /**
     * Separator to use for path storage. Defaults to ','
     */
    onDelete?: "REPARENT" | "DELETE"

    /**
     * Action to take when parent is deleted
     * REPARENT: Parent's children become children of parent's parent
     * DELETE: Delete all children (default)
     */
    pathField?: string

    /**
     * Field name for parent_id reference. Defaults to 'parent'
     */
    parentField?: string

    /**
     * Type to use for _id fields. Defaults to mongoose.Schema.Types.ObjectId
     */
    idType?: typeof Schema.Types.String | typeof Schema.Types.ObjectId

    /**
     * Whether to index the path. Defaults to true
     */
    indexPath?: boolean
  }

  export interface MpathMethods<T extends Document> {
    /**
     * Gets all children of the document, returns a promise
     */
    getAllChildren(filters?: Record<string, any>): Promise<T[]>

    /**
     * Gets immediate children of the document, returns a promise
     */
    getImmediateChildren(filters?: Record<string, any>): Promise<T[]>

    /**
     * Gets children tree of the document
     */
    getChildrenTree(options?: {
      filter?: Record<string, any>
      fields?: string | string[]
      options?: Record<string, any>
      minLevel?: number
      maxLevel?: number
      population?: string[]
    }): Promise<T[]>

    /**
     * Gets ancestors of the document
     */
    getAncestors(filters?: Record<string, any>): Promise<T[]>

    /**
     * Gets parent of the document
     */
    getParent(): Promise<T | null>
  }

  const MpathPlugin: <T extends Document>(
    schema: Schema,
    options?: MpathOptions,
  ) => void

  export default MpathPlugin
}
