import * as react_jsx_runtime from 'react/jsx-runtime';
import { ReactNode } from 'react';
import * as _shield_acl_core from '@shield-acl/core';
import { ACL, User, Scope, Environment, Action, Resource, EvaluationResult, RoleName, Role, Permission } from '@shield-acl/core';

/**
 * Opções de uma checagem no React.
 *
 * - `scope`: override do scope do Provider (checar OUTRO app).
 * - `record`: INSTÂNCIA do recurso (owner, status...) → vira `ctx.resource`.
 * - `environment`: sobrepõe (merge raso) o environment do Provider.
 */
interface CheckOptions<TRecord = unknown> {
    scope?: Scope;
    record?: TRecord;
    environment?: Environment;
}
interface ACLContextValue {
    engine: ACL;
    scope: Scope;
    environment: Environment | undefined;
    user: User | null;
    setUser: (user: User | null) => void;
    /** Revisão reativa do engine (bumpa quando roles mudam). */
    revision: number;
    can: (action: Action, resource?: Resource, opts?: CheckOptions) => boolean;
    evaluate: (action: Action, resource?: Resource, opts?: CheckOptions) => EvaluationResult;
    canAsync: (action: Action, resource?: Resource, opts?: CheckOptions) => Promise<EvaluationResult>;
}
interface ACLProviderProps {
    engine: ACL;
    /** Usuário: use como inicial (não-controlado) ou atualize a prop (controlado). */
    user?: User | null;
    /** Scope default da subárvore. Default "*". */
    scope?: Scope;
    /** Environment default (reativo: MFA/hora/IP). */
    environment?: Environment;
    children: ReactNode;
}
/**
 * Provider do ACL — scope + environment reativos e engine observável.
 */
declare function ACLProvider({ engine, user: userProp, scope, environment, children, }: ACLProviderProps): react_jsx_runtime.JSX.Element;
declare function useACLContext(): ACLContextValue;

/**
 * Primitivo do ACL: expõe tudo do contexto (já escopado) + atalhos.
 *
 * @example
 * const { can, scope, setUser } = useAcl()
 * can("update", "posts", { record: post })
 * can("read", "posts", { scope: "app:outro" })   // override de scope
 */
declare function useAcl(): {
    cannot: (action: Action, resource?: Resource, opts?: CheckOptions) => boolean;
    clearCache: () => void;
    engine: _shield_acl_core.ACL;
    scope: _shield_acl_core.Scope;
    environment: _shield_acl_core.Environment | undefined;
    user: _shield_acl_core.User | null;
    setUser: (user: _shield_acl_core.User | null) => void;
    revision: number;
    can: (action: Action, resource?: Resource, opts?: CheckOptions) => boolean;
    evaluate: (action: Action, resource?: Resource, opts?: CheckOptions) => _shield_acl_core.EvaluationResult;
    canAsync: (action: Action, resource?: Resource, opts?: CheckOptions) => Promise<_shield_acl_core.EvaluationResult>;
};

/**
 * Verificação simples, memoizada. Reavalia quando user/roles/scope/opts mudam.
 *
 * @example
 * const canEdit = useCan("update", "posts", { record: post })
 * const canInB  = useCan("read", "posts", { scope: "app:B" })
 */
declare function useCan(action: Action, resource?: Resource, opts?: CheckOptions): boolean;
declare function useCannot(action: Action, resource?: Resource, opts?: CheckOptions): boolean;

/**
 * Avaliação detalhada (allowed, reason, matchedRule, scope) — para tooltips,
 * telas de admin e "por que negado".
 */
declare function useEvaluate(action: Action, resource?: Resource, opts?: CheckOptions): EvaluationResult;

interface AsyncCheck {
    /** undefined enquanto carrega ou em erro. */
    allowed: boolean | undefined;
    loading: boolean;
    error: unknown;
    refetch: () => void;
}
/**
 * Verificação assíncrona — destrava conditions async, `policySource` e ReBAC
 * na UI (ex.: consulta a banco).
 *
 * @example
 * const { allowed, loading } = useCanAsync("edit", "docs", { record: doc })
 * if (loading) return <Spinner />
 * return allowed ? <Editor /> : <Denied />
 */
declare function useCanAsync(action: Action, resource?: Resource, opts?: CheckOptions): AsyncCheck;

/** Especificação de uma checagem: [action, resource?, options?]. */
type CheckSpec = [Action, Resource?, CheckOptions?];

/**
 * Batch tipado de verificações. Substitui Multiple/Map/Array/Any/All.
 *
 * @example
 * const c = useChecks({
 *   edit: ["update", "posts", { record: post }],
 *   del:  ["delete", "posts", { record: post }],
 * })
 * // c: { edit: boolean; del: boolean }
 * anyOf(c) // alguma
 * allOf(c) // todas
 */
declare function useChecks<K extends string>(map: Record<K, CheckSpec>): Record<K, boolean>;
/** true se QUALQUER checagem passou. */
declare const anyOf: (result: Record<string, boolean>) => boolean;
/** true se TODAS passaram (vazio = true). */
declare const allOf: (result: Record<string, boolean>) => boolean;

