import { AnyAbility, AnyMongoAbility, ClaimRawRule, MongoQuery, Subject, SubjectRawRule } from "@casl/ability";
import { Channel, RealTimeConnection } from "@feathersjs/transport-commons";
import { Application, HookContext, Id, NextFunction, Query, Service } from "@feathersjs/feathers";
import { AdapterBase } from "@feathersjs/adapter-commons";
import { PartialDeep } from "type-fest";

//#region src/types.d.ts
type AnyData = Record<string, any>;
type Adapter = '@feathersjs/memory' | '@feathersjs/knex' | '@feathersjs/mongodb' | 'feathers-sequelize' | 'feathers-kysely';
interface ServiceCaslOptions {
  availableFields: string[];
}
interface CaslParams<A extends AnyMongoAbility = AnyMongoAbility> {
  ability?: A | ((context: HookContext) => A | Promise<A>);
  casl?: {
    ability: A | (() => A);
  };
}
interface HookBaseOptions<H extends HookContext = HookContext> {
  ability: AnyAbility | ((context: H) => AnyAbility | Promise<AnyAbility>);
  actionOnForbidden: undefined | (() => void);
  checkAbilityForInternal: boolean;
  checkMultiActions: boolean;
  modelName: GetModelName;
  notSkippable: boolean;
  method?: string | ((context: H) => string);
  debug?: boolean;
}
interface CheckBasicPermissionHookOptions<H extends HookContext = HookContext> extends HookBaseOptions<H> {
  checkCreateForData: boolean | ((context: H) => boolean);
  storeAbilityForAuthorize: boolean;
}
type CheckBasicPermissionUtilsOptions<H extends HookContext = HookContext> = Omit<CheckBasicPermissionHookOptions<H>, 'notSkippable'>;
type CheckBasicPermissionHookOptionsExclusive<H extends HookContext = HookContext> = Pick<CheckBasicPermissionHookOptions<H>, Exclude<keyof CheckBasicPermissionHookOptions, keyof HookBaseOptions>>;
type AvailableFieldsOption<H extends HookContext = HookContext> = string[] | ((context: H) => string[] | undefined) | undefined;
interface AuthorizeChannelCommonsOptions<H extends HookContext = HookContext> {
  availableFields: AvailableFieldsOption<H>;
}
interface AuthorizeHookOptions<H extends HookContext = HookContext> extends HookBaseOptions<H>, AuthorizeChannelCommonsOptions<H> {
  adapter: Adapter;
  useUpdateData: boolean;
  usePatchData: boolean;
}
type AuthorizeHookOptionsExclusive<H extends HookContext = HookContext> = Pick<AuthorizeHookOptions<H>, Exclude<keyof AuthorizeHookOptions<H>, keyof HookBaseOptions<H>>>;
type GetModelName<H extends HookContext = HookContext> = string | ((context: H) => string);
type EventName = 'created' | 'updated' | 'patched' | 'removed';
interface ChannelOptions extends AuthorizeChannelCommonsOptions {
  ability: AnyAbility | ((app: Application, connection: RealTimeConnection, data: unknown, context: HookContext) => AnyAbility);
  /** Easy way to disable filtering, default: `false` */
  activated: boolean;
  /** Channel that's used when there occurs an error, default: `['authenticated']` */
  channelOnError: string[];
  /** Prefiltered channels, default: `app.channel(app.channels)` */
  channels?: Channel | Channel[];
  modelName: GetModelName;
  restrictFields: boolean;
  /** change action to use for events. For example: `'receive'`, default: `'get'` */
  useActionName: string | { [e in EventName]?: string };
}
interface GetConditionalQueryOptions {
  actionOnForbidden?(): void;
}
interface HasRestrictingFieldsOptions {
  availableFields: string[] | undefined;
}
interface InitOptions<H extends HookContext = HookContext> {
  defaultAdapter: Adapter;
  authorizeHook: AuthorizeHookOptions<H>;
  channels: ChannelOptions;
}
interface GetMinimalFieldsOptions {
  availableFields?: string[];
  checkCan?: boolean;
}
type Path = string | Array<string | number>;
interface ThrowUnlessCanOptions extends Pick<HookBaseOptions, 'actionOnForbidden' | 'debug'> {
  skipThrow: boolean;
}
interface UtilCheckCanOptions extends ThrowUnlessCanOptions {
  checkGeneral?: boolean;
  useConditionalSelect?: boolean;
}
//#endregion
//#region src/hooks/authorize/authorize.hook.d.ts
declare const authorize: <H extends HookContext = HookContext>(_options?: Partial<AuthorizeHookOptions>) => (context: H, next?: NextFunction) => Promise<any>;
//#endregion
//#region src/hooks/checkBasicPermission.hook.d.ts
declare const checkBasicPermission: <H extends HookContext>(_options?: Partial<CheckBasicPermissionHookOptions>) => ((context: H) => Promise<H>);
//#endregion
//#region src/channels/getChannelsWithReadAbility.d.ts
declare const getChannelsWithReadAbility: (app: Application, data: AnyData, context: HookContext, _options?: Partial<ChannelOptions>) => undefined | Channel | Channel[];
//#endregion
//#region src/channels/channels.utils.d.ts
declare const makeChannelOptions: (app: Application, options?: Partial<ChannelOptions>) => ChannelOptions;
declare const makeDefaultOptions: (options?: Partial<ChannelOptions>) => ChannelOptions;
declare const getAbility: (app: Application, data: Record<string, unknown>, connection: RealTimeConnection, context: HookContext, options: Partial<ChannelOptions>) => undefined | AnyAbility;
declare const getEventName: (method: string) => EventName | undefined;
//#endregion
//#region src/utils/checkBasicPermission.d.ts
declare const checkBasicPermissionUtil: <H extends HookContext>(context: H, _options?: Partial<CheckBasicPermissionUtilsOptions>) => Promise<H>;
//#endregion
//#region src/utils/checkCan.d.ts
declare const checkCan: <S>(ability: AnyAbility, id: Id, method: string, modelName: string, service: Service<S>, providedOptions?: Partial<UtilCheckCanOptions>) => Promise<boolean>;
//#endregion
//#region src/utils/convertRuleToQuery.d.ts
declare const convertRuleToQuery: (rule: SubjectRawRule<any, any, MongoQuery> | ClaimRawRule<any>, options?: GetConditionalQueryOptions) => Query | undefined;
//#endregion
//#region src/utils/couldHaveRestrictingFields.d.ts
declare function couldHaveRestrictingFields(ability: AnyAbility, action: string, subjectType: string): boolean;
//#endregion
//#region src/utils/getAvailableFields.d.ts
declare const getAvailableFields: (context: HookContext, options?: Partial<Pick<AuthorizeChannelCommonsOptions, "availableFields">>) => undefined | string[];
//#endregion
//#region src/utils/getModelName.d.ts
declare const getModelName: (modelName: string | ((context: HookContext) => string) | undefined, context: HookContext) => string;
//#endregion
//#region src/utils/hasRestrictingConditions.d.ts
type Rule = ReturnType<AnyAbility['possibleRulesFor']>[0];
declare const hasRestrictingConditions: (ability: AnyAbility, action: string, modelName: string) => Rule[] | false;
//#endregion
//#region src/utils/hasRestrictingFields.d.ts
declare const hasRestrictingFields: (ability: AnyAbility, action: string, subject: Subject, options?: HasRestrictingFieldsOptions) => boolean | string[];
//#endregion
//#region src/utils/mergeQueryFromAbility.d.ts
declare const mergeQueryFromAbility: <T>(app: Application, ability: AnyAbility, method: string, modelName: string, originalQuery: Query, service: AdapterBase<T>, options: Pick<AuthorizeHookOptions, "adapter">) => Query;
//#endregion
//#region src/utils/simplifyQuery.d.ts
declare const simplifyQuery: <Q extends Query | null>(query: Q, replaceAnd?: boolean, replaceOr?: boolean) => Q;
//#endregion
//#region src/utils/getFieldsForConditions.d.ts
declare const getFieldsForConditions: (ability: AnyAbility, action: string, modelName: string) => string[];
//#endregion
//#region src/utils/getMinimalFields.d.ts
declare const getMinimalFields: (ability: AnyAbility, action: string, subject: Record<string, unknown>, options: GetMinimalFieldsOptions) => string[];
//#endregion
//#region src/initialize.d.ts
declare const initialize: (options?: PartialDeep<InitOptions>) => ((app: Application) => void);
//#endregion
export { Adapter, AnyData, AuthorizeChannelCommonsOptions, AuthorizeHookOptions, AuthorizeHookOptionsExclusive, AvailableFieldsOption, CaslParams, ChannelOptions, CheckBasicPermissionHookOptions, CheckBasicPermissionHookOptionsExclusive, CheckBasicPermissionUtilsOptions, EventName, GetConditionalQueryOptions, GetMinimalFieldsOptions, GetModelName, HasRestrictingFieldsOptions, HookBaseOptions, InitOptions, Path, ServiceCaslOptions, ThrowUnlessCanOptions, UtilCheckCanOptions, authorize, checkBasicPermission, checkBasicPermissionUtil, checkCan, convertRuleToQuery, couldHaveRestrictingFields, initialize as feathersCasl, getAbility, getAvailableFields, getChannelsWithReadAbility, getEventName, getFieldsForConditions, getMinimalFields, getModelName, hasRestrictingConditions, hasRestrictingFields, makeChannelOptions, makeDefaultOptions, mergeQueryFromAbility, simplifyQuery };