"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VectorDatabaseConfigForm = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
/**
 * Vector Database Configuration Form Component
 *
 * This component provides a unified UI for configuring vector databases with built-in
 * validation using the same rules as the backend validation services.
 */
const react_1 = require("react");
const vector_model_dimensions_1 = require("./vector-model-dimensions");
/**
 * Vector Database Configuration Form
 */
const VectorDatabaseConfigForm = ({ initialConfig, embeddingModel, onConfigChange }) => {
    // Default initial config
    const defaultConfig = {
        type: 'pinecone',
        collection: '',
        dimensions: embeddingModel ? vector_model_dimensions_1.MODEL_DIMENSIONS[embeddingModel] || 1536 : 1536,
        url: '',
        apiKey: '',
        options: {}
    };
    // State management
    const [config, setConfig] = (0, react_1.useState)(initialConfig || defaultConfig);
    const [errors, setErrors] = (0, react_1.useState)({});
    const [touched, setTouched] = (0, react_1.useState)({});
    /**
     * Handles changes to the configuration
     */
    const handleConfigChange = (field, value) => {
        // Handle nested options fields
        if (field.includes('.')) {
            const [parent, child] = field.split('.');
            if (parent === 'options') {
                setConfig(prevConfig => ({
                    ...prevConfig,
                    options: {
                        ...prevConfig.options,
                        [child]: value
                    }
                }));
            }
        }
        else {
            // Handle top-level fields
            setConfig(prevConfig => ({
                ...prevConfig,
                [field]: value
            }));
        }
        // Mark field as touched
        setTouched(prev => ({
            ...prev,
            [field]: true
        }));
    };
    /**
     * Validates the configuration when it changes
     */
    (0, react_1.useEffect)(() => {
        // Validate the configuration
        const validationErrors = validateConfig(config, embeddingModel);
        setErrors(validationErrors);
        // Notify parent about the configuration change
        const isValid = Object.keys(validationErrors).length === 0;
        onConfigChange(config, isValid);
    }, [config, embeddingModel]);
    /**
     * Gets provider-specific configuration fields
     */
    const getProviderFields = () => {
        switch (config.type) {
            case 'pinecone':
                return renderPineconeFields();
            case 'qdrant':
                return renderQdrantFields();
            case 'weaviate':
                return renderWeaviateFields();
            // Add other providers here
            default:
                return null;
        }
    };
    /**
     * Renders Pinecone-specific fields
     */
    const renderPineconeFields = () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "pinecone-environment", children: "Environment:" }), (0, jsx_runtime_1.jsx)("input", { id: "pinecone-environment", type: "text", value: config.options?.environment || '', onChange: e => handleConfigChange('options.environment', e.target.value), className: `form-control ${touched['options.environment'] && errors['options.environment'] ? 'is-invalid' : ''}`, placeholder: "e.g., us-east1" }), touched['options.environment'] && errors['options.environment'] && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors['options.environment'] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "pinecone-project-id", children: "Project ID:" }), (0, jsx_runtime_1.jsx)("input", { id: "pinecone-project-id", type: "text", value: config.options?.projectId || '', onChange: e => handleConfigChange('options.projectId', e.target.value), className: `form-control ${touched['options.projectId'] && errors['options.projectId'] ? 'is-invalid' : ''}`, placeholder: "Pinecone project ID" }), touched['options.projectId'] && errors['options.projectId'] && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors['options.projectId'] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "pinecone-namespace", children: "Namespace (optional):" }), (0, jsx_runtime_1.jsx)("input", { id: "pinecone-namespace", type: "text", value: config.options?.namespace || '', onChange: e => handleConfigChange('options.namespace', e.target.value), className: `form-control ${touched['options.namespace'] && errors['options.namespace'] ? 'is-invalid' : ''}`, placeholder: "Namespace for partitioning data" }), touched['options.namespace'] && errors['options.namespace'] && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors['options.namespace'] }))] })] }));
    /**
     * Renders Qdrant-specific fields
     */
    const renderQdrantFields = () => ((0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "qdrant-metric", children: "Distance Metric:" }), (0, jsx_runtime_1.jsxs)("select", { id: "qdrant-metric", value: config.metric || 'cosine', onChange: e => handleConfigChange('metric', e.target.value), className: "form-control", children: [(0, jsx_runtime_1.jsx)("option", { value: "cosine", children: "Cosine Similarity" }), (0, jsx_runtime_1.jsx)("option", { value: "euclidean", children: "Euclidean Distance" }), (0, jsx_runtime_1.jsx)("option", { value: "dot", children: "Dot Product" })] })] }));
    /**
     * Renders Weaviate-specific fields
     */
    const renderWeaviateFields = () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "weaviate-schema-class", children: "Schema Class:" }), (0, jsx_runtime_1.jsx)("input", { id: "weaviate-schema-class", type: "text", value: config.options?.schemaClass || '', onChange: e => handleConfigChange('options.schemaClass', e.target.value), className: `form-control ${touched['options.schemaClass'] && errors['options.schemaClass'] ? 'is-invalid' : ''}`, placeholder: "MyClass" }), touched['options.schemaClass'] && errors['options.schemaClass'] && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors['options.schemaClass'] })), (0, jsx_runtime_1.jsx)("small", { className: "form-text text-muted", children: "Must start with a capital letter and contain only alphanumeric characters" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "weaviate-text-key", children: "Text Property (optional):" }), (0, jsx_runtime_1.jsx)("input", { id: "weaviate-text-key", type: "text", value: config.options?.textKey || '', onChange: e => handleConfigChange('options.textKey', e.target.value), className: "form-control", placeholder: "text" })] })] }));
    /**
     * Main render function
     */
    return ((0, jsx_runtime_1.jsxs)("div", { className: "vector-db-config-form", children: [(0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "db-type", children: "Vector Database Type:" }), (0, jsx_runtime_1.jsxs)("select", { id: "db-type", value: config.type, onChange: e => handleConfigChange('type', e.target.value), className: "form-control", children: [(0, jsx_runtime_1.jsx)("option", { value: "pinecone", children: "Pinecone" }), (0, jsx_runtime_1.jsx)("option", { value: "qdrant", children: "Qdrant" }), (0, jsx_runtime_1.jsx)("option", { value: "weaviate", children: "Weaviate" }), (0, jsx_runtime_1.jsx)("option", { value: "elasticsearch", children: "Elasticsearch" }), (0, jsx_runtime_1.jsx)("option", { value: "pgvector", children: "PGVector" }), (0, jsx_runtime_1.jsx)("option", { value: "redis", children: "Redis" }), (0, jsx_runtime_1.jsx)("option", { value: "faiss", children: "FAISS" }), (0, jsx_runtime_1.jsx)("option", { value: "local", children: "Local Storage" }), (0, jsx_runtime_1.jsx)("option", { value: "memory", children: "In-Memory" }), (0, jsx_runtime_1.jsx)("option", { value: "drupal", children: "Drupal" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "collection", children: "Collection/Index Name:" }), (0, jsx_runtime_1.jsx)("input", { id: "collection", type: "text", value: config.collection, onChange: e => handleConfigChange('collection', e.target.value), className: `form-control ${touched.collection && errors.collection ? 'is-invalid' : ''}`, placeholder: "Collection or index name" }), touched.collection && errors.collection && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors.collection }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "dimensions", children: "Dimensions:" }), (0, jsx_runtime_1.jsx)("input", { id: "dimensions", type: "number", value: config.dimensions || '', onChange: e => handleConfigChange('dimensions', parseInt(e.target.value, 10)), className: `form-control ${touched.dimensions && errors.dimensions ? 'is-invalid' : ''}`, placeholder: "Vector dimensions", min: "1" }), touched.dimensions && errors.dimensions && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors.dimensions })), embeddingModel && vector_model_dimensions_1.MODEL_DIMENSIONS[embeddingModel] && ((0, jsx_runtime_1.jsxs)("small", { className: "form-text text-muted", children: ["Recommended dimensions for ", embeddingModel, ": ", vector_model_dimensions_1.MODEL_DIMENSIONS[embeddingModel]] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "url", children: "Connection URL:" }), (0, jsx_runtime_1.jsx)("input", { id: "url", type: "text", value: config.url || '', onChange: e => handleConfigChange('url', e.target.value), className: `form-control ${touched.url && errors.url ? 'is-invalid' : ''}`, placeholder: "Database connection URL" }), touched.url && errors.url && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors.url }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "form-group", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "api-key", children: "API Key:" }), (0, jsx_runtime_1.jsx)("input", { id: "api-key", type: "password", value: config.apiKey || '', onChange: e => handleConfigChange('apiKey', e.target.value), className: `form-control ${touched.apiKey && errors.apiKey ? 'is-invalid' : ''}`, placeholder: "API key for authentication" }), touched.apiKey && errors.apiKey && ((0, jsx_runtime_1.jsx)("div", { className: "invalid-feedback", children: errors.apiKey }))] }), getProviderFields()] }));
};
exports.VectorDatabaseConfigForm = VectorDatabaseConfigForm;
/**
 * Validates vector database configuration
 *
 * @param config Vector database configuration
 * @param embeddingModel Optional embedding model name
 * @returns Map of validation errors
 */
