/**
 * HNG Commerce - Live Chat Frontend JavaScript
 *
 * @package HNG_Commerce
 * @since 1.3.0
 */

(function ($) {
	'use strict';

	// Debug mode - set to false in production
	const HNG_CHAT_DEBUG = false;

	// Debug logger
	function debugLog(...args) {
		if (HNG_CHAT_DEBUG && console && console.log) {
			console.log( '[HNG Chat]', ...args );
		}
	}

	// Chat controller
	const HNGLiveChat = {
		config: null,
		sessionKey: null,
		sessionId: null,
		guestToken: null,
		lastMessageId: 0,
		isOpen: false,
		isConnected: false,
		pollInterval: null,
		typingTimeout: null,
		unreadCount: 0,
		// Notification system
		eventSource: null,   // SSE EventSource
		websocket: null,     // WebSocket connection
		isPolling: false,    // Long polling flag
		hideTypingTimeout: null, // Typing indicator timeout

		/**
		 * Initialize
		 */
		init: function () {
			this.config = window.hngLiveChatConfig || {};

			if ( ! this.config.ajaxUrl) {
				console.error( 'HNG Live Chat: Configuration missing' );
				return;
			}

			this.bindEvents();
			this.restoreSession();
			this.applyCustomStyles();
			this.checkBusinessHours();
			this.restoreSoundPreference();
		},

		/**
		 * Apply custom styles
		 */
		applyCustomStyles: function () {
			const settings = this.config.settings || {};
			const widget   = document.getElementById( 'hng-live-chat-widget' );

			if ( ! widget) {
				return;
			}

			if (settings.primaryColor) {
				widget.style.setProperty( '--hng-chat-primary', settings.primaryColor );
			}

			// Apply start button color if configured
			if (settings.startButtonColor) {
				widget.style.setProperty( '--hng-chat-start-btn-color', settings.startButtonColor );
			}

			// Apply button text color
			if (settings.buttonTextColor) {
				widget.style.setProperty( '--hng-chat-btn-text-color', settings.buttonTextColor );
			}

			// Apply header colors
			if (settings.headerColor) {
				widget.style.setProperty( '--hng-chat-header-color', settings.headerColor );
			}
			if (settings.headerTextColor) {
				widget.style.setProperty( '--hng-chat-header-text-color', settings.headerTextColor );
			}

			// Apply chat background color (fix: was setting wrong variable name)
			if (settings.chatBgColor) {
				widget.style.setProperty( '--hng-chat-bg', settings.chatBgColor );
				widget.style.setProperty( '--hng-chat-bg-light', settings.chatBgColor );
			}

			// Apply message text color
			if (settings.messageTextColor) {
				widget.style.setProperty( '--hng-chat-message-text-color', settings.messageTextColor );
				widget.style.setProperty( '--hng-chat-text', settings.messageTextColor );
			}

			// Apply gradient if enabled
			if (settings.gradientEnabled && settings.gradientColor1 && settings.gradientColor2) {
				var dir      = settings.gradientDirection || '135deg';
				var balance  = settings.gradientBalance || 50;
				var gradient = 'linear-gradient(' + dir + ', ' + settings.gradientColor1 + ' 0%, ' + settings.gradientColor1 + ' ' + balance + '%, ' + settings.gradientColor2 + ' 100%)';
				widget.style.setProperty( '--hng-chat-gradient', gradient );

				// Apply gradient to bubble
				var bubble = widget.querySelector( '.hng-chat-bubble' );
				if (bubble) {
					bubble.style.background = gradient;
				}

				// Apply gradient to header
				var header = widget.querySelector( '.hng-chat-header' );
				if (header) {
					header.style.background = gradient;
				}
			}

			// Apply typography and form settings
			if (settings.borderColor && settings.borderColor !== '#e5e7eb') {
				widget.style.setProperty( '--hng-chat-border-color', settings.borderColor );
			}
			if (settings.chatRadius && settings.chatRadius !== 16) {
				widget.style.setProperty( '--hng-chat-radius', settings.chatRadius + 'px' );
			}
			if (settings.chatFontFamily) {
				widget.style.setProperty( '--hng-chat-font-family', settings.chatFontFamily );
			}
			if (settings.chatFontSize && settings.chatFontSize !== 14) {
				widget.style.setProperty( '--hng-chat-font-size', settings.chatFontSize + 'px' );
			}
		},

		/**
		 * Check business hours and show message if outside
		 */
		checkBusinessHours: function () {
			const settings = this.config.settings || {};

			if (settings.businessHoursEnabled && ! settings.isWithinBusinessHours) {
				// Show outside hours message
				$( '.hng-chat-welcome' ).text( settings.outsideHoursMessage );
				$( '.hng-chat-start-btn' ).prop( 'disabled', true ).text( this.config.i18n.outsideHours || 'Fora do horário' );
			}
		},

		/**
		 * Bind events
		 */
		bindEvents: function () {
			const self = this;

			// Toggle chat
			$( document ).on(
				'click',
				'.hng-chat-bubble',
				function () {
					self.toggleChat();
				}
			);

			// Close chat
			$( document ).on(
				'click',
				'.hng-chat-close',
				function () {
					self.closeChat();
				}
			);

			// Minimize chat
			$( document ).on(
				'click',
				'.hng-chat-minimize',
				function () {
					self.minimizeChat();
				}
			);

			// Sound toggle
			$( document ).on(
				'click',
				'.hng-chat-sound-toggle',
				function () {
					self.toggleSound();
				}
			);

			// Start chat form
			$( document ).on(
				'submit',
				'.hng-chat-prechat-form',
				function (e) {
					e.preventDefault();
					self.startChat( $( this ) );
				}
			);

			// Send message
			$( document ).on(
				'click',
				'.hng-chat-send',
				function () {
					self.sendMessage();
				}
			);

			$( document ).on(
				'keypress',
				'.hng-chat-input',
				function (e) {
					if (e.which === 13 && ! e.shiftKey) {
						e.preventDefault();
						self.sendMessage();
					}
				}
			);

			// Typing indicator
			$( document ).on(
				'input',
				'.hng-chat-input',
				function () {
					self.sendTypingIndicator( true );

					clearTimeout( self.typingTimeout );
					self.typingTimeout = setTimeout(
						function () {
							self.sendTypingIndicator( false );
						},
						2000
					);
				}
			);

			// File upload
			$( document ).on(
				'click',
				'.hng-chat-attach',
				function () {
					$( '.hng-chat-file-input' ).click();
				}
			);

			$( document ).on(
				'change',
				'.hng-chat-file-input',
				function () {
					self.uploadFile( this.files[0] );
					$( this ).val( '' );
				}
			);

			// End chat - inline confirmation
			$( document ).on(
				'click',
				'.hng-chat-end-btn',
				function () {
					var $btn = $( this );
					if ($btn.hasClass( 'hng-confirm-active' )) {
						self.endChat();
						$btn.removeClass( 'hng-confirm-active' );
						return;
					}
					$btn.addClass( 'hng-confirm-active' );
					var origHtml = $btn.html();
					$btn.html( '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18"/><path d="M6 6l12 12"/></svg> ' + (self.config.i18n.endChat || 'Encerrar') + '? Confirmar' );
					$btn.css( {'color': '#ef4444', 'border-color': '#ef4444', 'background': 'rgba(239,68,68,0.08)'} );
					// Revert after 4 seconds if not clicked
					setTimeout(
						function () {
							if ($btn.hasClass( 'hng-confirm-active' )) {
								$btn.removeClass( 'hng-confirm-active' );
								$btn.html( origHtml );
								$btn.css( {'color': '', 'border-color': '', 'background': ''} );
							}
						},
						4000
					);
				}
			);

			// Start a new chat after closing previous one
			$( document ).on(
				'click',
				'.hng-chat-restart-btn',
				function () {
					self.clearSession();
					self.resetChatUI();
					self.openChat();
				}
			);

			// Rating
			$( document ).on(
				'click',
				'.hng-chat-stars button',
				function () {
					const rating = $( this ).data( 'rating' );
					$( this ).addClass( 'active' ).prevAll().addClass( 'active' );
					$( this ).nextAll().removeClass( 'active' );
					self.selectedRating = rating;
				}
			);

			$( document ).on(
				'click',
				'.hng-chat-rating-submit',
				function () {
					self.submitRating();
				}
			);

			$( document ).on(
				'click',
				'.hng-chat-rating-skip',
				function () {
					self.closeRating();
				}
			);

			// Auto-resize textarea
			$( document ).on(
				'input',
				'.hng-chat-input',
				function () {
					this.style.height = 'auto';
					this.style.height = Math.min( this.scrollHeight, 100 ) + 'px';
				}
			);

			// Heartbeat for real-time updates
			$( document ).on(
				'heartbeat-send',
				function (e, data) {
					if (self.sessionKey) {
						data.hng_live_chat_session = self.sessionKey;
						data.hng_live_chat_last_id = self.lastMessageId;
					}
				}
			);

			$( document ).on(
				'heartbeat-tick',
				function (e, data) {
					if (data.hng_live_chat) {
						self.processNewMessages( data.hng_live_chat.messages );

						if (data.hng_live_chat.session_status === 'closed') {
							self.handleSessionClosed();
						}

						if (data.hng_live_chat.operator_typing) {
							self.showTypingIndicator( self.config.i18n.isTyping );
						} else {
							self.hideTypingIndicator();
						}
					}
				}
			);
		},

		/**
		 * Restore previous session
		 */
		restoreSession: function () {
			const savedSession = localStorage.getItem( 'hng_live_chat_session' );

			if (savedSession) {
				try {
					const session = JSON.parse( savedSession );

					// Check if session is marked as closed locally
					if (session.closed) {
						localStorage.removeItem( 'hng_live_chat_session' );
						return;
					}

					// Check if session is not too old (2 hours for active sessions)
					if (session.timestamp && (Date.now() - session.timestamp) < 7200000) {
						this.sessionKey    = session.key;
						this.sessionId     = session.id;
						this.lastMessageId = session.lastMessageId || 0;

						// Try to resume session
						this.resumeSession();
					} else {
						localStorage.removeItem( 'hng_live_chat_session' );
					}
				} catch (e) {
					localStorage.removeItem( 'hng_live_chat_session' );
				}
			}
		},

		/**
		 * Save session
		 */
		saveSession: function () {
			if (this.sessionKey) {
				localStorage.setItem(
					'hng_live_chat_session',
					JSON.stringify(
						{
							key: this.sessionKey,
							id: this.sessionId,
							lastMessageId: this.lastMessageId,
							timestamp: Date.now()
						}
					)
				);
			}
		},

		/**
		 * Resume session
		 */
		resumeSession: function () {
			const self = this;

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: {
						action: 'hng_live_chat_get_messages',
						nonce: this.config.nonce,
						session_key: this.sessionKey,
						last_id: 0
					},
					success: function (response) {
						if (response.success) {
							// Check if session is closed - if so, reset UI
							if (response.data.session_status === 'closed') {
								self.clearSession();
								self.resetChatUI();
								return;
							}

							self.isConnected = true;
							self.showChatArea( false );
							self.lastMessageId = 0;
							self.processNewMessages( response.data.messages );
							self.startPolling();

							if (response.data.operator_name) {
								self.updateStatus( response.data.operator_name + ' ' + self.config.i18n.operatorJoined );
							}
						} else {
							// Session invalid, clear
							self.clearSession();
						}
					},
					error: function () {
						self.clearSession();
					}
				}
			);
		},

		/**
		 * Clear session
		 */
		clearSession: function () {
			// Mark session as closed before removing
			const savedSession = localStorage.getItem( 'hng_live_chat_session' );
			if (savedSession) {
				try {
					const session  = JSON.parse( savedSession );
					session.closed = true;
					localStorage.setItem( 'hng_live_chat_session', JSON.stringify( session ) );
				} catch (e) {
				}
			}

			this.sessionKey    = null;
			this.sessionId     = null;
			this.lastMessageId = 0;
			this.isConnected   = false;
			localStorage.removeItem( 'hng_live_chat_session' );
			this.stopPolling();
		},

		/**
		 * Reset chat UI to initial state
		 */
		resetChatUI: function () {
			const self = this;

			// Clear any existing polling
			this.stopPolling();

			// Reset state variables
			this.sessionKey    = null;
			this.sessionId     = null;
			this.lastMessageId = 0;
			this.isConnected   = false;

			// Clear localStorage completely
			localStorage.removeItem( 'hng_live_chat_session' );

			// Reset visibility with slight delay to ensure DOM is ready
			setTimeout(
				function () {
					$( '.hng-chat-prechat' ).show();
					$( '.hng-chat-messages' ).hide().empty();
					$( '.hng-chat-footer' ).hide();
					$( '.hng-chat-restart-container' ).hide();
					$( '.hng-chat-rating' ).hide();

					// Reset form if exists
					var $form = $( '.hng-chat-prechat-form' );
					if ($form.length && $form[0]) {
						$form[0].reset();
					}
					$( '.hng-chat-start-btn' ).prop( 'disabled', false ).text( self.config.i18n.startChat );

					// Reset status
					self.updateStatus( '' );
				},
				100
			);
		},

		/**
		 * Toggle chat window
		 */
		toggleChat: function () {
			if (this.isOpen) {
				this.closeChat();
			} else {
				this.openChat();
			}
		},

		/**
		 * Open chat
		 */
		openChat: function () {
			this.isOpen = true;
			$( '.hng-chat-window' ).show();
			$( '.hng-chat-bubble' ).hide();

			// Clear unread
			this.unreadCount = 0;
			this.updateBadge();

			// Scroll to bottom
			this.scrollToBottom();

			// Focus input
			setTimeout(
				function () {
					if ($( '.hng-chat-messages' ).is( ':visible' )) {
						$( '.hng-chat-input' ).focus();
					} else {
						$( '.hng-chat-prechat-form input:first' ).focus();
					}
				},
				300
			);
		},

		/**
		 * Close chat
		 */
		closeChat: function () {
			this.isOpen = false;
			$( '.hng-chat-window' ).hide();
			$( '.hng-chat-bubble' ).show();
		},

		/**
		 * Minimize chat
		 */
		minimizeChat: function () {
			$( '#hng-live-chat-widget' ).toggleClass( 'minimized' );
		},

		/**
		 * Start chat
		 */
		startChat: function ($form) {
			const self = this;
			const $btn = $form.find( '.hng-chat-start-btn' );

			// Prevent double submit
			if ($btn.prop( 'disabled' )) {
				return;
			}

			$btn.prop( 'disabled', true ).text( this.config.i18n.connecting );

			const initialMessage = $form.find( '[name="initial_message"]' ).val() || '';

			const data = {
				action: 'hng_live_chat_start',
				nonce: this.config.nonce,
				guest_name: $form.find( '[name="guest_name"]' ).val() || '',
				guest_email: $form.find( '[name="guest_email"]' ).val() || '',
				subject: $form.find( '[name="subject"]' ).val() || '',
				initial_message: initialMessage,
				page_url: window.location.href
			};

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: data,
					success: function (response) {
						if (response.success) {
							self.sessionKey  = response.data.session_key;
							self.sessionId   = response.data.session_id;
							self.guestToken  = response.data.guest_token;
							self.isConnected = true;

							// Mark initial message ID so we don't add it again from polling
							self.lastMessageId = response.data.last_message_id || 0;

							self.saveSession();
							self.showChatArea();
							self.updateStatus( self.config.i18n.waitingOperator );
							self.startPolling();

							// Show the initial message that was already sent to server
							// (Server already saved it, just display locally)
							if (initialMessage) {
								self.addMessage(
									{
										sender_type: 'customer',
										message: initialMessage,
										time: new Date().toLocaleTimeString( [], {hour: '2-digit', minute:'2-digit'} )
									}
								);
							}
						} else {
							alert( response.data.message || self.config.i18n.error );
							$btn.prop( 'disabled', false ).text( self.config.i18n.startChat );
						}
					},
					error: function () {
						alert( self.config.i18n.error );
						$btn.prop( 'disabled', false ).text( self.config.i18n.startChat );
					}
				}
			);
		},

		/**
		 * Show chat area
		 */
		showChatArea: function (clearMessages) {
			const shouldClear = clearMessages !== false;
			$( '.hng-chat-prechat' ).hide();
			$( '.hng-chat-messages' ).show();
			if (shouldClear) {
				$( '.hng-chat-messages' ).empty();
			}
			$( '.hng-chat-footer' ).show();
			$( '.hng-chat-restart-container' ).hide();
			$( '.hng-chat-input' ).focus();
		},

		/**
		 * Update status text
		 */
		updateStatus: function (text) {
			$( '.hng-chat-status' ).text( text );
		},

		/**
		 * Send message
		 */
		sendMessage: function () {
			const $input  = $( '.hng-chat-input' );
			const message = $input.val().trim();

			if ( ! message || ! this.sessionKey) {
				return;
			}

			const self = this;

			// Clear input
			$input.val( '' ).css( 'height', 'auto' );

			// Add message immediately
			this.addMessage(
				{
					sender_type: 'customer',
					message: message,
					time: new Date().toLocaleTimeString( [], {hour: '2-digit', minute:'2-digit'} ),
					pending: true
				}
			);

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: {
						action: 'hng_live_chat_send',
						nonce: this.config.nonce,
						session_key: this.sessionKey,
						guest_token: this.guestToken || '',
						message: message
					},
					success: function (response) {
						if (response.success) {
							// Mark as sent
							$( '.hng-chat-message.pending' ).last().removeClass( 'pending' );
							self.lastMessageId = Math.max( self.lastMessageId, response.data.message_id );
							self.saveSession();
						} else {
							alert( response.data.message || self.config.i18n.error );
						}
					},
					error: function () {
						alert( self.config.i18n.error );
					}
				}
			);
		},

		/**
		 * Add message to chat
		 */
		addMessage: function (msg) {
			const $container = $( '.hng-chat-messages' );

			let html = '<div class="hng-chat-message ' + msg.sender_type;
			if (msg.pending) {
				html += ' pending';
			}
			html += '">';

			if (msg.sender_type === 'operator' && msg.sender_name) {
				html += '<div class="hng-chat-message-header">';
				html += '<span class="hng-chat-sender-name">' + this.escapeHtml( msg.sender_name ) + '</span>';
				html += '</div>';
			}

			if (msg.message_type === 'image' && msg.attachment) {
				html += '<div class="hng-chat-attachment">';
				html += '<img src="' + msg.attachment.url + '" alt="' + this.escapeHtml( msg.attachment.name ) + '" onclick="window.open(this.src)" />';
				html += '</div>';
			} else if (msg.message_type === 'file' && msg.attachment) {
				html += '<div class="hng-chat-attachment">';
				html += '<a href="' + msg.attachment.url + '" target="_blank" class="hng-chat-file-preview">';
				html += '<span class="hng-chat-file-icon">📎</span>';
				html += '<span class="hng-chat-file-info">';
				html += '<span class="hng-chat-file-name">' + this.escapeHtml( msg.attachment.name ) + '</span>';
				html += '<span class="hng-chat-file-size">' + this.formatFileSize( msg.attachment.size ) + '</span>';
				html += '</span>';
				html += '</a>';
				html += '</div>';
			} else {
				html += '<div class="hng-chat-message-content">' + this.escapeHtml( msg.message ).replace( /\n/g, '<br>' ) + '</div>';
			}

			if (msg.time && msg.sender_type !== 'system') {
				html += '<div class="hng-chat-message-time">' + msg.time + '</div>';
			}

			html += '</div>';

			$container.append( html );
			this.scrollToBottom();
		},

		/**
		 * Process new messages from polling/heartbeat
		 */
		processNewMessages: function (messages) {
			const self = this;

			debugLog( 'Live Chat: processNewMessages called with', messages ? messages.length : 0, 'messages' );

			if ( ! messages || ! messages.length) {
				return;
			}

			messages.forEach(
				function (msg) {
					debugLog( 'Live Chat: Processing message id=' + msg.id + ', lastMessageId=' + self.lastMessageId );
					if (msg.id > self.lastMessageId) {
						debugLog( 'Live Chat: Adding message', msg );
						self.addMessage( msg );
						self.lastMessageId = msg.id;

						// Play sound for operator messages (play if chat is not open, or if document is not visible)
						if (msg.sender_type === 'operator' && self.config.settings.soundEnabled) {
							// Always play sound for new operator messages
							self.playNotificationSound();

							// Update badge only if chat is not open
							if ( ! self.isOpen) {
								self.unreadCount++;
								self.updateBadge();
							}
						}

						// Update status when operator joins
						if (msg.sender_type === 'system' && msg.message.includes( 'entrou' )) {
							self.updateStatus( msg.sender_name + ' ' + self.config.i18n.operatorJoined );
						}
					}
				}
			);

			this.saveSession();
		},

		/**
		 * Start polling for new messages
		 * Supports: polling, long_polling, sse, websocket
		 */
		startPolling: function () {
			const self   = this;
			const method = this.config.settings.notificationMethod || 'polling';

			// Stop any existing connections
			this.stopPolling();

			debugLog( 'Live Chat: Starting notification method:', method );

			switch (method) {
				case 'long_polling':
					this.startLongPolling();
					break;
				case 'sse':
					this.startSSE();
					break;
				case 'websocket':
					this.startWebSocket();
					break;
				case 'polling':
				default:
					this.startRegularPolling();
					break;
			}
		},

		/**
		 * Start regular polling (default)
		 */
		startRegularPolling: function () {
			const self     = this;
			const interval = this.config.settings.pollingInterval || 3000;

			debugLog( 'Live Chat: Starting regular polling, interval:', interval + 'ms' );

			this.pollInterval = setInterval(
				function () {
					self.pollMessages();
				},
				interval
			);
		},

		/**
		 * Start long polling
		 */
		startLongPolling: function () {
			const self     = this;
			this.isPolling = true;

			debugLog( 'Live Chat: Starting long polling' );

			function doPoll() {
				if ( ! self.isPolling || ! self.sessionKey) {
					debugLog( 'Live Chat: Long polling stopped' );
					return;
				}

				$.ajax(
					{
						url: self.config.ajaxUrl,
						type: 'POST',
						data: {
							action: 'hng_live_chat_long_poll',
							nonce: self.config.nonce,
							session_key: self.sessionKey,
							last_id: self.lastMessageId
						},
						timeout: 30000,
						success: function (response) {
							debugLog( 'Live Chat: Long poll response', response );
							if (response.success) {
								self.processNewMessages( response.data.messages );

								if (response.data.session_status === 'closed') {
									self.handleSessionClosed();
									return;
								}

								if (response.data.operator_name) {
									self.updateStatus( response.data.operator_name );
								}
							}
							// Continue polling
							if (self.isPolling) {
								setTimeout( doPoll, 100 );
							}
						},
						error: function (xhr, status, error) {
							console.error( 'HNG Live Chat: Long poll error', status, error );
							// Retry after delay on error
							if (self.isPolling) {
								setTimeout( doPoll, 3000 );
							}
						}
					}
				);
			}

			doPoll();
		},

		/**
		 * Start Server-Sent Events (SSE)
		 */
		startSSE: function () {
			const self = this;

			if ( ! window.EventSource) {
				debugLog( 'Live Chat: SSE not supported, falling back to polling' );
				this.startRegularPolling();
				return;
			}

			const sseUrl = this.config.ajaxUrl +
				'?action=hng_live_chat_sse' +
				'&nonce=' + encodeURIComponent( this.config.nonce ) +
				'&session_key=' + encodeURIComponent( this.sessionKey ) +
				'&last_id=' + this.lastMessageId;

			debugLog( 'Live Chat: Starting SSE connection' );

			this.eventSource = new EventSource( sseUrl );

			this.eventSource.addEventListener(
				'connected',
				function (e) {
					debugLog( 'Live Chat: SSE connected', JSON.parse( e.data ) );
				}
			);

			this.eventSource.addEventListener(
				'messages',
				function (e) {
					const data = JSON.parse( e.data );
					debugLog( 'Live Chat: SSE messages received', data );
					self.processNewMessages( data.messages );
				}
			);

			this.eventSource.addEventListener(
				'session_closed',
				function (e) {
					debugLog( 'Live Chat: SSE session closed' );
					self.handleSessionClosed();
					self.stopPolling();
				}
			);

			this.eventSource.addEventListener(
				'operator_typing',
				function (e) {
					const data = JSON.parse( e.data );
					if (data.typing) {
						self.showTypingIndicator();
					}
				}
			);

			this.eventSource.addEventListener(
				'reconnect',
				function (e) {
					const data = JSON.parse( e.data );
					debugLog( 'Live Chat: SSE reconnecting, last_id:', data.last_id );
					self.lastMessageId = data.last_id;
					// Reconnect after a short delay
					setTimeout(
						function () {
							if (self.sessionKey) {
								self.startSSE();
							}
						},
						1000
					);
				}
			);

			this.eventSource.onerror = function (e) {
				debugLog( 'Live Chat: SSE error, reconnecting...' );
				self.eventSource.close();
				// Retry after delay
				setTimeout(
					function () {
						if (self.sessionKey) {
							self.startSSE();
						}
					},
					3000
				);
			};
		},

		/**
		 * Start WebSocket connection
		 */
		startWebSocket: function () {
			const self  = this;
			const wsUrl = this.config.settings.websocketUrl;

			if ( ! wsUrl || ! window.WebSocket) {
				debugLog( 'Live Chat: WebSocket not configured or not supported, falling back to polling' );
				this.startRegularPolling();
				return;
			}

			debugLog( 'Live Chat: Starting WebSocket connection to', wsUrl );

			try {
				this.websocket = new WebSocket( wsUrl );

				this.websocket.onopen = function () {
					debugLog( 'Live Chat: WebSocket connected' );
					// Send authentication/session info
					self.websocket.send(
						JSON.stringify(
							{
								type: 'auth',
								session_key: self.sessionKey,
								last_id: self.lastMessageId
							}
						)
					);
				};

				this.websocket.onmessage = function (e) {
					try {
						const data = JSON.parse( e.data );
						debugLog( 'Live Chat: WebSocket message', data );

						switch (data.type) {
							case 'messages':
								self.processNewMessages( data.messages );
								break;
							case 'session_closed':
								self.handleSessionClosed();
								break;
							case 'operator_typing':
								if (data.typing) {
									self.showTypingIndicator();
								}
								break;
							case 'operator_joined':
								self.updateStatus( data.operator_name );
								break;
						}
					} catch (err) {
						console.error( 'HNG Live Chat: WebSocket parse error', err );
					}
				};

				this.websocket.onerror = function (e) {
					console.error( 'HNG Live Chat: WebSocket error', e );
				};

				this.websocket.onclose = function (e) {
					debugLog( 'Live Chat: WebSocket closed, code:', e.code );
					// Reconnect if not intentionally closed
					if (self.sessionKey && e.code !== 1000) {
						setTimeout(
							function () {
								self.startWebSocket();
							},
							3000
						);
					}
				};
			} catch (err) {
				console.error( 'HNG Live Chat: WebSocket connection failed', err );
				this.startRegularPolling();
			}
		},

		/**
		 * Show typing indicator
		 */
		showTypingIndicator: function () {
			const self    = this;
			const $typing = $( '.hng-chat-typing' );

			if ($typing.length === 0) {
				const $messages = $( '.hng-chat-messages' );
				$messages.append( '<div class="hng-chat-typing"><span>' + this.config.i18n.isTyping + '</span></div>' );
				$messages.scrollTop( $messages[0].scrollHeight );
			}

			// Hide after 3 seconds
			clearTimeout( this.hideTypingTimeout );
			this.hideTypingTimeout = setTimeout(
				function () {
					$( '.hng-chat-typing' ).remove();
				},
				3000
			);
		},

		/**
		 * Stop polling / disconnect
		 */
		stopPolling: function () {
			// Stop regular polling
			if (this.pollInterval) {
				clearInterval( this.pollInterval );
				this.pollInterval = null;
			}

			// Stop long polling
			this.isPolling = false;

			// Close SSE
			if (this.eventSource) {
				this.eventSource.close();
				this.eventSource = null;
			}

			// Close WebSocket
			if (this.websocket) {
				this.websocket.close( 1000, 'User closed' );
				this.websocket = null;
			}

			debugLog( 'Live Chat: All connections stopped' );
		},

		/**
		 * Poll for new messages (regular polling)
		 */
		pollMessages: function () {
			const self = this;

			if ( ! this.sessionKey) {
				debugLog( 'Live Chat: No session key, stopping polling' );
				this.stopPolling();
				return;
			}

			debugLog( 'Live Chat: Polling for messages, last_id=' + this.lastMessageId );

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: {
						action: 'hng_live_chat_get_messages',
						nonce: this.config.nonce,
						session_key: this.sessionKey,
						last_id: this.lastMessageId
					},
					success: function (response) {
						debugLog( 'Live Chat: Poll response', response );
						if (response.success) {
							self.processNewMessages( response.data.messages );

							if (response.data.session_status === 'closed') {
								self.handleSessionClosed();
							}

							if (response.data.operator_name) {
								self.updateStatus( response.data.operator_name );
							}
						} else {
							console.error( 'HNG Live Chat: Poll error', response );
						}
					},
					error: function (xhr, status, error) {
						console.error( 'HNG Live Chat: AJAX error', status, error );
					}
				}
			);
		},

		/**
		 * Upload file
		 */
		uploadFile: function (file) {
			const self     = this;
			const settings = this.config.settings;

			if ( ! file || ! this.sessionKey) {
				return;
			}

			// Validate size
			if (file.size > settings.maxFileSize) {
				alert( this.config.i18n.fileTooLarge );
				return;
			}

			// Validate type
			const ext     = file.name.split( '.' ).pop().toLowerCase();
			const allowed = settings.allowedFileTypes.split( ',' ).map( s => s.trim().toLowerCase() );

			if ( ! allowed.includes( ext )) {
				alert( this.config.i18n.fileNotAllowed );
				return;
			}

			// Show progress
			const $progress = $(
				'<div class="hng-chat-upload-progress">' +
				'<span>' + this.config.i18n.uploading + '</span>' +
				'<div class="hng-chat-upload-progress-bar"><span></span></div>' +
				'</div>'
			);

			$( '.hng-chat-messages' ).append( $progress );
			this.scrollToBottom();

			const formData = new FormData();
			formData.append( 'action', 'hng_live_chat_upload' );
			formData.append( 'nonce', this.config.nonce );
			formData.append( 'session_key', this.sessionKey );
			formData.append( 'file', file );

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: formData,
					processData: false,
					contentType: false,
					xhr: function () {
						const xhr = new XMLHttpRequest();
						xhr.upload.addEventListener(
							'progress',
							function (e) {
								if (e.lengthComputable) {
									const percent = (e.loaded / e.total) * 100;
									$progress.find( '.hng-chat-upload-progress-bar span' ).css( 'width', percent + '%' );
								}
							}
						);
						return xhr;
					},
					success: function (response) {
						$progress.remove();

						if (response.success) {
							self.addMessage( response.data.message );
							self.lastMessageId = Math.max( self.lastMessageId, response.data.message_id );
							self.saveSession();
						} else {
							alert( response.data.message || self.config.i18n.error );
						}
					},
					error: function () {
						$progress.remove();
						alert( self.config.i18n.error );
					}
				}
			);
		},

		/**
		 * Send typing indicator
		 */
		sendTypingIndicator: function (isTyping) {
			if ( ! this.sessionKey) {
				return;
			}

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: {
						action: 'hng_live_chat_typing',
						nonce: this.config.nonce,
						session_key: this.sessionKey,
						is_typing: isTyping
					}
				}
			);
		},

		/**
		 * Show typing indicator
		 */
		showTypingIndicator: function (name) {
			const $typing = $( '.hng-chat-typing' );
			$typing.find( '.hng-typing-text' ).text( name );
			$typing.show();
			this.scrollToBottom();
		},

		/**
		 * Hide typing indicator
		 */
		hideTypingIndicator: function () {
			$( '.hng-chat-typing' ).hide();
		},

		/**
		 * End chat
		 */
		endChat: function (rating, comment) {
			const self = this;

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: {
						action: 'hng_live_chat_end',
						nonce: this.config.nonce,
						session_key: this.sessionKey,
						rating: rating || 0,
						comment: comment || ''
					},
					success: function (response) {
						self.handleSessionClosed();

						// Show rating if not provided
						if ( ! rating) {
							self.showRating();
						}
					}
				}
			);
		},

		/**
		 * Handle session closed
		 */
		handleSessionClosed: function () {
			this.stopPolling();
			this.updateStatus( this.config.i18n.chatEnded );
			$( '.hng-chat-input-container' ).hide();
			$( '.hng-chat-end-container' ).hide();
			$( '.hng-chat-footer' ).show();
			$( '.hng-chat-restart-container' ).show();

			// Only add message if not already added
			const $messages   = $( '.hng-chat-messages' );
			const lastMessage = $messages.find( '.hng-chat-message.system' ).last().text();

			if ( ! lastMessage.includes( this.config.i18n.chatEnded )) {
				this.addMessage(
					{
						sender_type: 'system',
						message: this.config.i18n.chatEnded
					}
				);
			}

			// Show rating after a brief delay
			const self = this;
			setTimeout(
				function () {
					self.showRating();
				},
				500
			);
		},

		/**
		 * Show rating overlay
		 */
		showRating: function () {
			// Only show if we have a session
			if ( ! this.sessionKey) {
				return;
			}

			$( '.hng-chat-rating' ).show();
			this.selectedRating = 0;
		},

		/**
		 * Submit rating
		 */
		submitRating: function () {
			const self    = this;
			const comment = $( '.hng-chat-rating-comment' ).val();

			if ( ! this.selectedRating) {
				return;
			}

			$.ajax(
				{
					url: this.config.ajaxUrl,
					type: 'POST',
					data: {
						action: 'hng_live_chat_end',
						nonce: this.config.nonce,
						session_key: this.sessionKey,
						rating: this.selectedRating,
						comment: comment
					},
					success: function () {
						self.closeRating();
						self.clearSession();

						// Show styled thanks message
						$( '.hng-chat-rating' ).html(
							'<div class="hng-chat-rating-thanks">' +
							'<span class="hng-thanks-icon">✅</span>' +
							'<div class="hng-thanks-text">' + self.config.i18n.thanks + '</div>' +
							'<div class="hng-thanks-sub">Obrigado pelo seu feedback!</div>' +
							'</div>'
						).show();

						setTimeout(
							function () {
								self.closeChat();
								location.reload();
							},
							2500
						);
					}
				}
			);
		},

		/**
		 * Close rating overlay
		 */
		closeRating: function () {
			$( '.hng-chat-rating' ).hide();
			this.clearSession();
			$( '.hng-chat-restart-container' ).show();
		},

		/**
		 * Scroll to bottom of messages
		 */
		scrollToBottom: function () {
			const $messages = $( '.hng-chat-messages' );
			$messages.scrollTop( $messages[0].scrollHeight );
		},

		/**
		 * Update badge count
		 */
		updateBadge: function () {
			const $badge = $( '.hng-chat-badge' );

			if (this.unreadCount > 0) {
				$badge.text( this.unreadCount ).show();
			} else {
				$badge.hide();
			}
		},

		/**
		 * Play notification sound
		 */
		playNotificationSound: function () {
			// Check if sound is enabled
			if ( ! this.config.settings.soundEnabled) {
				return;
			}

			try {
				// Use Web Audio API to generate a pleasant notification sound
				const audioContext = new( window.AudioContext || window.webkitAudioContext )();

				// Create oscillators for a pleasant ding-dong sound
				const osc1     = audioContext.createOscillator();
				const osc2     = audioContext.createOscillator();
				const gainNode = audioContext.createGain();

				osc1.connect( gainNode );
				osc2.connect( gainNode );
				gainNode.connect( audioContext.destination );

				// Pleasant notification frequencies (G5 and E5)
				osc1.frequency.value = 784;
				osc2.frequency.value = 659;
				osc1.type            = 'sine';
				osc2.type            = 'sine';

				// Fade in and out
				const now = audioContext.currentTime;
				gainNode.gain.setValueAtTime( 0, now );
				gainNode.gain.linearRampToValueAtTime( 0.3, now + 0.05 );
				gainNode.gain.linearRampToValueAtTime( 0.1, now + 0.15 );
				gainNode.gain.linearRampToValueAtTime( 0, now + 0.4 );

				osc1.start( now );
				osc2.start( now + 0.15 );
				osc1.stop( now + 0.2 );
				osc2.stop( now + 0.4 );

				debugLog( 'Chat: Notification sound played' );
			} catch (e) {
				debugLog( 'Chat: Audio not supported', e );
			}
		},

		/**
		 * Toggle sound on/off
		 */
		toggleSound: function () {
			const self = this;
			const $btn = $( '.hng-chat-sound-toggle' );

			// Toggle sound setting
			this.config.settings.soundEnabled = ! this.config.settings.soundEnabled;

			if (this.config.settings.soundEnabled) {
				$btn.addClass( 'sound-active' );
				$btn.attr( 'title', this.config.i18n ? .soundOn || 'Som ativado' );
				// Play test sound to activate audio context
				this.playNotificationSound();
			} else {
				$btn.removeClass( 'sound-active' );
				$btn.attr( 'title', this.config.i18n ? .soundOff || 'Som desativado' );
			}

			// Save preference in localStorage
			try {
				localStorage.setItem( 'hng_chat_sound_enabled', this.config.settings.soundEnabled ? '1' : '0' );
			} catch (e) {
			}

			debugLog( 'Chat: Sound toggled to', this.config.settings.soundEnabled );
		},

		/**
		 * Restore sound preference
		 */
		restoreSoundPreference: function () {
			try {
				const savedPref = localStorage.getItem( 'hng_chat_sound_enabled' );

				// Padrão: som ATIVO. Somente desativa se usuário explicitamente salvou "0".
				this.config.settings.soundEnabled = savedPref !== '0';

				// Normalizar preferência inválida/ausente para "1"
				if (savedPref !== '0' && savedPref !== '1') {
					localStorage.setItem( 'hng_chat_sound_enabled', '1' );
				}

				if (this.config.settings.soundEnabled) {
					$( '.hng-chat-sound-toggle' ).addClass( 'sound-active' );
					debugLog( 'Chat: Sound enabled by default' );
				}
			} catch (e) {
				// Fallback: ativar som mesmo em caso de erro
				this.config.settings.soundEnabled = true;
				$( '.hng-chat-sound-toggle' ).addClass( 'sound-active' );
			}
		},

		/**
		 * Escape HTML
		 */
		escapeHtml: function (text) {
			if ( ! text) {
				return '';
			}

			const div       = document.createElement( 'div' );
			div.textContent = text;
			return div.innerHTML;
		},

		/**
		 * Format file size
		 */
		formatFileSize: function (bytes) {
			if ( ! bytes) {
				return '0 B';
			}

			const units = ['B', 'KB', 'MB', 'GB'];
			let i       = 0;

			while (bytes >= 1024 && i < units.length - 1) {
				bytes /= 1024;
				i++;
			}

			return bytes.toFixed( 1 ) + ' ' + units[i];
		}
	};

	// Initialize on DOM ready
	$( document ).ready(
		function () {
			HNGLiveChat.init();
		}
	);

	// Expose globally
	window.HNGLiveChat = HNGLiveChat;

})( jQuery );
