import { z } from 'zod';
import { Result, SchemaError } from '@unkey/error';

/**
 *  Here, the Result type is still a generic type that takes in a type T that extends the Actions
 *  type. It uses a mapped type to iterate over the keys of the T object and create a string literal
 *  union of all the possible combinations of resourceId:action strings. The [keyof T] at the end of
 *  the type definition means that the resulting type is a union of all the possible string literal
 *  unions created by the mapped type.
 *
 *  In the example, we define a new MyActions type that matches the Actions type from the original
 *  question, and then use the Result type to transform it into the desired MyResult type. The
 *  resulting type is:
 *  "team.read" | "team.write" | "domain.dns.read_record" | "domain.dns.create_record"
 *
 *
 *
 * @example
 * type Resources = {
 *   team: 'read' | 'write';
 *   domain: {
 *     dns: "read_record" | "create_record"
 *   }
 * };
 *
 * type MyResult = Flatten<Resources>; // type MyResult = "team.read" | "team.write" | "domain.dns.read_record" | "domain.dns.create_record"
 *
 * You can also choose a custom delimiter:
 * @example
 * Flatten<Resources, "::">
 */
type Flatten<T extends Record<string, unknown>, Delimiter extends string = "."> = {
    [K in keyof T]: T[K] extends Record<string, unknown> ? `${string & K}${Delimiter}${T[K] extends infer U ? U extends Record<string, unknown> ? Flatten<U, Delimiter> : string & U : never}` : `${string & K}${Delimiter}${string & T[K]}`;
}[keyof T];

/**
 * The database takes care of isolating roles between workspaces.
 * That's why we can assume the highest scope of a role is an `api` or later `gateway`
 *
 * role identifiers can look like this:
 * - `api_id.xxx`
 * - `gateway_id.xxx`
 *
 */

declare function buildIdSchema(prefix: string): z.ZodEffects<z.ZodString, string, string>;
declare const apiId: z.ZodEffects<z.ZodString, string, string>;
declare const ratelimitNamespaceId: z.ZodEffects<z.ZodString, string, string>;
declare const apiActions: z.ZodEnum<["read_api", "create_api", "delete_api", "update_api", "create_key", "update_key", "delete_key", "encrypt_key", "decrypt_key", "read_key"]>;
declare const ratelimitActions: z.ZodEnum<["limit", "create_namespace", "read_namespace", "update_namespace", "delete_namespace"]>;
type Resources = {
    [resourceId in `api.${z.infer<typeof apiId>}`]: z.infer<typeof apiActions>;
} & {
    [resourceId in `ratelimit.${z.infer<typeof ratelimitNamespaceId>}`]: z.infer<typeof ratelimitActions>;
};
type UnkeyPermission = Flatten<Resources> | "*";
/**
 * Validation for roles used for our root keys
 */
declare const unkeyPermissionValidation: z.ZodEffects<z.ZodType<UnkeyPermission, z.ZodTypeDef, UnkeyPermission>, UnkeyPermission, UnkeyPermission>;

type PermissionQuery<R extends string = string> = R | {
    and: Array<PermissionQuery<R> | undefined>;
    or?: never;
} | {
    and?: never;
    or: Array<PermissionQuery<R> | undefined>;
};
declare const permissionQuerySchema: z.ZodType<PermissionQuery>;
declare function or<R extends string = string>(...args: Array<PermissionQuery<R> | undefined>): PermissionQuery<R>;
declare function and<R extends string = string>(...args: Array<PermissionQuery<R> | undefined>): PermissionQuery<R>;
declare function buildQuery<R extends string = string>(fn: (ops: {
    or: typeof or<R>;
    and: typeof and<R>;
}) => PermissionQuery<R>): PermissionQuery;
/**
 * buildUnkeyQuery is preloaded with out available roles and ensures typesafety for root key validation
 */
declare const buildUnkeyQuery: (fn: (ops: {
    or: (...args: (PermissionQuery<UnkeyPermission> | undefined)[]) => PermissionQuery<UnkeyPermission>;
    and: (...args: (PermissionQuery<UnkeyPermission> | undefined)[]) => PermissionQuery<UnkeyPermission>;
}) => PermissionQuery<UnkeyPermission>) => PermissionQuery;

declare class RBAC {
    evaluatePermissions(q: PermissionQuery, roles: string[]): Result<{
        valid: true;
        message?: never;
    } | {
        valid: false;
        message: string;
    }, SchemaError>;
    validateQuery(q: PermissionQuery): Result<{
        query: PermissionQuery;
    }>;
    private evaluateQueryV1;
}

export { type Flatten, type PermissionQuery, RBAC, type Resources, type UnkeyPermission, and, apiActions, buildIdSchema, buildQuery, buildUnkeyQuery, or, permissionQuerySchema, ratelimitActions, unkeyPermissionValidation };
