import { createAttachmentToolDefinitions } from '../attachmentTools';
import { getRegisteredProvider, registerProvider, hasProvider, listProviders, registerModelDefinition, registerStreamHandler as registerStreamHandlerForKind, setAttachmentToolDefinitionsResolver, getAttachmentToolDefinitions, hasAttachmentToolDefinitionsResolver, getOptionalRegisteredProvider } from './registry';
const registeredPluginIds = new Set();
export const registerProviderPlugin = async (plugin) => {
    const pluginId = plugin?.id;
    if (typeof pluginId !== 'string' || pluginId.trim().length === 0) {
        throw new Error('Provider plugin must include a stable `id` field');
    }
    if (registeredPluginIds.has(pluginId)) {
        return;
    }
    registeredPluginIds.add(pluginId);
    try {
        if (!hasAttachmentToolDefinitionsResolver()) {
            setAttachmentToolDefinitionsResolver(() => createAttachmentToolDefinitions());
        }
        if (typeof plugin.configureAttachmentTools === 'function') {
            await plugin.configureAttachmentTools(() => getAttachmentToolDefinitions());
        }
        const provider = await plugin.createProvider();
        validateProviderForPlugin(pluginId, provider);
        registerProvider(provider);
        if (typeof plugin.getModelDefinition === 'function') {
            const definition = await plugin.getModelDefinition();
            if (definition) {
                validateModelDefinitionForPlugin(pluginId, definition);
                registerModelDefinition(definition);
            }
        }
        if (typeof plugin.getStreamHandler === 'function') {
            const handler = await plugin.getStreamHandler();
            if (handler) {
                registerStreamHandlerForKind(pluginId, handler);
            }
        }
        if (typeof plugin.onRegistered === 'function') {
            const runtime = {
                hasProvider,
                listProviders,
                getAttachmentToolDefinitions,
                getProvider: (kind) => getOptionalRegisteredProvider(kind)
            };
            await plugin.onRegistered(runtime);
        }
    }
    catch (error) {
        registeredPluginIds.delete(pluginId);
        throw error;
    }
};
const validateProviderForPlugin = (pluginId, provider) => {
    if (!provider || typeof provider !== 'object') {
        throw new Error(`Provider plugin "${pluginId}" returned an invalid provider instance`);
    }
    const providerId = provider.metadata?.kind;
    if (!providerId) {
        throw new Error(`Provider plugin "${pluginId}" supplied a provider without a metadata.kind value`);
    }
    if (providerId !== pluginId) {
        throw new Error(`Provider plugin "${pluginId}" must return a provider whose metadata.kind matches the plugin id. Received "${providerId}".`);
    }
};
const validateModelDefinitionForPlugin = (pluginId, definition) => {
    if (!definition || typeof definition !== 'object') {
        throw new Error(`Provider plugin "${pluginId}" returned an invalid model definition`);
    }
    if (!definition.id) {
        throw new Error(`Provider plugin "${pluginId}" returned a model definition without an id`);
    }
    if (definition.id !== pluginId) {
        throw new Error(`Provider plugin "${pluginId}" must return a model definition whose id matches the plugin id. Received "${definition.id}".`);
    }
};
export const getChatProvider = (kind) => {
    return getRegisteredProvider(kind);
};
export * from './types';
export * from './registry';
