import {forwardRef, useCallback, useEffect, useRef, useState} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import {handleError, handleSuccess} from "../../../../../../../../helpers/notifications";
import {GetSettings, UpdateSettings} from "../../../../../../../../rest/settings";
import {getProviderFromConfigRelation} from "../../../../../../../../helpers";
import {getAIProviderUtilities, getUtilityAIProviders} from "../../../../../../../../data/utilities";
import {SETTINGS_UTILITIES_KEY_PREFIX} from "../../../../../../../../data/settings";
import {GetUtilitySettings} from "../../../../../../../../helpers/rest";
import Config from "../../../../../../../fields/specific-fields/config";
import Description from "../../../../../../../sections/description";
import Dropdown from "../../../../../../../fields/dropdown";
import AddEditConfig from "../../../../../../../popups/ai-providers/models/add-edit-config";
import {AI_PROVIDERS} from "../../../../../../../../constants/chatbot/ai";
import {required, validate} from "../../../../../../../../../validations";

const EMBEDDING_AI_PROVIDERS = getUtilityAIProviders('embedding');
const EMBEDDING_AI_PROVIDERS_OPTIONS = AI_PROVIDERS.filter(option => EMBEDDING_AI_PROVIDERS.includes(option.value));

const EmbeddingSettings = forwardRef(({
                                          config,
                                          hasEmbeddingSupport,
                                          setHasEmbeddingSupport,
                                          setLoading,
                                          notifications,
                                          onStateChange,
                                          showEmbeddingSettingsUI,
                                          setShowEmbeddingSettingsUI,
                                          collecting
                                      }, ref) => {
    const [isEmbeddingSupportChecked, setIsEmbeddingSupportChecked] = useState(false);

    const settings = {
        'ai_provider_id': useState(EMBEDDING_AI_PROVIDERS[0]),
        'config_id': useState(''),
    };
    const errors = {
        'ai_provider_id': useState(false),
        'config_id': useState(false),
    };

    const [showAddNewConfigPopup, setShowAddNewConfigPopup] = useState(false);
    const embeddingConfigFieldRef = useRef(null);
    const selectedConfigRef = useRef(null);
    const savingRef = useRef(false);
    const lastSavedConfigIdRef = useRef(null);

    /**
     * Check embedding support
     *
     * @return {Promise<void>}
     */
    const checkEmbeddingSupport = useCallback(async () => {
        setLoading(prev => prev + 1);
        setIsEmbeddingSupportChecked(false);

        let embeddingConfigId = null;
        // Get config AI provider ID
        const configAIProviderId = getProviderFromConfigRelation(config?.related_to);
        if (configAIProviderId) {
            // Check embedding support
            const utilities = getAIProviderUtilities(configAIProviderId);
            const providerHasEmbedding = utilities.includes('embedding');

            if (providerHasEmbedding) {
                embeddingConfigId = config.id;
            }
        }

        if (!embeddingConfigId) {
            // Check chatbot KB settings
            try {
                const settings = await GetSettings(LimbChatbot.rest.url, LimbChatbot.rest.nonce, {
                    key: [SETTINGS_UTILITIES_KEY_PREFIX + 'chatbot.kb_config_id']
                });

                embeddingConfigId = settings?.find(setting => setting.key === SETTINGS_UTILITIES_KEY_PREFIX + 'chatbot.kb_config_id')?.value;
            } catch (e) {
                handleError(e);
            }
        }

        // Check has embedding config
        if (embeddingConfigId) {
            setHasEmbeddingSupport(true);
            // If settings already exist, don't show the UI
            if (setShowEmbeddingSettingsUI) {
                setShowEmbeddingSettingsUI(false);
            }
        } else {
            // If settings don't exist, show the UI
            if (setShowEmbeddingSettingsUI) {
                setShowEmbeddingSettingsUI(true);
            }
        }

        setIsEmbeddingSupportChecked(true);
        setLoading(prev => prev - 1);
    }, [config, setHasEmbeddingSupport, setLoading, setShowEmbeddingSettingsUI]);

    // Check if provider has embedding support and if KB config exists
    useEffect(() => {
        checkEmbeddingSupport();
    }, [checkEmbeddingSupport]);

    /**
     * Save embedding settings
     *
     * @return {Promise<boolean>} Returns true if saved successfully, false otherwise
     */
    const saveEmbeddingSettings = useCallback(async () => {
        if (!selectedConfigRef.current?.id) {
            handleError(notifications.set, {
                title: __("Knowledge collection API key is missing.", 'limb-chatbot'),
            });
            return false;
        }

        // Prevent duplicate saves: check if already saving or if same config was just saved
        const currentConfigId = selectedConfigRef.current.id;
        if (savingRef.current || lastSavedConfigIdRef.current === currentConfigId) {
            return true; // Already saved or saving
        }

        savingRef.current = true;
        setLoading(prev => prev + 1);

        try {
            const embeddingProviderId = getProviderFromConfigRelation(selectedConfigRef.current?.related_to);
            // Get embedding utility default AI model ID
            const embeddingRes = await GetUtilitySettings(embeddingProviderId, 'embedding', [
                {
                    key: 'ai_model_id',
                    defaultValue: '',
                }
            ]);

            // Update KB settings
            await UpdateSettings(LimbChatbot.rest.url, LimbChatbot.rest.nonce, [
                {
                    key: SETTINGS_UTILITIES_KEY_PREFIX + 'chatbot.kb_config_id',
                    value: selectedConfigRef.current?.id,
                },
                {
                    key: SETTINGS_UTILITIES_KEY_PREFIX + 'chatbot.kb_ai_model_id',
                    value: embeddingRes.ai_model_id || '',
                },
                {
                    key: SETTINGS_UTILITIES_KEY_PREFIX + 'embedding.default.ai_provider_id',
                    value: embeddingProviderId,
                }
            ]);

            // Now has embedding support
            setHasEmbeddingSupport(true);

            // Track the saved config ID to prevent duplicate saves
            lastSavedConfigIdRef.current = currentConfigId;

            setLoading(prev => prev - 1);
            savingRef.current = false;

            // Notify parent that settings were saved (so it can update AddSources)
            if (onStateChange) {
                onStateChange({
                    isEmbeddingSettingsValid: true,
                    saveEmbeddingSettings,
                    settingsSaved: true
                });
            }

            return true;
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Failed to save knowledge base settings.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
            });
            setLoading(prev => prev - 1);
            savingRef.current = false;
            return false;
        }
    }, [setHasEmbeddingSupport, notifications, setLoading, onStateChange]);

    // Check if embedding settings fields are valid
    // Valid when both provider and config are selected
    const isEmbeddingSettingsValid = Boolean(settings['ai_provider_id'][0] && settings['config_id'][0]);

    // Notify parent of state changes
    useEffect(() => {
        if (onStateChange) {
            onStateChange({
                isEmbeddingSettingsValid,
                saveEmbeddingSettings
            });
        }
    }, [isEmbeddingSettingsValid, saveEmbeddingSettings, onStateChange]);

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

            switch (name) {
                case 'ai_provider_id':
                case 'config_id':
                    validations = [required];
                    break;
                default:
                    break;
            }
            const res = validate(value, validations);
            // Update field errors state
            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;
        }
    };

    /**
     * Handle embedding config selection
     */
    const handleEmbeddingConfigSelected = async (config) => {
        // Only process if config actually changed
        if (selectedConfigRef.current?.id === config?.id) {
            return; // Same config, no need to save again
        }

        selectedConfigRef.current = config;

        // Auto-save embedding settings when config is selected
        // Only save if config ID is different from last saved
        if (config?.id && lastSavedConfigIdRef.current !== config.id) {
            await saveEmbeddingSettings();
        }
    };

    // Don't show if:
    // 1. Initial check not completed yet
    // 2. Settings already exist (checked on initial render)
    // 3. UI should be hidden (after first job completion)
    if (!isEmbeddingSupportChecked || !showEmbeddingSettingsUI) {
        return null;
    }

    return (
        <div className='lbaic-settings-mp-popup-content'>
            <div className="lbaic-settings-column">
                <div className="lbaic-settings-column-in">
                    <Dropdown
                        value={settings['ai_provider_id'][0]}
                        setValue={settings['ai_provider_id'][1]}
                        options={EMBEDDING_AI_PROVIDERS_OPTIONS}
                        placeholder={__("AI provider", 'limb-chatbot')}
                        validate={value => validateField('ai_provider_id', value)}
                        errorMessage={errors['ai_provider_id'][0]}
                        disabled={collecting}
                    />
                    <Description>{__("Choose AI provider for Knowledge collection", 'limb-chatbot')}</Description>
                </div>
                <div className="lbaic-settings-column-in">
                    <Config
                        ref={embeddingConfigFieldRef}
                        aiProviderId={settings['ai_provider_id'][0]}
                        isDataFetched={Boolean(settings['ai_provider_id'][0])}
                        configId={settings['config_id'][0]}
                        setConfigId={settings['config_id'][1]}
                        configSelected={handleEmbeddingConfigSelected}
                        fieldProps={{
                            addNew: () => setShowAddNewConfigPopup(true),
                            validate: value => validateField('config_id', value),
                            errorMessage: errors['config_id'][0],
                        }}
                        setLoading={setLoading}
                        notifications={notifications}
                        disabled={!settings['ai_provider_id'][0] || collecting}
                    />
                    <Description>{__("Select the API key for Knowledge collection.", 'limb-chatbot')} <a href="https://wpaichatbot.com/documentation/teaching-your-chatbot/adding-knowledge-to-your-chatbot/#api-key" target="_blank">{__("Learn more", 'limb-chatbot')}</a></Description>
                </div>
            </div>
            <div className="lbaic-settings-gap-end"/>
            {showAddNewConfigPopup && (
                <AddEditConfig
                    aiProviderId={settings['ai_provider_id'][0]}
                    added={newConfig => embeddingConfigFieldRef.current?.newConfigAdded(newConfig)}
                    close={() => setShowAddNewConfigPopup(false)}
                    notifications={notifications}
                />
            )}
        </div>
    );
});

EmbeddingSettings.displayName = 'EmbeddingSettings';

export default EmbeddingSettings;
