(function($) {
    'use strict';
    function AysChatGPTEmbedding(element, options){
        this.el = element;
        this.$el = $(element);
        this.ajaxAction = 'ays_chatgpt_admin_ajax';

		// DEFINE PREFIXES
        this.CHATGPT_ASSISTANT_CLASS_PREFIX   = 'ays-chatgpt-assistant';
        this.CHATGPT_ASSISTANT_ID_PREFIX      = 'ays-chatgpt-assistant';
        this.CHATGPT_ASSISTANT_NAME_PREFIX    = 'ays_chatgpt_assistant';
        this.CHATGPT_ASSISTANT_OPTIONS_PREFIX = 'chatgpt_assistant_';
        this.dbOptions = undefined;
		
		this.REQUEST_URL = "";
		// OpenAI settings
		this.API_MAIN_URL = "https://api.openai.com/v1";
		this.API_EMBEDDING_URL = "/embeddings";
		this.API_COMPLETIONS_URL = "/completions";
		this.API_CHAT_COMPLETIONS_URL = "/chat/completions";
		// Gemini settings
		this.GEMINI_API_EMBEDDING_URL = "https://generativelanguage.googleapis.com/v1beta/models/embedding-001:embedContent";
		// Pinecone settings
		this.PINECONE_API_KEY = "";
		this.PINECONE_INDEX = "";
		this.PINECONE_DATABASE_URL = "/describe_index_stats";
		this.PINECONE_UPSERT_URL = "/vectors/upsert";
		this.PINECONE_DELETE_URL = "/vectors/delete?";
		this.PINECONE_QUERY_URL = "/query";

		// Global vars
		this.type = 'posts';

        this.init();

        return this;
    }

    AysChatGPTEmbedding.prototype.init = function() {
        var _this = this;
		_this.setEvents();
    };

    AysChatGPTEmbedding.prototype.setEvents = function(e){
		var _this = this;
		
		_this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-hidden-suboption-checkbox').on('change', function () {
			var suboption = $(this).parents('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-hidden-suboption-parent').next('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-hidden-suboption');
			var pineconeConection = _this.$el.find('#'+_this.CHATGPT_ASSISTANT_ID_PREFIX+'-pinecone-connection').val();
			if ($(this).is(':checked')) {
				suboption.removeClass('display_none');
				if(pineconeConection == 'true'){
					_this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-embedding-container').removeClass('display_none');
				}
			} else {
				suboption.addClass('display_none');
				if ($(this).is('#'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-enable-embedding')) {
					_this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-embedding-container').addClass('display_none');
				}
			}
		});

		_this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-connect-button').on('click', function (e) {
			e.preventDefault();
			_this.checkPineconeConnection($(this));
		});
		
		
		_this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-embed-custom-text').on('click', function (e) {
			e.preventDefault();
			_this.type = 'text';
			var postID = +$(this).attr('data-post-id');
			_this.embedCustomContent($(this));
		});

		_this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-settings-nav-tab a.nav-tab').on('click', function (e) {
			e.preventDefault();
			var key = 'ays_tab';
			var value = $(this).attr('data-tab');

			_this.insertUrlParam(key, value);
		});

    }

	AysChatGPTEmbedding.prototype.checkPineconeConnection = function (button) {
		var _this = this;
		var apiKey = _this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-api-key').val();
		var index = _this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-index').val();
		var connection = _this.$el.find('#'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-connection');
		var postsContainer = _this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-embedding-container');
		var responseMessageBox = button.next('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-response-message');
		var loader = button.find('i');
		var valid = false;
		index = index.indexOf("https://") === -1 ? 'https://'+index : index;	
		if (apiKey != "" && index != "") {
			$.ajax({
				url: aysChatGptAssistantGeneral.ajaxUrl,
				method: 'post',
				dataType: 'json',
				data: {
					pinecone_url : index+_this.PINECONE_DATABASE_URL,
					pinecone_key : apiKey,
					action : _this.ajaxAction,					
					function : 'ays_chatgpt_pinecone_check_connection',
				},
				beforeSend: function () {
					loader.removeClass('display_none');
				},
				success: function (response) {
					if (typeof response != "undefined") {
						var result = JSON.parse(response);
						valid = result.status;
						if (valid) {
							if (result.allow_embedding) {
								postsContainer.removeClass('display_none');				
								_this.$el.find('.note-for-save').show();
								connection.val(true);
								responseMessageBox.find('.valid-feedback').html(aysChatGptAssistantGeneral.translations.connectedPinecone).show();
								setTimeout(() => {
									responseMessageBox.find('.valid-feedback').hide();
								}, 5000);
							
							} else {
								_this.$el.find('.note-for-save').hide();
								postsContainer.addClass('display_none');
								connection.val(false);
								responseMessageBox.find('.invalid-feedback').html(aysChatGptAssistantGeneral.translations.pineconeDbEmpty).show();
								setTimeout(() => {
									responseMessageBox.find('.invalid-feedback').hide();
								}, 5000);
							}
						} else {
							_this.$el.find('.note-for-save').hide();
							postsContainer.addClass('display_none');
							connection.val(false);
							responseMessageBox.find('.invalid-feedback').html(aysChatGptAssistantGeneral.translations.errorConnectingPinecone).show();
							setTimeout(() => {
								responseMessageBox.find('.invalid-feedback').hide();
							}, 5000);
						}
					}
				},
				complete: function () {
					loader.addClass('display_none');
				}
			});
		}
	}
	
	AysChatGPTEmbedding.prototype.embedCustomContent = function (button) {
		var _this = this;
		var key = _this.$el.find('.ays-assistant-chatbox-apikey').val();
		
		var responseMessageBox = button.next().next('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-response-message');
		var loader = button.find('i');

		var text = button.parents('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-custom-content-container').find('#'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-custom-content').val();
		text = text.replace(/<(style|script)\b[^>]*>.*?<\/(style|script)>/gis, '');
		text = text.replace(/"/g, "'"); 
		var words = text.split(/\s+/).filter(word => word.length > 0); 
		var wordCount = words.length;
		if (text.trim() === '') {
			responseMessageBox.find('.invalid-feedback').html(aysChatGptAssistantGeneral.translations.errorEmptyText).show();
			setTimeout(() => {
				responseMessageBox.find('.invalid-feedback').hide();
			}, 5000);
			return;
		}
		if (wordCount > 5000) {
			responseMessageBox.find('.invalid-feedback').html(aysChatGptAssistantGeneral.translations.errorWords).show();
			setTimeout(() => {
				responseMessageBox.find('.invalid-feedback').hide();
			}, 5000);
			return;
		}
		var oldId = $('#ays_last_pinecone_post_id').val() || null;
		var postId = '-' + Date.now();
		$('#ays_last_pinecone_post_id').val(postId);

		_this.saveTextToDatabase(text, wordCount, postId)
        .then(() => {
            if (key != "") {
                loader.removeClass('display_none');
                var promises = [];
                var promise = _this.pineconeEmbedding(text, postId, key);
                promises.push(promise);
	
				if (oldId) {
					promises.push(_this.pineconeDelete(oldId));
				}
				
				var embedPromise = _this.pineconeEmbedding(text, postId, key);
				promises.push(embedPromise);
			
                Promise.all(promises)
                    .then(function () {
                        loader.addClass('display_none');
                        responseMessageBox.find('.valid-feedback').html(aysChatGptAssistantGeneral.translations.successfullyEmbeded).show();
                        setTimeout(() => {
                            responseMessageBox.find('.valid-feedback').hide();
                        }, 5000);
                    })
                    .catch(function (error) {
                        loader.addClass('display_none');
                        responseMessageBox.find('.invalid-feedback').html(aysChatGptAssistantGeneral.translations.embeddingFailed + error).show();
                        setTimeout(() => {
                            responseMessageBox.find('.invalid-feedback').hide();
                        }, 5000);
                    });

            } else {
                responseMessageBox.find('.invalid-feedback').html(aysChatGptAssistantGeneral.translations.errorOpenAi).show();
                setTimeout(() => {
                    responseMessageBox.find('.invalid-feedback').hide();
                }, 5000);
            }
        })
        .catch((error) => {
            responseMessageBox.find('.invalid-feedback').html(error).show();
            setTimeout(() => {
                responseMessageBox.find('.invalid-feedback').hide();
            }, 5000);
        });
	}

	AysChatGPTEmbedding.prototype.saveTextToDatabase = function (text, wordCount, postID) {
		var _this = this;
		return new Promise(function (resolve, reject) {
			jQuery.ajax({
				url: aysChatGptAssistantGeneral.ajaxUrl,
				method: 'post',
				dataType: 'json',
				data: {
					id: postID,
					text: text,
					length: wordCount,
					action : _this.ajaxAction,	
					function: 'ays_chatgpt_save_embedding_text_to_db', 
				},
				success: function (response) {
					if (response.success) {
						resolve();
					} else {
						reject("You weren't able to embed the content.");
					}
				},error: function () {
					reject(error);
				}
			});
		});
	};


	AysChatGPTEmbedding.prototype.pineconeEmbedding = function (content, postId, key) {
		var _this = this;
		var apiType = _this.$el.find('.ays-assistant-chatbox-apitype').val();
		
		return new Promise(function (resolve, reject) {
			_this.textEmbedding(content, key)
			.then(data => {
				if (!(typeof data?.error === "object")) {
					var tokens = 0;
					var embeddedValues;

					tokens += data.usage.total_tokens;
					embeddedValues = data.data[0].embedding
					
					var upsertData = {
						vectors: [{
							id: postId,
							metadata: {
								text: content,
							},
							values: embeddedValues
						}],
						namespace: ""
					};

					_this.pineconeUpsert(upsertData, tokens)
					.then(response => {
						resolve(response);
					})
					.catch(error => {
						reject(error);
					});
				
				} else {
					var errorMessage = data?.error.message;
					if(data?.error.type == "insufficient_quota"){
						errorMessage += " <a href='https://platform.openai.com/account/usage'> https://platform.openai.com/account/usage </a>";
					}
					reject(errorMessage);
				}
			})
			.catch(error => {
				reject(error);
			});
		});
	}

	AysChatGPTEmbedding.prototype.textEmbedding = function (content, key) {
		var _this = this;

		var requestHeaders = {};
		var requestBody = {};

		_this.REQUEST_URL = _this.API_MAIN_URL + _this.API_EMBEDDING_URL;
		
		requestHeaders = {
			"Content-Type": "application/json",
			"Authorization": `Bearer ${key}`,
		};

		requestBody = {
			model: "text-embedding-ada-002",
			input: content,
		};
		

		return fetch(_this.REQUEST_URL, {
			method: "POST",
			headers: requestHeaders,
			body: JSON.stringify(requestBody),
		})
        .then(response => {
            return response.json();
        })
	}

	AysChatGPTEmbedding.prototype.pineconeUpsert = function (upsertData, tokens) {
		var _this = this;
		var apiKey = _this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-api-key').val();
		var index = _this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-index').val();
		var insertData = {
			embed_tokens: tokens,
			post_id: upsertData.vectors[0].id,
			type: _this.type
		}

		index = index.indexOf("https://") === -1 ? 'https://'+index : index;
	  
		return new Promise(function(resolve, reject) {
			$.ajax({
				url: aysChatGptAssistantGeneral.ajaxUrl,
				method: 'post',
				dataType: 'json',
				data: {
					pinecone_url : index+_this.PINECONE_UPSERT_URL,
					pinecone_key : apiKey,
					upsert_data : JSON.stringify(upsertData),
					insert_data : JSON.stringify(insertData),
					action : _this.ajaxAction,					
					function : 'ays_chatgpt_pinecone_upsert',
					nonce: aysChatGptAssistantGeneral.nonce,
				},
				success: function (response) {
					if (typeof response !== "undefined" && response == true) {
						resolve(response);
					} else {
						reject(response);
					}
				},
				error: function (error) {
					reject(error);
				}
			});
		});
	}
	
	AysChatGPTEmbedding.prototype.pineconeDelete = function (postID) {
		var _this = this;
		var apiKey = _this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-api-key').val();
		var index = _this.$el.find('.'+_this.CHATGPT_ASSISTANT_CLASS_PREFIX+'-pinecone-index').val();
	
		index = index.indexOf("https://") === -1 ? 'https://'+index : index;
	  
		return new Promise(function(resolve, reject) {
			$.ajax({
				url: aysChatGptAssistantGeneral.ajaxUrl,
				method: 'post',
				dataType: 'json',
				data: {
					pinecone_url: index + _this.PINECONE_DELETE_URL + 'ids=' + postID, 
					pinecone_key: apiKey,
					pinecone_id: postID,
					action: _this.ajaxAction,
					function: 'ays_chatgpt_pinecone_delete',
				},
				success: function (response) {
					if (response === true) {
						resolve(response);
					} else {
						reject(response);
					}
				},
				error: function (error) {
					console.error(error); 
					reject(error);
				}
			});
		});
	};

	
	AysChatGPTEmbedding.prototype.insertUrlParam = function (key, value) {
		key = encodeURIComponent(key);
		value = encodeURIComponent(value);
	
		var keyValue = document.location.search.substr(1).split('&');
		var i = 0;
	
		for(; i < keyValue.length; i++) {
			if (keyValue[i].startsWith(key + '=')) {
				var pair = keyValue[i].split('=');
				pair[1] = value;
				keyValue[i] = pair.join('=');
				break;
			}
		}
	
		if (i >= keyValue.length) {
			keyValue[keyValue.length] = [key,value].join('=');
		}
	
		var params = keyValue.join('&');
	
		document.location.search = params;
	}


	$.fn.AysChatGPTEmbeddingMain = function(options) {       
		if (!$.data(this, 'AysChatGPTEmbeddingMain')) {
			$.data(this, 'AysChatGPTEmbeddingMain', new AysChatGPTEmbedding(this, options));
		} else {
			try {
				$(this).data('AysChatGPTEmbeddingMain').init();
			} catch (err) {
				console.error('AysChatGPTEmbeddingMain has not initiated properly');
			}
		}        
    };

    $(document).find('#ays-embeddings-form').AysChatGPTEmbeddingMain();

})(jQuery);