import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createContext, useContext, useMemo, } from 'react';
import { TelemetryProvider, useUserTelemetry, } from '../../lib/telemetry/index.js';
import { useSeamFont } from '../../lib/seam/use-seam-font.js';
import { useSeamStyles } from '../../lib/seam/use-seam-styles.js';
const defaultQueryClient = new QueryClient();
export const seamComponentsClassName = 'seam-components';
export function SeamProvider({ children, disableTelemetry = false, disableCssInjection = false, disableFontInjection = false, unminifiyCss = false, queryClient, telemetryClient, ...props }) {
    useSeamStyles({ disabled: disableCssInjection, unminified: unminifiyCss });
    useSeamFont({ disabled: disableFontInjection });
    const value = useMemo(() => {
        const context = createSeamContextValue(props);
        if (context.client == null &&
            context.publishableKey == null &&
            context.clientSessionToken == null) {
            return defaultSeamContextValue;
        }
        return context;
    }, [props]);
    if (value.client == null &&
        value.publishableKey == null &&
        value.clientSessionToken == null) {
        throw new Error(`Must provide either a Seam client, clientSessionToken, or a publishableKey.`);
    }
    const { Provider } = seamContext;
    const endpoint = 'endpoint' in props ? props.endpoint : undefined;
    return (_jsx("div", { className: seamComponentsClassName, children: _jsx(TelemetryProvider, { client: telemetryClient ?? globalThis.seamTelemetryClient, disabled: disableTelemetry, endpoint: endpoint, children: _jsx(QueryClientProvider, { client: queryClient ?? globalThis.seamQueryClient ?? defaultQueryClient, children: _jsx(Provider, { value: value, children: _jsx(Wrapper, { children: children }) }) }) }) }));
}
function Wrapper({ children }) {
    useUserTelemetry();
    return _jsx(_Fragment, { children: children });
}
const createDefaultSeamContextValue = () => {
    try {
        if (globalThis.seam == null) {
            return { client: null };
        }
        return createSeamContextValue(globalThis.seam);
    }
    catch (err) {
        // eslint-disable-next-line no-console
        console.warn(err);
        return { client: null };
    }
};
const createSeamContextValue = (options) => {
    if (isSeamProviderPropsWithClient(options)) {
        return options;
    }
    if (isSeamProviderPropsWithClientSessionToken(options)) {
        const { clientSessionToken, ...clientOptions } = options;
        return {
            clientSessionToken,
            clientOptions,
            client: null,
        };
    }
    if (isSeamProviderPropsWithPublishableKey(options)) {
        const { publishableKey, userIdentifierKey, ...clientOptions } = options;
        return {
            publishableKey,
            userIdentifierKey,
            clientOptions,
            client: null,
        };
    }
    return { client: null };
};
const defaultSeamContextValue = createDefaultSeamContextValue();
export const seamContext = createContext(defaultSeamContextValue);
export function useSeamContext() {
    return useContext(seamContext);
}
const isSeamProviderPropsWithClient = (props) => {
    if (!('client' in props))
        return false;
    const { client } = props;
    if (client == null)
        return false;
    const otherNonNullProps = Object.values(props).filter((v) => v != null);
    if (otherNonNullProps.length > 0) {
        throw new InvalidSeamProviderProps(`The client prop cannot be used with ${otherNonNullProps.join(' or ')}.`);
    }
    return true;
};
const isSeamProviderPropsWithPublishableKey = (props) => {
    if (!('publishableKey' in props))
        return false;
    const { publishableKey } = props;
    if (publishableKey == null)
        return false;
    if ('client' in props && props.client != null) {
        throw new InvalidSeamProviderProps('The client prop cannot be used with the publishableKey prop.');
    }
    if ('clientSessionToken' in props && props.clientSessionToken != null) {
        throw new InvalidSeamProviderProps('The clientSessionToken prop cannot be used with the publishableKey prop.');
    }
    return true;
};
const isSeamProviderPropsWithClientSessionToken = (props) => {
    if (!('clientSessionToken' in props))
        return false;
    const { clientSessionToken } = props;
    if (clientSessionToken == null)
        return false;
    if ('client' in props && props.client != null) {
        throw new InvalidSeamProviderProps('The client prop cannot be used with the clientSessionToken prop.');
    }
    if ('publishableKey' in props && props.publishableKey != null) {
        throw new InvalidSeamProviderProps('The publishableKey prop cannot be used with the clientSessionToken prop.');
    }
    if ('userIdentifierKey' in props && props.userIdentifierKey != null) {
        throw new InvalidSeamProviderProps('The userIdentifierKey prop cannot be used with the clientSessionToken prop.');
    }
    return true;
};
class InvalidSeamProviderProps extends Error {
    constructor(message) {
        super(`SeamProvider received invalid props: ${message}`);
        this.name = this.constructor.name;
        Error.captureStackTrace(this, this.constructor);
    }
}
//# sourceMappingURL=SeamProvider.js.map