import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from "@wordpress/element";
import {__, sprintf} from "@wordpress/i18n";
import {getInitialData, getNavLinkTo, getSettingsDataToUpdate} from "../../../../../../../helpers";
import {handleError, handleWarning} from "../../../../../../../helpers/notifications";
import Dropdown from "../../../../../../fields/dropdown";
import {SOURCE_TYPES} from "../_data";
import LexicalEditor from "../../../../../../fields/lexical";
import {required, validate} from "../../../../../../../../validations";
import Input from "../../../../../../fields/input";
import {GetDefaultSettings} from "../../../../../../../helpers/rest";
import {GetSettings} from "../../../../../../../rest/settings";
import WPObjectsMultiSelect from "../../../../../../fields/specific-fields/wp-objects-multi-select";
import {GetPostTypes} from "../../../../../../../rest/wp-objects";
import {DGEN_PROCESS_KEY_PREFIX, DIN_PROCESS_KEY_PREFIX} from "../../../../../../../data/bg-processes";
import {WP_POST_TYPES_ICONS} from "./_data";
import FilesMultiSelect from "../../../../../../fields/specific-fields/files-multi-select";
import {SETTINGS_UTILITIES_KEY_PREFIX} from "../../../../../../../data/settings";
import Description from "../../../../../../sections/description";
import MultiSelect from "../../../../../../fields/multiselect";

/**
 * Get prepared settings
 *
 * @param {object} settings Settings
 * @param {string[]} skipKeys Settings keys to skip
 * @param {object[]} moreData Append more data
 * @return {{}|*}
 */
const getPreparedSettings = (settings, skipKeys = [], moreData = []) => {
    try {
        // All keys
        let keys = Object.keys(settings);
        // Skip keys
        if (skipKeys?.length > 0) {
            keys = keys.filter(item => !skipKeys.includes(item));
        }
        // Data
        const data = keys.reduce((obj, key) => {
            obj[key] = settings[key];
            return obj;
        }, {});
        // More data
        if (moreData?.length > 0) {
            for (const datum of moreData) {
                data[datum.key] = [datum.value, null]; // Keeping our state structure
            }
        }

        return data;
    } catch (e) {
        return settings;
    }
}