interface ResourceBinding<TRecord> {
    resource: Resource;
    record: TRecord;
    can: (action: Action, extra?: Omit<CheckOptions, "record">) => boolean;
    evaluate: (action: Action) => EvaluationResult;
    canRead: () => boolean;
    canCreate: () => boolean;
    canUpdate: () => boolean;
    canDelete: () => boolean;
    canManage: () => boolean;
}
/**
 * Vincula tipo + instância do recurso: a instância entra automaticamente nas
 * conditions (via `record`). Substitui usePermissionHelpers/useResourceACL.
 *
 * @example
 * const acl = useResource("posts", post)
 * acl.canUpdate()          acl.can("publish")
 * acl.can("read", { scope: "app:B" })
 */
declare function useResource<TRecord>(type: Resource, record: TRecord, opts?: {
    scope?: Scope;
    environment?: Environment;
}): ResourceBinding<TRecord>;

/** Roles concedidas ao usuário no scope (com override opcional). */
declare function useGrantedRoles(opts?: {
    scope?: Scope;
}): RoleName[];
interface RoleHierarchy {
    allRoles: RoleName[];
    directRoles: RoleName[];
    inheritedRoles: RoleName[];
    hasRole: (name: RoleName) => boolean;
    hasAnyRole: (names: RoleName[]) => boolean;
    hasAllRoles: (names: RoleName[]) => boolean;
    getRole: (name: RoleName) => Role | undefined;
}
/** Hierarquia de roles do usuário no scope (diretas + herdadas). */
declare function useRoleHierarchy(opts?: {
    scope?: Scope;
}): RoleHierarchy;

interface UserPermissions {
    /** Efetivas no scope (roles resolvidas + diretas). */
    all: Permission[];
    /** Diretas nos grants deste scope (correspondência exata). */
    direct: Permission[];
    byRole: Record<RoleName, Permission[]>;
    denials: Permission[];
    allowances: Permission[];
    actions: string[];
    resources: string[];
    count: number;
}
/** Permissões efetivas do usuário no scope — para telas de admin/debug. */
declare function usePermissions(opts?: {
    scope?: Scope;
}): UserPermissions;

type Cleanup = (() => void) | void;
/**
 * Sincroniza os grants do USUÁRIO ATUAL em tempo real.
 * Suporta push (a notificação traz o user) e pull (sinal → refetch → aplica).
 * A função `subscribe` roda uma vez (montagem) e retorna o unsubscribe.
 *
 * @example
 * // push
 * useUserSync((apply) => socket.on("acl:user", (m) => apply(m.user)))
 * // pull
 * useUserSync((apply) => socket.on("acl:invalidate", async () => apply(await api.me())))
 */
declare function useUserSync(subscribe: (apply: (user: User | null) => void) => Cleanup): void;
/**
 * Sincroniza o CATÁLOGO DE ROLES (afeta todos que as têm).
 * `reload(roles)` chama `engine.setRoles` — 1 notificação, toda a árvore reavalia.
 *
 * @example
 * useRolesSync((reload) => socket.on("acl:roles", async () => reload(await api.roles())))
 */
declare function useRolesSync(subscribe: (reload: (roles: Role[]) => void) => Cleanup): void;
/**
 * Reage ao GANHO/PERDA de uma permissão (ex.: ao perder acesso, redirecionar).
 */
declare function usePermissionEffect(action: Action, resource: Resource | undefined, handlers: {
    onGain?: () => void;
    onLose?: () => void;
}, opts?: CheckOptions): void;

interface CanProps {
    action: Action;
    /** Nome/tipo do recurso (matching). */
    resource?: Resource;
    /** Instância do recurso (conditions ABAC). */
    record?: unknown;
    /** Override do scope do Provider. */
    scope?: Scope;
    environment?: Environment;
    fallback?: ReactNode;
    children: ReactNode;
}
/** Renderiza children quando o usuário TEM a permissão. */
declare function CanBase({ action, resource, record, scope, environment, fallback, children, }: CanProps): react_jsx_runtime.JSX.Element;
/** Renderiza children quando o usuário NÃO tem a permissão. */
declare function Cannot({ action, resource, record, scope, environment, children, }: Omit<CanProps, "fallback">): react_jsx_runtime.JSX.Element;
interface CanBatchProps {
    checks: CheckSpec[];
    fallback?: ReactNode;
    children: ReactNode;
}
/** Renderiza se QUALQUER checagem passar. */
declare function CanAny({ checks, fallback, children }: CanBatchProps): react_jsx_runtime.JSX.Element;
/** Renderiza se TODAS as checagens passarem. */
declare function CanAll({ checks, fallback, children }: CanBatchProps): react_jsx_runtime.JSX.Element;
interface CanAsyncProps extends CanProps {
    pending?: ReactNode;
}
/** Verificação assíncrona com estado de carregamento. */
declare function CanAsync({ action, resource, record, scope, environment, pending, fallback, children, }: CanAsyncProps): react_jsx_runtime.JSX.Element;
/**
 * `<Can>` com composição namespaced: `<Can.Any>`, `<Can.All>`, `<Can.Async>`.
 */
declare const Can: typeof CanBase & {
    Any: typeof CanAny;
    All: typeof CanAll;
    Async: typeof CanAsync;
};

export { type ACLContextValue, ACLProvider, type ACLProviderProps, type AsyncCheck, Can, type CanAsyncProps, type CanBatchProps, type CanProps, Cannot, type CheckOptions, type CheckSpec, type ResourceBinding, type RoleHierarchy, type UserPermissions, allOf, anyOf, useACLContext, useAcl, useCan, useCanAsync, useCannot, useChecks, useEvaluate, useGrantedRoles, usePermissionEffect, usePermissions, useResource, useRoleHierarchy, useRolesSync, useUserSync };