function validateConfig(config, embeddingModel) {
    const errors = {};
    // Basic validation
    if (!config.type) {
        errors.type = 'Vector database type is required';
    }
    if (!config.collection) {
        errors.collection = 'Collection name is required';
    }
    // Dimensions validation
    if (!config.dimensions) {
        errors.dimensions = 'Dimensions are required';
    }
    else if (!Number.isInteger(config.dimensions) || config.dimensions <= 0) {
        errors.dimensions = 'Dimensions must be a positive integer';
    }
    // Model dimension compatibility
    if (embeddingModel && vector_model_dimensions_1.MODEL_DIMENSIONS[embeddingModel] &&
        config.dimensions !== vector_model_dimensions_1.MODEL_DIMENSIONS[embeddingModel]) {
        errors.dimensions = `Dimensions must match the embedding model (expected: ${vector_model_dimensions_1.MODEL_DIMENSIONS[embeddingModel]})`;
    }
    // Provider-specific validation
    switch (config.type) {
        case 'pinecone':
            if (!config.url) {
                errors.url = 'URL is required for Pinecone';
            }
            else if (!isValidUrl(config.url)) {
                errors.url = 'Pinecone URL must be a valid URL';
            }
            if (!config.apiKey) {
                errors.apiKey = 'API key is required for Pinecone';
            }
            if (!config.options?.environment) {
                errors['options.environment'] = 'Environment is required for Pinecone';
            }
            else if (typeof config.options.environment === 'string' &&
                !config.options.environment.match(/^[a-z]{2,}-[a-z]{4,}$/)) {
                errors['options.environment'] = 'Environment should be in format "region-location" (e.g., us-east1)';
            }
            if (!config.options?.projectId) {
                errors['options.projectId'] = 'Project ID is required for Pinecone';
            }
            if (config.options?.namespace && typeof config.options.namespace === 'string' &&
                !config.options.namespace.match(/^[a-zA-Z0-9_-]+$/)) {
                errors['options.namespace'] = 'Namespace can only contain letters, numbers, underscores, and hyphens';
            }
            break;
        case 'qdrant':
            if (!config.url) {
                errors.url = 'URL is required for Qdrant';
            }
            else if (!isValidUrl(config.url)) {
                errors.url = 'Qdrant URL must be a valid URL';
            }
            if (config.collection && typeof config.collection === 'string' &&
                !config.collection.match(/^[a-zA-Z0-9_-]+$/)) {
                errors.collection = 'Qdrant collection name can only contain letters, numbers, underscores, and hyphens';
            }
            break;
        case 'weaviate':
            if (!config.url) {
                errors.url = 'URL is required for Weaviate';
            }
            else if (!isValidUrl(config.url)) {
                errors.url = 'Weaviate URL must be a valid URL';
            }
            if (!config.options?.schemaClass) {
                errors['options.schemaClass'] = 'Schema class is required for Weaviate';
            }
            else if (typeof config.options.schemaClass === 'string' &&
                !config.options.schemaClass.match(/^[A-Z][a-zA-Z0-9]*$/)) {
                errors['options.schemaClass'] = 'Schema class must start with capital letter and contain only alphanumeric characters';
            }
            break;
        // Add other providers as needed
    }
    return errors;
}
/**
 * Validates URL format
 *
 * @param url URL to validate
 * @returns boolean indicating if URL is valid
 */
function isValidUrl(url) {
    try {
        new URL(url);
        return true;
    }
    catch (error) {
        return false;
    }
}
//# sourceMappingURL=VectorDatabaseConfigForm.js.map