const AddSources = forwardRef(({
                                   formData,
                                   saving,
                                   setLoading,
                                   setShowLoading,
                                   updateHasUnsavedChanges,
                                   setIsFormValid,
                                   notifications,
                                   excludeSourceTypes
                               }, ref) => {
    // Actions states
    const [isDataSet, setIsDataSet] = useState(false);
    // Select options
    const [postTypes, setPostTypes] = useState([]);
    // Jet engine fields
    const [jetEngineFields, setJetEngineFields] = useState([]);
    const [jetEngineMetaBoxFields, setJetEngineMetaBoxFields] = useState([]);
    // Dataset generating settings
    const dgSettings = {
        'source': useState(''),
        'post_type': useState(''),
        'jet_engine_custom_fields': useState([]),
        'jet_engine_meta_box_fields': useState([]),
        'limit': useState([]),
        'files': useState([]),
        'q_a': useState({
            input: '',
            output: '',
        }),
        'text': useState({
            title: '',
            content: '',
        }),
        'urls': useState([]),
        'ai_model_id': useState(''),
        'config_id': useState(''),
    };
    // Dataset indexing settings
    const diSettings = {
        'ai_model_id': useState(''),
        'config_id': useState(''),
        'vector_index_type': useState(''),
        'vector_index_config_id': useState(''),
        'dimension': useState(''),
    };
    // Errors
    const errors = {
        // Dataset generating
        'source': useState(false),
        'post_type': useState(false),
        'limit': useState(false),
        'files': useState(false),
        'input': useState(false),
        'output': useState(false),
        'title': useState(false),
        'content': useState(false),
        'urls': useState(false),
        'sitemap': useState(false),
        // Dataset indexing
        'di_ai_model_id': useState(false),
        'di_config_id': useState(false),
        'vector_index_type': useState(false),
        'vector_index_config_id': useState(false),
        'dimension': useState(false),
    };
    // Initial data
    const dgInitialData = useRef(getInitialData(dgSettings));
    const diInitialData = useRef(getInitialData(diSettings));

    const [diAIDefaultSettingsChecked, setDIAIDefaultSettingsChecked] = useState(false);

    const diDefaultSettings = useRef();
    const isResettingRef = useRef(false);

    const [sitemap, setSitemap] = useState('');

    /**
     * Validate form fields
     *
     * @param {boolean} silent Whether to update the errors state
     * @return {boolean} True if form is valid, false otherwise
     */
    const validateFormFields = (silent) => {
        let hasError = false;
        // Dataset generating fields validation
        for (const item of Object.keys(dgSettings)) {
            // Check for non-standard key/values
            const errStates = [];
            if (item === 'ai_model_id' || item === 'config_id') {
                // Skip data sanitizing fields
                continue;
            } else if (item === 'q_a') {
                // Q/A
                errStates.push(
                    {
                        key: 'input',
                        value: dgSettings['q_a'][0]['input'],
                    },
                    {
                        key: 'output',
                        value: dgSettings['q_a'][0]['output'],
                    }
                );
            } else if (item === 'text') {
                // Text
                errStates.push(
                    {
                        key: 'title',
                        value: dgSettings['text'][0]['title'],
                    },
                    {
                        key: 'content',
                        value: dgSettings['text'][0]['content'],
                    }
                );
            } else {
                // Others, standard
                errStates.push({
                    key: item,
                    value: dgSettings[item][0],
                });
            }
            // Validate
            for (const errState of errStates) {
                if (!validateField(errState.key, errState.value, silent)) {
                    hasError = true;
                    break;
                }
            }
            if (hasError) {
                break;
            }
        }
        // Dataset indexing fields validation
        if (!hasError) {
            for (const item of Object.keys(diSettings)) {
                // Check for non-standard key/values
                const errStates = [];
                if (item === 'ai_model_id' || item === 'config_id') {
                    // AI settings
                    errStates.push({
                        key: 'di_' + item,
                        value: diSettings[item][0]
                    });
                } else {
                    // Others, standard
                    errStates.push({
                        key: item,
                        value: diSettings[item][0],
                    });
                }
                // Validate
                for (const errState of errStates) {
                    if (!validateField(errState.key, errState.value, silent)) {
                        hasError = true;
                        break;
                    }
                }
                if (hasError) {
                    break;
                }
            }
        }
        return !hasError;
    };

    useImperativeHandle(ref, () => ({
        async getDataToSave() {
            // Validate form fields
            if (!validateFormFields()) {
                return false;
            }
            // Check source type
            const dgSkipKeys = ['ai_model_id', 'config_id']; // Skip data sanitizing fields
            if (dgSettings['source'][0] === 'q_a') {
                dgSkipKeys.push('post_type', 'limit', 'files', 'text', 'urls');
            } else if (dgSettings['source'][0] === 'text') {
                dgSkipKeys.push('post_type', 'limit', 'files', 'q_a', 'urls');
            } else if (dgSettings['source'][0] === 'url' || dgSettings['source'][0] === 'sitemap') {
                dgSkipKeys.push('post_type', 'limit', 'files', 'q_a', 'text');
            } else {
                dgSkipKeys.push('q_a', 'text', 'urls');
                if (dgSettings['source'][0] === 'post') {
                    dgSkipKeys.push('files');
                }
                if (dgSettings['source'][0] === 'file') {
                    dgSkipKeys.push('post_type', 'limit');
                }
            }
            // Dataset generating process data
            const dgDataToSave = LimbChatbot.Hooks.applyFilters(
                'lbaic.admin.page.settings.knowledge.items.dataset-generating.dataToSave',
                getSettingsDataToUpdate(
                    getPreparedSettings(
                        dgSettings,
                        dgSkipKeys
                    ),
                    {},
                    DGEN_PROCESS_KEY_PREFIX
                )
            );
            // Use URLs array for URL source type
            if (dgSettings['source'][0] === 'url') {
                const urlsValue = dgSettings['urls'][0];
                const urlsIndex = dgDataToSave.findIndex(item => item.key === `${DGEN_PROCESS_KEY_PREFIX}urls`);
                if (urlsIndex !== -1 && Array.isArray(urlsValue) && urlsValue.length > 0) {
                    dgDataToSave[urlsIndex].value = urlsValue.map(u => String(u).trim()).filter(Boolean);
                }
            }
            // Check limit value
            const limitIndex = dgDataToSave.findIndex(item => item.key === `${DGEN_PROCESS_KEY_PREFIX}limit`);
            if (limitIndex !== -1) {
                const value = dgDataToSave[limitIndex].value;
                // Check type
                if (value.length === 1 && value[0] === 'all') {
                    // Keep value as a count
                    dgDataToSave[limitIndex].value = 'all';
                }
            }
            // Dataset indexing process data
            const diDataToSave = LimbChatbot.Hooks.applyFilters(
                'lbaic.admin.page.settings.knowledge.items.dataset-indexing.dataToSave',
                getSettingsDataToUpdate(
                    getPreparedSettings(
                        diSettings
                    ),
                    {},
                    DIN_PROCESS_KEY_PREFIX
                )
            );
            return {
                data: [...dgDataToSave, ...diDataToSave],
            };
        },
        processCompleted() {
            // Set flag to prevent useEffect from checking unsaved changes during reset
            isResettingRef.current = true;

            // Store current source value before resetting
            const currentSource = dgSettings['source'][0];
            const shouldResetLimitAndFiles = currentSource !== 'q_a' && currentSource !== 'text' && currentSource !== 'url';

            // Reset all source-dependent state values
            dgSettings['source'][1]('');
            dgSettings['post_type'][1]('');
            dgSettings['q_a'][1]({input: '', output: ''});
            dgSettings['text'][1]({title: '', content: ''});
            dgSettings['urls'][1]([]);
            dgSettings['jet_engine_custom_fields'][1]([]);
            dgSettings['jet_engine_meta_box_fields'][1]([]);
            setSitemap('');
            if (shouldResetLimitAndFiles) {
                dgSettings['limit'][1]([]);
                dgSettings['files'][1]([]);
            }

            // Set hasUnsavedChanges to false since form is now reset
            // The reset flag will prevent useEffect from overriding this
            if (updateHasUnsavedChanges) {
                updateHasUnsavedChanges(false);
            }
        },
        discardChanges() {
            // Set flag to prevent useEffect from checking unsaved changes during reset
            isResettingRef.current = true;

            // Reset all dataset generating settings to initial values
            Object.keys(dgSettings).forEach(key => {
                if (key === 'q_a') {
                    const initialValue = dgInitialData.current[key] || {input: '', output: ''};
                    dgSettings[key][1]({...initialValue});
                } else if (key === 'text') {
                    const initialValue = dgInitialData.current[key] || {title: '', content: ''};
                    dgSettings[key][1]({...initialValue});
                } else {
                    const initialValue = dgInitialData.current[key];
                    if (Array.isArray(initialValue)) {
                        dgSettings[key][1]([...initialValue]);
                    } else {
                        dgSettings[key][1](initialValue !== undefined ? initialValue : (key === 'urls' ? [] : (key === 'source' ? '' : (key === 'post_type' ? '' : []))));
                    }
                }
            });

            // Reset sitemap
            setSitemap('');

            // Reset all dataset indexing settings to initial values
            Object.keys(diSettings).forEach(key => {
                const initialValue = diInitialData.current[key];
                if (Array.isArray(initialValue)) {
                    diSettings[key][1]([...initialValue]);
                } else {
                    diSettings[key][1](initialValue !== undefined ? initialValue : '');
                }
            });

            // Clear all errors
            Object.keys(errors).forEach(key => {
                errors[key][1](false);
            });

            // Set hasUnsavedChanges to false since form is now reset
            if (updateHasUnsavedChanges) {
                updateHasUnsavedChanges(false);
            }

            isResettingRef.current = false;
        },
        async isValid() {
            // Check if form is valid to learn
            return validateFormFields(true);
        },
        async updateDataIndexingSettings() {
            // Reset the checked flag to trigger re-checking of settings
            setDIAIDefaultSettingsChecked(false);
            // Call setupDatasetIndexingAIDefaultSettings to update with new embedding settings
            await setupDatasetIndexingAIDefaultSettings();
        },
        getSitemapUrl() {
            // Return current sitemap URL
            return sitemap;
        },
        validateSitemap() {
            // Validate sitemap field and return true if valid, false otherwise
            return validateField('sitemap', sitemap, false);
        },
        getSourceType() {
            // Return current source type
            return dgSettings['source'][0];
        },
    }));

    useEffect(() => {
        getPostTypes();
    }, []);

    useEffect(() => {
        checkFormData(formData);
    }, [formData]);

    /**
     * Setup initial data
     */
    useEffect(() => {
        if (isDataSet) {
            // Setup default settings
            setupDatasetIndexingAIDefaultSettings();
        }
    }, [isDataSet]);

    useEffect(() => {
        if (isDataSet && diAIDefaultSettingsChecked) {
            // Set initial data
            dgInitialData.current = getInitialData(dgSettings);
            diInitialData.current = getInitialData(diSettings);
        }
    }, [isDataSet, diAIDefaultSettingsChecked]);

    /**
     * Has unsaved changes
     */
    useEffect(() => {
        if (!updateHasUnsavedChanges) {
            return;
        }
        // Skip check if we're currently resetting the form
        if (isResettingRef.current) {
            return;
        }
        if (isDataSet && diAIDefaultSettingsChecked) {
            const dgDataToSave = getSettingsDataToUpdate(dgSettings, dgInitialData.current, DGEN_PROCESS_KEY_PREFIX);
            const diDataToSave = getSettingsDataToUpdate(diSettings, diInitialData.current, DIN_PROCESS_KEY_PREFIX);
            const hasChanges = dgDataToSave?.length > 0 || diDataToSave?.length > 0;
            updateHasUnsavedChanges(hasChanges);
        } else {
            updateHasUnsavedChanges(false);
        }
    }, [isDataSet, dgSettings, diSettings, diAIDefaultSettingsChecked, updateHasUnsavedChanges]);

    /**
     * Check form validity and update parent
     */
    useEffect(() => {
        if (!setIsFormValid) {
            return;
        }
        // Skip check if we're currently resetting the form
        if (isResettingRef.current) {
            return;
        }

        const checkFormValidity = () => {
            if (isDataSet && diAIDefaultSettingsChecked) {
                const isValid = validateFormFields(true);
                setIsFormValid(isValid);
            } else {
                setIsFormValid(false);
            }
        };

        checkFormValidity();
    }, [
        isDataSet,
        diAIDefaultSettingsChecked,
        setIsFormValid,
        // Dataset generating settings
        dgSettings['source'][0],
        dgSettings['post_type'][0],
        dgSettings['limit'][0],
        dgSettings['files'][0],
        dgSettings['q_a'][0],
        dgSettings['text'][0],
        dgSettings['urls'][0],
        // Dataset indexing settings
        diSettings['ai_model_id'][0],
        diSettings['config_id'][0],
        diSettings['vector_index_type'][0],
        diSettings['vector_index_config_id'][0],
        diSettings['dimension'][0],
    ]);

    /**
     * Reset posts related settings on q/a, text, or url case
     * Also reset all dependent fields when source is set to empty (default value)
     */
    useEffect(() => {
        const currentSource = dgSettings['source'][0];

        // Reset errors for all dataset generating fields when source type changes
        errors['post_type'][1](false);
        errors['limit'][1](false);
        errors['files'][1](false);
        errors['input'][1](false);
        errors['output'][1](false);
        errors['title'][1](false);
        errors['content'][1](false);
        errors['urls'][1](false);
        errors['sitemap'][1](false);

        // If source is set to empty (default value), reset all dependent fields
        if (!currentSource) {
            // Set flag to prevent useEffect from checking unsaved changes during reset
            isResettingRef.current = true;

            // Reset all source-dependent state values to initial/empty values
            dgSettings['post_type'][1]('');
            dgSettings['q_a'][1]({input: '', output: ''});
            dgSettings['text'][1]({title: '', content: ''});
            dgSettings['urls'][1]([]);
            dgSettings['limit'][1]([]);
            dgSettings['files'][1]([]);
            dgSettings['jet_engine_custom_fields'][1]([]);
            dgSettings['jet_engine_meta_box_fields'][1]([]);
            setSitemap('');

            isResettingRef.current = false;
        } else if (currentSource === 'q_a' || currentSource === 'text' || currentSource === 'url') {
            // Reset values for these source types
            dgSettings['post_type'][1]('');
            dgSettings['limit'][1]([]);
            dgSettings['files'][1]([]);
            dgSettings['jet_engine_custom_fields'][1]([]);
            dgSettings['jet_engine_meta_box_fields'][1]([]);
        } else if (currentSource !== 'post') {
            // When switching away from post, clear post-specific fields
            dgSettings['jet_engine_custom_fields'][1]([]);
            dgSettings['jet_engine_meta_box_fields'][1]([]);
        }

        // Clear reset flag when user starts making changes (source changes from empty to a value)
        if (isResettingRef.current && currentSource) {
            isResettingRef.current = false;
        }
    }, [dgSettings['source'][0]]);

    /**
     * Validate field
     *
     * @param {string} name Field name
     * @param {any} value Field value
     * @param {boolean} silent Whether to update the errors state
     * @return {boolean}
     */
    const validateField = (name, value, silent) => {
        try {
            let validations = [];

            switch (name) {
                case 'source':
                    validations = [required];
                    break;
                case 'post_type':
                case 'limit':
                    if (dgSettings['source'][0] === 'post') {
                        validations = [required];
                    }
                    break;
                case 'files':
                    if (dgSettings['source'][0] === 'file') {
                        validations = [required];
                    }
                    break;
                case 'input':
                case 'output':
                    if (dgSettings['source'][0] === 'q_a') {
                        validations = [(v) => required(v, {trim: true})];
                    }
                    break;
                case 'title':
                case 'content':
                    if (dgSettings['source'][0] === 'text') {
                        validations = [(v) => required(v, {trim: true})];
                    }
                    break;
                case 'urls':
                    if (dgSettings['source'][0] === 'url') {
                        validations = [
                            (v) => required(v, {trim: true}),
                            (v) => {
                                try {
                                    new URL(v.trim());
                                    return {valid: true};
                                } catch (e) {
                                    return {valid: false, message: __("Please enter a valid URL.", 'limb-chatbot')};
                                }
                            }
                        ];
                    }
                    break;
                case 'sitemap':
                    if (dgSettings['source'][0] === 'sitemap') {
                        validations = [
                            (v) => required(v, {trim: true}),
                            (v) => {
                                try {
                                    new URL(v.trim());
                                    return {valid: true};
                                } catch (e) {
                                    return {valid: false, message: __("Please enter a valid URL.", 'limb-chatbot')};
                                }
                            }
                        ];
                    }
                    break;
                default:
                    return true;
            }

            if (name === 'urls') {
                value = Array.isArray(value) ? (value.length ? value[0] : '') : value;
            }
            const res = validate(value, validations);
            // Update field errors state
            if (!silent) {
                errors[name][1](!res.valid ? res.message : false);
            }

            return res.valid;
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Field validation failed.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Something went wrong.", 'limb-chatbot'),
            });
            return false;
        }
    }

    /**
     * Get post types
     *
     * @return {Promise<void>}
     */
    const getPostTypes = async () => {
        const res = await GetPostTypes();
        setPostTypes([
            {
                label: 'Select post type',
                value: '',
                icon: '',
            },
            ...res.map(item => ({
                label: item.name,
                value: item.slug,
                icon: WP_POST_TYPES_ICONS.includes(item.slug) ? item.slug : 'settings',
            }))
        ]);
    }

    /**
     * Check form data
     *
     * @param {object|null} defaultData Form default data
     */
    const checkFormData = (defaultData) => {
        setLoading(prev => prev + 1);
        /**
         * Dataset generating settings
         */
        if (defaultData?.generating) {
            const keys = Object.keys(defaultData.generating);
            if (keys.length > 0) {
                for (const key of keys) {
                    if (key in dgSettings) {
                        // Keep URLs as array; normalize from string if stored as single URL
                        if (key === 'urls') {
                            const raw = defaultData.generating[key];
                            dgSettings[key][1](
                                Array.isArray(raw) ? [...raw] : (raw ? [raw] : [])
                            );
                        } else if (key === 'jet_engine_custom_fields' || key === 'jet_engine_meta_box_fields') {
                            const raw = defaultData.generating[key];
                            const value = raw?.items?.length
                                ? raw.items.map(item => item.key)
                                : (Array.isArray(raw) ? [...raw] : []);
                            dgSettings[key][1](value);
                        } else {
                            dgSettings[key][1](defaultData.generating[key]);
                        }
                    }
                }
            }
        }
        /**
         * Dataset indexing settings
         */
        if (defaultData?.indexing) {
            const keys = Object.keys(defaultData.indexing);
            if (keys.length > 0) {
                for (const key of keys) {
                    if (key in diSettings) {
                        diSettings[key][1](defaultData.indexing[key]);
                    }
                }
            }
        }
        setIsDataSet(true);
        setLoading(prev => prev - 1);
        setShowLoading(false);
    }

    /**
     * Setup post/dataset indexing default settings
     *
     * @return {Promise<void>}
     */
    const setupDatasetIndexingAIDefaultSettings = async () => {
        const dataNotDefined = [
            'ai_model_id',
            'config_id',
            'dimension',
            'vector_index_type',
            'vector_index_config_id'
        ];
        let aiModelId = diSettings['ai_model_id'][0];
        const chatbotSettingsPrefix = `${SETTINGS_UTILITIES_KEY_PREFIX}chatbot.`;
        const chatbotSettings = [];
        const chatbotKnowledgeSettingsPrefix = `${SETTINGS_UTILITIES_KEY_PREFIX}chatbot.kb_`;
        const chatbotKnowledgeSettings = [];
        try {
            // Check data existence
            for (const key of dataNotDefined) {
                if (diSettings[key][0]) {
                    dataNotDefined.splice(dataNotDefined.indexOf(key), 1);
                }
            }
            // Get data that aren't defined yet
            if (dataNotDefined.length) {
                const settings = await GetSettings(
                    LimbChatbot.rest.url,
                    LimbChatbot.rest.nonce,
                    {
                        key: [
                            ...dataNotDefined.map(item => chatbotKnowledgeSettingsPrefix + item),
                            chatbotSettingsPrefix + 'ai_provider_id',
                            chatbotSettingsPrefix + 'config_id',
                        ],
                    }
                );
                // Check knowledge settings
                if (settings?.length) {
                    for (const setting of settings) {
                        if (setting.key.indexOf(chatbotKnowledgeSettingsPrefix) !== -1) {
                            chatbotKnowledgeSettings.push(setting);
                        } else {
                            chatbotSettings.push(setting);
                        }
                    }
                }
            }
        } catch (e) {
            handleError(e);
        }

        // Check knowledge settings first
        if (chatbotKnowledgeSettings.length) {
            for (const item of chatbotKnowledgeSettings) {
                if (!item.value) {
                    continue;
                }
                const key = item.key.replace(chatbotKnowledgeSettingsPrefix, '');
                // Data found
                const index = dataNotDefined.indexOf(key);
                if (index !== -1) {
                    dataNotDefined.splice(index, 1);
                }
                // Update settings state
                diSettings[key][1](item.value);
                // Model ID
                if (key === 'ai_model_id') {
                    aiModelId = item.value;
                }
                // Vector index type
                if (key === 'vector_index_type') {
                    if (item.value === 'local') {
                        const index = dataNotDefined.indexOf('vector_index_config_id');
                        if (index !== -1) {
                            dataNotDefined.splice(index, 1);
                        }
                    }
                }
            }
        }

        // If all data defined then nothing to do
        if (!dataNotDefined.length) {
            setDIAIDefaultSettingsChecked(true);
            return;
        }

        // Check embedding utility settings
        const embeddingSettingsInfo = [
            {
                key: 'ai_model_id',
                defaultValue: '',
                validationKey: 'di_ai_model_id',
            },
            {
                key: 'config_id',
                defaultValue: '',
                validationKey: 'di_config_id',
            },
            {
                key: 'dimension',
                defaultValue: 1536,
                validationKey: 'dimension',
            }
        ];
        // Get the utility settings if it hasn't already
        if (!diDefaultSettings.current) {
            diDefaultSettings.current = await GetDefaultSettings(
                'embedding',
                embeddingSettingsInfo
            );
        }
        // Setup default values
        for (const item of embeddingSettingsInfo) {
            if (!diDefaultSettings.current[item.key]) {
                continue;
            }
            const index = dataNotDefined.indexOf(item.key);
            if (index !== -1) {
                dataNotDefined.splice(index, 1);
                // Update settings state
                const value = diDefaultSettings.current[item.key];
                diSettings[item.key][1](value);
                // Validate
                validateField(item.validationKey, value);
                // Model ID
                if (item.key === 'ai_model_id') {
                    aiModelId = value;
                }
            }
        }

        // If all data defined then nothing to do
        if (!dataNotDefined.length) {
            setDIAIDefaultSettingsChecked(true);
            return;
        }

        // Check chatbot settings if config not defined yet, as from the chatbot we can get only that one
        if (chatbotSettings.length && dataNotDefined.includes('config_id')) {
            const aiProviderId = chatbotSettings.find(item => item.key === chatbotSettingsPrefix + 'ai_provider_id')?.value;
            const configId = chatbotSettings.find(item => item.key === chatbotSettingsPrefix + 'config_id')?.value;
            if (configId) {
                // Check if the current config AI provider same as the DI model's AI provider
                if (aiModelId) {
                    try {
                        const res = await GetModel(LimbChatbot.rest.url, LimbChatbot.rest.nonce, aiModelId);
                        if (res?.id) {
                            if (res.ai_provider_id === aiProviderId) {
                                diSettings['config_id'][1](configId);
                                // Remove from dataNotDefined
                                dataNotDefined.splice(dataNotDefined.indexOf('config_id'), 1);
                            }
                        }
                    } catch (e) {
                        handleError(e);
                    }
                }
            }

        }

        // If all data defined then nothing to do
        if (!dataNotDefined.length) {
            setDIAIDefaultSettingsChecked(true);
            return;
        }

        // Check dimension
        const dimensionIndex = dataNotDefined.indexOf('dimension');
        if (dimensionIndex !== -1) {
            diSettings['dimension'][1](1536);
            dataNotDefined.splice(dimensionIndex, 1);
        }

        // Check storage type
        const vectorIndexType = dataNotDefined.indexOf('vector_index_type');
        if (vectorIndexType !== -1) {
            diSettings['vector_index_type'][1]('local');
            dataNotDefined.splice(vectorIndexType, 1);
            // Check storage config ID
            diSettings['vector_index_config_id'][1]('');
            const index = dataNotDefined.indexOf('vector_index_config_id');
            if (index !== -1) {
                dataNotDefined.splice(index, 1);
            }
        }

        // If all data defined then nothing to do
        if (!dataNotDefined.length) {
            setDIAIDefaultSettingsChecked(true);
            return;
        }

        handleWarning(null, notifications.set, {
            title: __("Knowledge settings are missing.", 'limb-chatbot'),
            description: sprintf(
                __("Please check the %s to be able to run learn process.", 'limb-chatbot'),
                `<a href="${getNavLinkTo('knowledge', 'settings')}">${__("Knowledge Settings", 'limb-chatbot')}<svg class="lbaic-settings-table-card-body-i lbaic-settings-table-card-body-input-i" fill="none" viewBox="0 0 24 24"><use href="#lbaic-settings-external-arrow" class="lbaic-settings-external-arrow"/><use href="#lbaic-external-box"/></svg></a>`
            ),
        });

        // Now all available things are defined
        setDIAIDefaultSettingsChecked(true);
    }

    const sourceTypes = SOURCE_TYPES.filter(item => !excludeSourceTypes?.includes(item.value) && item.value !== 'q_a');

    return <>
        <div className='lbaic-settings-a-ei-body'>
            <div className='lbaic-settings-column'>
                <div className='lbaic-settings-column-in'>
                    <Dropdown
                        value={dgSettings['source'][0]}
                        setValue={dgSettings['source'][1]}
                        options={sourceTypes}
                        placeholder={__("Source", 'limb-chatbot')}
                        disabled={saving}
                        iconClassName='lbaic-settings-dropdown-kb-icon'
                    />
                    <Description>{__("Select the type of content you want to learn from.", 'limb-chatbot')} <a href="https://wpaichatbot.com/documentation/teaching-your-chatbot/adding-knowledge-to-your-chatbot/#adding-a-knowledge-source" target="_blank">{__("Learn more", 'limb-chatbot')}</a></Description>
                </div>
                <div className='lbaic-settings-column-in'>
                    {dgSettings['source'][0] === 'post' && (
                        <>
                            <Dropdown
                                value={dgSettings['post_type'][0]}
                                setValue={(value) => {
                                    const prev = dgSettings['post_type'][0];
                                    dgSettings['post_type'][1](value);
                                    if (prev !== value) {
                                        dgSettings['jet_engine_custom_fields'][1]([]);
                                        dgSettings['jet_engine_meta_box_fields'][1]([]);
                                    }
                                }}
                                options={postTypes}
                                placeholder={__("Post type", 'limb-chatbot')}
                                validate={value => validateField('post_type', value)}
                                errorMessage={errors['post_type'][0]}
                                disabled={saving}
                                iconClassName='lbaic-settings-dropdown-kb-icon'
                            />
                            <Description>{__("Select which WordPress content type to choose from.", 'limb-chatbot')} <a href="https://wpaichatbot.com/documentation/teaching-your-chatbot/adding-knowledge-to-your-chatbot/#source-type-posts" target="_blank">{__("Learn more", 'limb-chatbot')}</a></Description>
                        </>
                    )}
                    {dgSettings['source'][0] === 'text' && (
                        <>
                            <Input
                                value={dgSettings['text'][0]['title']}
                                setValue={(value) => dgSettings['text'][1](prevState => ({
                                    ...(prevState || {}),
                                    title: value,
                                }))}
                                placeholder={__("Title", 'limb-chatbot')}
                                validate={value => validateField('title', value)}
                                errorMessage={errors['title'][0]}
                                disabled={saving}
                            />
                            <Description>{__("Enter a title for this text content", 'limb-chatbot')}</Description>
                        </>
                    )}
                    {dgSettings['source'][0] === 'url' && (
                        <>
                            <Input
                                value={dgSettings['urls'][0][0] || ''}
                                setValue={(value) => dgSettings['urls'][1]([value])}
                                placeholder={__("URL", 'limb-chatbot')}
                                staticPlaceholder={__("e.g., https://example.com", 'limb-chatbot')}
                                validate={value => validateField('urls', value)}
                                errorMessage={errors['urls'][0]}
                                disabled={saving}
                                autofocus
                            />
                            <Description>{__("Enter the URL of the webpage you want your chatbot to learn from.", 'limb-chatbot')}</Description>
                        </>
                    )}
                    {dgSettings['source'][0] === 'sitemap' && (
                        <>
                            <Input
                                value={sitemap}
                                setValue={setSitemap}
                                placeholder={__("Sitemap URL", 'limb-chatbot')}
                                staticPlaceholder={__("e.g., https://example.com/sitemap.xml", 'limb-chatbot')}
                                validate={value => validateField('sitemap', value)}
                                errorMessage={errors['sitemap'][0]}
                                disabled={saving}
                                autofocus
                            />
                            <Description>{__("Enter the URL of the website sitemap you want to load.", 'limb-chatbot')}</Description>
                        </>
                    )}
                </div>
            </div>
            {Boolean(dgSettings['post_type'][0]) && (
                <>
                    <div className='lbaic-settings-column'>
                        <div className='lbaic-settings-column-in'>
                            <WPObjectsMultiSelect
                                limit={dgSettings['limit'][0]}
                                setLimit={dgSettings['limit'][1]}
                                isDataSet={isDataSet}
                                postType={dgSettings['post_type'][0]}
                                additionalQueryParams={(
                                    LimbChatbot?.integrations?.includes('jetengine') ?
                                        {
                                            include: ['jet_engine_custom_fields', 'jet_engine_meta_box_fields']
                                        }
                                        :
                                        undefined
                                )}
                                onJetEngineFieldsUpdate={setJetEngineFields}
                                onJetEngineMetaBoxFieldsUpdate={setJetEngineMetaBoxFields}
                                validateField={value => validateField('limit', value)}
                                errors={errors['limit'][0]}
                                setLoading={setLoading}
                                saving={saving}
                                addNotification={notifications.set}
                                showAllOption
                            />
                            <Description>{__("Select the specific items to add to your knowledge source", 'limb-chatbot')}</Description>
                        </div>
                    </div>
                    {jetEngineFields.length > 0 && (
                        <div className='lbaic-settings-column'>
                            <div className='lbaic-settings-column-in'>
                                <MultiSelect
                                    value={dgSettings['jet_engine_custom_fields'][0]}
                                    setValue={dgSettings['jet_engine_custom_fields'][1]}
                                    options={jetEngineFields.map(item => ({
                                        label: item.label,
                                        value: item.key,
                                    }))}
                                    savedValueOptions={jetEngineFields.map(item => ({
                                        label: item.label,
                                        value: item.key,
                                    }))}
                                    placeholder={__("JetEngine meta fields", 'limb-chatbot')}
                                    searchable
                                    disabled={!dgSettings['limit'][0].length || saving}
                                    placeholderChildren={
                                        !jetEngineFields.every(item => dgSettings['jet_engine_custom_fields'][0].includes(item.key)) && (
                                            <div className="lbaic-settings-multiselect-placeholder-actions">
                                                <button
                                                    className="lbaic-settings-multiselect-placeholder-action"
                                                    type="button"
                                                    onClick={() => dgSettings['jet_engine_custom_fields'][1](jetEngineFields.map(item => item.key))}
                                                >{__("Select all", 'limb-chatbot')}</button>
                                            </div>
                                        )
                                    }
                                />
                                <Description>{__("Select the meta fields you want to include in your knowledge source", 'limb-chatbot')}</Description>
                            </div>
                        </div>
                    )}
                    {jetEngineMetaBoxFields.length > 0 && (
                        <div className='lbaic-settings-column'>
                            <div className='lbaic-settings-column-in'>
                                <MultiSelect
                                    value={dgSettings['jet_engine_meta_box_fields'][0]}
                                    setValue={dgSettings['jet_engine_meta_box_fields'][1]}
                                    options={jetEngineMetaBoxFields.map(item => ({
                                        label: item.label,
                                        value: item.key,
                                    }))}
                                    savedValueOptions={jetEngineMetaBoxFields.map(item => ({
                                        label: item.label,
                                        value: item.key,
                                    }))}
                                    placeholder={__("JetEngine meta box fields", 'limb-chatbot')}
                                    searchable
                                    disabled={!dgSettings['limit'][0].length || saving}
                                    placeholderChildren={
                                        !jetEngineMetaBoxFields.every(item => dgSettings['jet_engine_meta_box_fields'][0].includes(item.key)) && (
                                            <div className="lbaic-settings-multiselect-placeholder-actions">
                                                <button
                                                    className="lbaic-settings-multiselect-placeholder-action"
                                                    type="button"
                                                    onClick={() => dgSettings['jet_engine_meta_box_fields'][1](jetEngineMetaBoxFields.map(item => item.key))}
                                                >{__("Select all", 'limb-chatbot')}</button>
                                            </div>
                                        )
                                    }
                                />
                                <Description>{__("Select the meta box fields you want to include in your knowledge source", 'limb-chatbot')}</Description>
                            </div>
                        </div>
                    )}
                </>
            )}
            {dgSettings['source'][0] === 'file' && (
                <>
                    <div className='lbaic-settings-column'>
                        <div className='lbaic-settings-column-in'>
                            <FilesMultiSelect
                                filesUuids={dgSettings['files'][0]}
                                onUpdateFilesUuids={dgSettings['files'][1]}
                                isDataSet={isDataSet}
                                configId={dgSettings['config_id'][0]}
                                validateField={value => validateField('files', value)}
                                errors={errors['files'][0]}
                                setLoading={setLoading}
                                saving={saving}
                                addNotification={notifications.set}
                            />
                            <Description>{__("Upload documents for your chatbot to extract and learn from", 'limb-chatbot')} <a href="https://wpaichatbot.com/documentation/teaching-your-chatbot/adding-knowledge-to-your-chatbot/#source-type-files" target="_blank">{__("Learn more", 'limb-chatbot')}</a></Description>
                        </div>
                    </div>
                </>
            )}
            {dgSettings['source'][0] === 'q_a' &&
                <>
                    <div className='lbaic-settings-column'>
                        <div className='lbaic-settings-column-in'>
                            <Input
                                value={dgSettings['q_a'][0]['input']}
                                setValue={(value) => dgSettings['q_a'][1](prevState => ({
                                    ...(prevState || {}),
                                    input: value,
                                }))}
                                placeholder={__("Question", 'limb-chatbot')}
                                validate={value => validateField('input', value)}
                                errorMessage={errors['input'][0]}
                                disabled={saving}
                                autofocus
                            />
                        </div>
                        <div className='lbaic-settings-column-in'/>
                    </div>
                    <div className='lbaic-settings-column'>
                        <div className='lbaic-settings-column-in'>
                            <LexicalEditor
                                value={dgSettings['q_a'][0]['output']}
                                setValue={(value) => dgSettings['q_a'][1](prevState => ({
                                    ...(prevState || {}),
                                    output: value
                                }))}
                                validate={value => validateField('output', value)}
                                errorMessage={errors['output'][0]}
                                disabled={saving}
                                placeholder={__("Enter the answer...", 'limb-chatbot')}
                            />
                        </div>
                    </div>
                </>}
            {dgSettings['source'][0] === 'text' &&
                <>
                    <div className='lbaic-settings-column'>
                        <div className='lbaic-settings-column-in'>
                            <LexicalEditor
                                value={dgSettings['text'][0]['content']}
                                setValue={(value) => dgSettings['text'][1](prevState => ({
                                    ...(prevState || {}),
                                    content: value
                                }))}
                                convertToMarkdown={false}
                                placeholder={__("Enter your text...", 'limb-chatbot')}
                                validate={value => validateField('content', value)}
                                errorMessage={errors['content'][0]}
                                disabled={saving}
                            />
                            <Description>{__("Enter the content you want your chatbot to learn from.", 'limb-chatbot')} <a href="https://wpaichatbot.com/documentation/teaching-your-chatbot/adding-knowledge-to-your-chatbot/#source-type-text" target="_blank">{__("Learn more", 'limb-chatbot')}</a></Description>
                        </div>
                    </div>
                </>}
        </div>
    </>
});

export default AddSources;