import * as react from 'react';
import { ReactNode } from 'react';
import * as react_jsx_runtime from 'react/jsx-runtime';
import { UseBoundStore, StoreApi } from 'zustand';

/**
 * Branded organization identifiers.
 *
 * Every organization carries TWO distinct ID values that are both plain
 * strings at runtime but mean different things:
 *
 * - WorkOS organization id (`org_...`) -- the auth/JWT identity. Used for API
 *   requests, SSE headers, and org-scoped query keys.
 * - Supabase organization id (UUID) -- the database key. Used for
 *   `.eq('organization_id', ...)` queries and RLS scoping.
 *
 * They are not interchangeable, yet both are `string` -- so a swap compiles
 * cleanly and fails silently (zero rows on the Supabase side, cross-pollinated
 * cache keys on the API side). These brands make the two non-assignable to one
 * another, turning that silent footgun into a compile error at the sink.
 *
 * Mint a brand only through the `as*` factories below: they are the single
 * validate-and-tag boundary (compile-time brand + runtime format check). The
 * type predicates double as the cast, so no raw `as` cast is needed anywhere.
 *
 * Lives on the published `@repo/core` / `@repo/core/auth` surface so the UI,
 * the API, and the dogfooding `@repo/elevasis-*` packages can all use it.
 */
declare const supabaseOrgIdBrand: unique symbol;
declare const workOsOrgIdBrand: unique symbol;
/** A Supabase organization id (UUID) -- the database key for RLS-scoped rows. */
type SupabaseOrgId = string & {
    readonly [supabaseOrgIdBrand]: true;
};
/** A WorkOS organization id (`org_...`) -- the auth identity for API/SSE/query keys. */
type WorkOsOrgId = string & {
    readonly [workOsOrgIdBrand]: true;
};

/**
 * Organization Membership types based on WorkOS API
 */
interface OrganizationMembership {
    object: 'organization_membership';
    id: string;
    userId: string;
    organizationId: string;
    role: {
        slug: string;
    };
    status: 'active' | 'inactive';
    createdAt: string;
    updatedAt: string;
}
/**
 * Extended membership with user and organization details for UI
 */
interface MembershipWithDetails extends OrganizationMembership {
    user?: {
        id: string;
        email: string;
        firstName?: string;
        lastName?: string;
        profilePictureUrl?: string;
    };
    organization?: {
        id: string;
        name: string;
        workos_org_id: string;
        primaryDomain?: string;
        is_test?: boolean;
        status?: string;
        metadata?: Record<string, unknown>;
        config?: Record<string, unknown>;
    };
}

/**
 * The value exposed by OrganizationProvider to all consumers.
 */
interface OrganizationContextValue {
    /** WorkOS organization ID of the currently selected organization. */
    currentWorkOSOrganizationId: WorkOsOrgId | null;
    /** Supabase (UUID) organization ID of the currently selected organization. */
    currentSupabaseOrganizationId: SupabaseOrgId | null;
    /** Full membership record for the currently selected organization. */
    currentMembership: MembershipWithDetails | null;
    /** All memberships for the authenticated user. */
    memberships: MembershipWithDetails[];
    /** True while the initial membership list is being fetched. */
    isInitializing: boolean;
    /** True while a subsequent org switch / refresh is in flight. */
    isOrgRefreshing: boolean;
    /** Error message if the membership fetch or org switch failed. */
    error: string | null;
    /**
     * Switch the active organization.
     *
     * Persists the selection to `last_visited_org` on the user profile and
     * invalidates all org-scoped TanStack Query cache entries.
     *
     * @param workosOrgId - WorkOS organization ID to switch to.
     * @param options.persist - Set false for programmatic single-org pinning.
     */
    switchOrganization: (workosOrgId: string, options?: {
        persist?: boolean;
    }) => void;
    /**
     * Re-fetch memberships and retry org selection after an error.
     */
    retry: () => Promise<void>;
}
declare const OrganizationContext: react.Context<OrganizationContextValue | null>;
/**
 * Consumes the nearest OrganizationProvider.
 *
 * @throws {Error} If called outside of an OrganizationProvider tree.
 */
