import { Querier, TransactionalDatabase, Transaction } from '@platform-modules/db';
import { Table, InferInsertModel, SQL } from 'drizzle-orm';

/** @platform-modules/tenancy core — contract seam over injected RBAC + isolation adapters. */

type TenantStatus = 'active' | 'suspended' | 'pending';
type MembershipStatus = 'active' | 'frozen' | 'pending_approval';
type Tenant = {
    id: string;
    slug: string;
    name: string;
    status: TenantStatus;
    ownerId: string;
    createdAt: Date;
};
type Membership = {
    tenantId: string;
    userId: string;
    roleKey: string;
    status: MembershipStatus;
};
type CreateTenantInput = {
    slug: string;
    name: string;
    ownerId: string;
    status?: TenantStatus;
};
type TenancyStore = {
    createTenant(input: CreateTenantInput): Promise<Tenant>;
    getTenant(tenantId: string): Promise<Tenant | null>;
    getTenantBySlug(slug: string): Promise<Tenant | null>;
    suspendTenant(tenantId: string): Promise<Tenant>;
    addMember(membership: Membership): Promise<Membership>;
    removeMember(tenantId: string, userId: string): Promise<void>;
    setMemberRole(tenantId: string, userId: string, roleKey: string): Promise<Membership>;
    freezeMember(tenantId: string, userId: string): Promise<Membership>;
    listMembers(tenantId: string): Promise<Membership[]>;
    getMembership(tenantId: string, userId: string): Promise<Membership | null>;
};
type RunInTenantFn<S extends Record<string, unknown> = Record<string, never>> = <T>(db: TransactionalDatabase<S>, tenantId: string, fn: (scoped: Transaction<S>) => Promise<T>, opts?: {
    gucName?: string;
    role?: string;
}) => Promise<T>;
type ScopedSelectBuilder = {
    from(table: Table, ...rest: unknown[]): unknown;
};
type SnakeToCamel<S extends string> = S extends `${infer Head}_${infer Tail}` ? `${Head}${Capitalize<SnakeToCamel<Tail>>}` : S;
type ScopedTenantOmitKeys<T extends Table, C extends string> = Extract<keyof InferInsertModel<T>, C | SnakeToCamel<C>>;
type ScopedInsertValues<T extends Table, C extends string> = Omit<InferInsertModel<T>, ScopedTenantOmitKeys<T, C>>;
type ScopedInsertBuilder<TTable extends Table = Table, C extends string = never> = {
    values(values: ScopedInsertValues<TTable, C> | ScopedInsertValues<TTable, C>[]): unknown;
};
type ScopedUpdateBuilder<TTable extends Table = Table, C extends string = never> = {
    set(patch: Partial<ScopedInsertValues<TTable, C>>): unknown;
};
type ScopedQuerier<S extends Record<string, unknown> = Record<string, never>, C extends string = never> = {
    select: (...args: unknown[]) => ScopedSelectBuilder;
    selectDistinct: (...args: unknown[]) => ScopedSelectBuilder;
    selectDistinctOn: (...args: unknown[]) => ScopedSelectBuilder;
    insert: <TTable extends Table>(table: TTable) => ScopedInsertBuilder<TTable, C>;
    update: <TTable extends Table>(table: TTable) => ScopedUpdateBuilder<TTable, C>;
    delete: <TTable extends Table>(table: TTable) => {
        where: (condition?: SQL) => unknown;
    };
};
type IsolationAdapter<S extends Record<string, unknown> = Record<string, never>, C extends string = never> = {
    scopeQuerier(q: Querier<S>, tenantId: string): ScopedQuerier<S, C>;
};
type RbacResolveInput = {
    userId: string;
    tenantId: string;
    roleKey: string;
};
type RbacAdapter = {
    resolveCapabilities(input: RbacResolveInput): Promise<string[]>;
};
declare class TenancyError extends Error {
}
declare class TenantNotFoundError extends TenancyError {
    readonly tenantId: string;
    readonly name = "TenantNotFoundError";
    constructor(message: string, tenantId: string);
}
declare class NotAMemberError extends TenancyError {
    readonly tenantId: string;
    readonly userId: string;
    readonly name = "NotAMemberError";
    constructor(message: string, tenantId: string, userId: string);
}
declare class MembershipFrozenError extends TenancyError {
    readonly tenantId: string;
    readonly userId: string;
    readonly name = "MembershipFrozenError";
    constructor(message: string, tenantId: string, userId: string);
}
declare class ScopeViolationError extends TenancyError {
    readonly tenantId: string;
    readonly name = "ScopeViolationError";
    constructor(message: string, tenantId: string);
}
type TenancyDeps<S extends Record<string, unknown> = Record<string, never>> = {
    store: TenancyStore;
    rbac: RbacAdapter;
    isolation?: IsolationAdapter<S>;
};
type Tenancy<S extends Record<string, unknown> = Record<string, never>> = {
    scopeQuerier?(q: Querier<S>, tenantId: string): ScopedQuerier<S>;
    resolveCapabilities(userId: string, tenantId: string): Promise<string[]>;
    createTenant(input: CreateTenantInput): Promise<Tenant>;
    getTenant(tenantId: string): Promise<Tenant | null>;
    suspendTenant(tenantId: string): Promise<Tenant>;
    addMember(membership: Membership): Promise<Membership>;
    removeMember(tenantId: string, userId: string): Promise<void>;
    setMemberRole(tenantId: string, userId: string, roleKey: string): Promise<Membership>;
    freezeMember(tenantId: string, userId: string): Promise<Membership>;
    listMembers(tenantId: string): Promise<Membership[]>;
};
declare function createMemoryTenancyStore(): TenancyStore;
declare function createTenancy<S extends Record<string, unknown> = Record<string, never>>(deps: TenancyDeps<S>): Tenancy<S>;

export { type CreateTenantInput, type IsolationAdapter, type Membership, MembershipFrozenError, type MembershipStatus, NotAMemberError, type RbacAdapter, type RbacResolveInput, type RunInTenantFn, ScopeViolationError, type ScopedInsertBuilder, type ScopedInsertValues, type ScopedQuerier, type ScopedSelectBuilder, type ScopedTenantOmitKeys, type ScopedUpdateBuilder, type Tenancy, type TenancyDeps, TenancyError, type TenancyStore, type Tenant, TenantNotFoundError, type TenantStatus, createMemoryTenancyStore, createTenancy };
