type TupleToUnionTuple<T extends any[], R extends any[] = [], U = T[number]> = T extends [infer I, ...infer Rest] ? TupleToUnionTuple<Rest, [...R, U], U> | R : R;
type UniqueTuple<T extends any[], Seen extends any[] = []> = T extends [
    infer First,
    ...infer Rest
] ? First extends Seen[number] ? never : UniqueTuple<Rest, [...Seen, First]> : Seen extends [infer I, ...infer Rest] ? Seen : never;

type Mode = 'some' | 'every';
type AnyRecord = Record<string, any>;
type AnyFunction = (...args: any[]) => any;
type ConvertRecordValue<T extends AnyRecord> = T[string] extends [...T[string]] ? {
    [key in keyof T]: T[key];
} : {
    [key in keyof T]: T[key][];
};
type Tuple = [string, ...string[]];
type BaseActions<K extends string> = Record<K, Tuple>;
type BaseConditions<K extends string> = Record<K, AnyRecord>;
type Rules<K extends string, A extends BaseActions<K>, C extends BaseConditions<K>> = {
    [key in K]: {
        [action in A[key][number]]: C[key] extends never ? boolean : C[key] | boolean;
    };
};
type CheckPermissions<Subject extends string, Action extends BaseActions<Subject>[Subject], Conditions extends BaseConditions<Subject>, FunctionMode extends Mode = 'some'> = {
    subject: Subject | UniqueTuple<Subject[]>;
    action: Action[number] | UniqueTuple<TupleToUnionTuple<Action>>;
    conditions?: Conditions[Subject] | ConvertRecordValue<Conditions[Subject]>;
    mode?: FunctionMode;
};
type Signal = {
    signal: () => void;
};
type SubscribedCheckPermissions<Subjects extends string, Action extends BaseActions<Subjects>[Subjects], Conditions extends BaseConditions<Subjects>> = CheckPermissions<Subjects, Action, Conditions> & Signal;
type SubscriberMap<S extends string, A extends string> = {
    [key in S]: {
        [action in A]: Set<Signal['signal']>;
    };
};

declare const factoryPermission: <S extends string, A extends BaseActions<S>, C extends BaseConditions<S>>() => {
    can: ({ subject, action, conditions, mode }: CheckPermissions<S, A[S], C>) => boolean;
    subscribe: () => <Subjects extends S, Action extends A[Subjects]>(props: SubscribedCheckPermissions<Subjects, Action, C>) => boolean;
    update: <Subject extends S>(subject: Subject, action: A[Subject][number], value: Rules<S, A, C>[Subject][A[Subject][number]]) => void;
};

export { type AnyFunction, type AnyRecord, type BaseActions, type BaseConditions, type CheckPermissions, type ConvertRecordValue, type Mode, type Rules, type Signal, type SubscribedCheckPermissions, type SubscriberMap, type Tuple, factoryPermission };