declare function useOrganization(): OrganizationContextValue;

type ApiRequestFn = <T>(endpoint: string, options?: RequestInit) => Promise<T>;
/**
 * Provides organization state to its subtree via React Context.
 *
 * Must be rendered inside:
 * - ProfileProvider (needs useProfile for last_visited_org preference)
 * - A TanStack QueryClientProvider (needs useQueryClient for cache invalidation)
 *
 * Receives apiRequest as a prop so it can mount before ElevasisServiceProvider.
 *
 * Behaviors:
 * - Fetches all memberships for the authenticated user via GET /memberships/my-memberships
 * - Selects the active org by priority: WorkOS org ID > saved preference > first membership
 * - Persists explicit multi-org switches to PATCH /users/me { lastVisitedOrg }
 * - Clears all state when the user signs out (user becomes null)
 */
declare function OrganizationProvider({ apiRequest, children }: {
    apiRequest: ApiRequestFn;
    children: ReactNode;
}): react.FunctionComponentElement<react.ProviderProps<OrganizationContextValue | null>>;

type Organization = NonNullable<MembershipWithDetails['organization']>;
interface OrganizationSwitcherProps {
    currentOrganization: Organization | undefined;
    memberships: MembershipWithDetails[];
    isLoading: boolean;
    onSwitch: (workosOrgId: string) => Promise<void>;
}
declare function OrganizationSwitcher({ currentOrganization, memberships, isLoading, onSwitch }: OrganizationSwitcherProps): react_jsx_runtime.JSX.Element;

/**
 * Self-wired OrganizationSwitcher that internally handles both the WorkOS JWT update
 * (via AuthKit switchToOrganization) and the provider state update (via switchOrganization).
 *
 * Drop-in replacement for a custom onSwitch handler in most apps. If the app needs
 * post-switch side effects (e.g. navigating away from an org-scoped route), keep that
 * logic app-local and call useOrganization().switchOrganization directly.
 */
declare function OrganizationSwitcherConnected(): react_jsx_runtime.JSX.Element;

interface OrganizationsState {
    currentWorkOSOrganizationId: WorkOsOrgId | null;
    currentSupabaseOrganizationId: SupabaseOrgId | null;
    currentMembership: MembershipWithDetails | null;
    isInitializing: boolean;
    isOrgRefreshing: boolean;
    error: string | null;
}
interface OrganizationsActions {
    setCurrentWorkOSOrganizationId: (workOSorgId: WorkOsOrgId | null) => void;
    setCurrentMembership: (membership: MembershipWithDetails | null) => void;
    setOrganizationsInitializing: (initializing: boolean) => void;
    setOrganizationsLoading: (loading: boolean) => void;
    setOrganizationsError: (error: string | null) => void;
}
interface OrganizationsSlice extends OrganizationsActions {
    organizations: OrganizationsState;
}

/**
 * Type for Zustand's immer set function.
 * This is a simplified version that works with immer middleware.
 * The replace parameter uses false | undefined to match Zustand's type for immer mutation support.
 */
type ImmerSet<T> = (partial: T | Partial<T> | ((state: T) => void), replace?: false | undefined, action?: string) => void;
/**
 * Creates the organizations slice for Zustand store.
 *
 * Usage in app:
 * ```typescript
 * import { createOrganizationsSlice } from '@repo/ui/organization'
 *
 * // Define AppState that extends OrganizationsSlice
 * interface AppState extends OrganizationsSlice {
 *   // other slices...
 * }
 *
 * // Pass the slice creator to your store
 * const useAppStore = create<AppState>()(
 *   devtools(
 *     immer((...a) => ({
 *       ...createOrganizationsSlice(...a),
 *       // other slices...
 *     }))
 *   )
 * )
 * ```
 *
 * Note: The slice creator accepts set/get/store from any Zustand store
 * that extends OrganizationsSlice. It returns the slice state and actions.
 */
declare const createOrganizationsSlice: <TAppState extends OrganizationsSlice>(set: ImmerSet<TAppState>, _get: () => TAppState, _store: unknown) => OrganizationsSlice;

/**
 * Factory function to create a useOrganizations hook for your app's store.
 *
 * Usage in app:
 * ```typescript
 * import { createUseOrganizations } from '@repo/ui/organization'
 * import { useAppStore } from './zustand/store'
 *
 * export const useOrganizations = createUseOrganizations(useAppStore)
 * ```
 *
 * This pattern allows the shared package to provide the hook logic
 * while each app provides its own store instance.
 */
declare function createUseOrganizations<TStore extends OrganizationsSlice>(useStore: UseBoundStore<StoreApi<TStore>>): () => {
    setCurrentWorkOSOrganizationId: (workOSorgId: WorkOsOrgId | null) => void;
    setCurrentMembership: (membership: MembershipWithDetails | null) => void;
    setOrganizationsInitializing: (initializing: boolean) => void;
    setOrganizationsLoading: (loading: boolean) => void;
    setOrganizationsError: (error: string | null) => void;
    organizations: OrganizationsState;
    currentWorkOSOrganizationId: WorkOsOrgId | null;
    currentSupabaseOrganizationId: SupabaseOrgId | null;
    currentMembership: MembershipWithDetails | null;
    isInitializing: boolean;
    isOrgRefreshing: boolean;
    error: string | null;
};

/**
 * Type for the useOrganizations hook return value
 */
interface UseOrganizationsReturn {
    currentWorkOSOrganizationId: WorkOsOrgId | null;
    currentMembership: MembershipWithDetails | null;
    setCurrentWorkOSOrganizationId: (id: WorkOsOrgId | null) => void;
    setCurrentMembership: (membership: MembershipWithDetails | null) => void;
    setOrganizationsInitializing: (initializing: boolean) => void;
    setOrganizationsLoading: (loading: boolean) => void;
    setOrganizationsError: (error: string | null) => void;
    organizations: {
        isInitializing: boolean;
        isOrgRefreshing: boolean;
        error: string | null;
    };
}
/**
 * Type for the useApiClient hook return value
 */
interface UseApiClientReturn {
    apiRequest: <T = unknown>(path: string, options?: RequestInit) => Promise<T>;
}
/**
 * Return type for useOrgInitialization hook
 */
interface UseOrgInitializationReturn {
    memberships: MembershipWithDetails[];
    isInitializing: boolean;
    isLoading: boolean;
    isInitialized: boolean;
    error: string | null;
    currentOrganization: MembershipWithDetails['organization'] | null;
    retry: () => Promise<void>;
}
/**
 * Factory function to create a useOrgInitialization hook for your app.
 *
 * Usage in app:
 * ```typescript
 * import { createUseOrgInitialization } from '@repo/ui/organization'
 * import { useOrganizations } from './hooks/useOrganizations'
 * import { useApiClient } from './api/hooks/useApiClient'
 *
 * export const useOrgInitialization = createUseOrgInitialization(
 *   useOrganizations,
 *   useApiClient
 * )
 * ```
 *
 * This pattern allows the shared package to provide the hook logic
 * while each app provides its own hook instances.
 */
declare function createUseOrgInitialization(useOrganizations: () => UseOrganizationsReturn, useApiClient: () => UseApiClientReturn): () => UseOrgInitializationReturn;

export { OrganizationContext, OrganizationProvider, OrganizationSwitcher, OrganizationSwitcherConnected, createOrganizationsSlice, createUseOrgInitialization, createUseOrganizations, useOrganization };
export type { MembershipWithDetails, OrganizationContextValue, OrganizationsActions, OrganizationsSlice, OrganizationsState, UseApiClientReturn, UseOrgInitializationReturn, UseOrganizationsReturn };
