/**
 * AgenticWP Chat Interface
 *
 * Main chat interface orchestrator that manages the chat panel, messages,
 * sidebar actions, and user interactions.
 *
 * @file
 * @since 1.0.0
 * @package AgenticWP
 */

/**
 * Main chat interface controller.
 *
 * @class
 * @since 1.0.0
 */
class AgenticWPChat {
	/**
	 * Initializes the chat interface.
	 */
	constructor() {
		this.storage = new StorageWrapper();
		this.uiHelpers = new ChatUIHelpers();
		this.chatAPI = new ChatAPI(this.storage, this.uiHelpers);

		this.state = {
			isOpen: this.getStoredVisibility(),
			isLoading: false
		};

		this.elements = {};
		this.dragHandler = null;
		this.sidebar = null;
		this.sidebarToggle = null;
		this.sidebarClose = null;
		this.actionsLoaded = false;
		this.actionsData = null;
		this.beforeUnloadHandler = this.handleBeforeUnload.bind(this);
        
		this.init();
	}

	/**
	 * Initializes chat interface components.
	 */
	init() {
		this.createChatInterface();
		this.cacheElements();
		this.initializeDragHandler();
		this.bindEvents();
		this.restorePosition();
		this.restoreVisibility();
		this.restoreSidebarState();
		this.chatAPI.restoreMessages(this.elements.messagesContainer);
		window.addEventListener('beforeunload', this.beforeUnloadHandler);
	}

	/**
	 * Creates the chat panel HTML and adds it to the page.
	 */
	createChatInterface() {
		const chatHTML = this.uiHelpers.getChatPanelHTML();
		document.body.insertAdjacentHTML('beforeend', chatHTML);
	}

	/**
	 * Initializes drag handler for movable chat panel.
	 */
	initializeDragHandler() {
		this.dragHandler = new ChatDragHandler(this.elements.panel);
	}

	/**
	 * Caches DOM element references for performance.
	 */
	cacheElements() {
		this.elements = {
			toggle: document.querySelector('#wp-admin-bar-agenticwp-chat'),
			panel: document.querySelector('.agenticwp-chat-panel'),
			dragHandle: document.querySelector('.agenticwp-drag-handle'),
			close: document.querySelector('.agenticwp-chat-close'),
			clear: document.querySelector('.agenticwp-chat-clear'),
			sendButton: document.querySelector('.agenticwp-send-button'),
			sendText: document.querySelector('.agenticwp-send-text'),
			messageInput: document.querySelector('.agenticwp-message-input'),
			messagesContainer: document.querySelector('.agenticwp-messages')
		};

		this.sidebar = this.elements.panel?.querySelector('.agenticwp-actions-sidebar');
		this.sidebarToggle = this.elements.panel?.querySelector('.agenticwp-actions-toggle');
		this.sidebarClose = this.elements.panel?.querySelector('.agenticwp-actions-close');
	}

	/**
	 * Binds all event handlers for the chat interface.
	 */
	bindEvents() {
		this.elements.toggle.addEventListener('click', (event) => {
			event.preventDefault();
			this.toggleChat();
		});

		this.elements.close.addEventListener('click', () => {
			this.closeChat();
		});

		this.elements.clear.addEventListener('click', () => {
			this.chatAPI.clearChatHistory(this.elements.messagesContainer);
		});

		this.elements.sendButton.addEventListener('click', () => {
			if (this.state.isLoading) {
				this.stopMessage();
			} else {
				this.sendMessage();
			}
		});

		this.elements.messageInput.addEventListener('keydown', (event) => {
			if (event.key === 'Enter' && !event.shiftKey) {
				event.preventDefault();
				this.sendMessage();
			}
		});

		this.elements.messageInput.addEventListener('input', () => {
			this.uiHelpers.autoResizeTextarea(this.elements.messageInput);
		});

		document.addEventListener('keydown', (event) => {
			if (event.key === 'Escape' && this.state.isOpen) {
				this.closeChat();
			}
		});

		document.addEventListener('click', (event) => {
			if (this.state.isOpen && !this.elements.panel.contains(event.target) && !this.elements.toggle.contains(event.target)) {
				this.closeChat();
			}
		});

		this.elements.dragHandle.addEventListener('mousedown', (event) => {
			this.dragHandler.startDrag(event);
		});

		document.addEventListener('mousemove', (event) => {
			this.dragHandler.onDrag(event);
		});

		document.addEventListener('mouseup', () => {
			const position = this.dragHandler.endDrag();
			if (position) {
				this.storePosition(position);
			}
		});

		this.bindSidebarEvents();
	}

	/**
	 * Toggles chat panel visibility.
	 */
	toggleChat() {
		if (this.state.isOpen) {
			this.closeChat();
		} else {
			this.openChat();
		}
	}

	/**
	 * Opens the chat panel.
	 */
	openChat() {
		this.state.isOpen = true;
		this.elements.panel.setAttribute('aria-hidden', 'false');
		this.storeVisibility();
		this.elements.messageInput.focus();
	}

	/**
	 * Closes the chat panel.
	 */
	closeChat() {
		this.state.isOpen = false;
		this.elements.panel.setAttribute('aria-hidden', 'true');
		this.storeVisibility();
		this.elements.toggle.focus();
	}

	/**
	 * Sends a message to the API.
	 *
	 * @return {Promise<void>}
	 */
	async sendMessage() {
		if (!this.validateMessageInput()) {
			return;
		}

		const message = this.elements.messageInput.value.trim();
		await this.chatAPI.sendMessage(
			message,
			this.elements.messageInput,
			this.elements.messagesContainer,
			(loading) => this.setLoading(loading)
		);
	}

	/**
	 * Stops the current message request.
	 */
	stopMessage() {
		this.chatAPI.abortRequest();
		this.setLoading(false);
	}

	/**
	 * Validates message input before sending.
	 *
	 * @return {boolean} True if message is valid.
	 */
	validateMessageInput() {
		const message = this.elements.messageInput.value.trim();
		return message && !this.state.isLoading;
	}

	/**
	 * Sets loading state.
	 *
	 * @param {boolean} loading - Loading state.
	 */
	setLoading(loading) {
		this.state.isLoading = loading;
		this.updateLoadingUI(loading);
	}

	/**
	 * Updates UI to reflect loading state.
	 *
	 * @param {boolean} loading - Loading state.
	 */
	updateLoadingUI(loading) {
		this.elements.messageInput.disabled = loading;
		this.elements.sendButton.setAttribute('aria-label', loading ? 'Stop generation' : 'Send message');
		this.elements.sendText.textContent = loading ? 'Stop' : 'Send';
	}

	/**
	 * Stores chat panel position.
	 *
	 * @param {Object} position - Position object with x and y coordinates.
	 */
	storePosition(position) {
		this.storage.set('agenticwp_panel_position', position);
	}

	/**
	 * Gets stored panel position.
	 *
	 * @return {Object|null} Stored position or null.
	 */
	getStoredPosition() {
		return this.storage.get('agenticwp_panel_position');
	}

	/**
	 * Restores panel position from storage.
	 */
	restorePosition() {
		const position = this.getStoredPosition();
		if (!position) return;
        
		const viewportWidth = window.innerWidth;
		const viewportHeight = window.innerHeight;
		const panelWidth = 500;
		const panelHeight = 600;
        
		const validX = Math.max(0, Math.min(position.x, viewportWidth - panelWidth));
		const validY = Math.max(0, Math.min(position.y, viewportHeight - panelHeight));
        
		this.elements.panel.style.left = `${validX}px`;
		this.elements.panel.style.top = `${validY}px`;
		this.elements.panel.style.right = 'auto';
	}

	/**
	 * Gets stored visibility state.
	 *
	 * @return {boolean} Stored visibility state.
	 */
	getStoredVisibility() {
		return this.storage.get('agenticwp_panel_visibility', false);
	}

	/**
	 * Stores visibility state.
	 */
	storeVisibility() {
		this.storage.set('agenticwp_panel_visibility', this.state.isOpen);
	}

	/**
	 * Handles beforeunload event to prevent navigation during active responses.
	 *
	 * @param {Event} event - Browser beforeunload event.
	 */
	handleBeforeUnload(event) {
		if (!this.state.isLoading) {
			return;
		}

		event.preventDefault();
		event.returnValue = '';
	}

	/**
	 * Restores visibility state from storage.
	 */
	restoreVisibility() {
		if (this.state.isOpen) {
			this.elements.panel.setAttribute('aria-hidden', 'false');
		}
	}

	/**
	 * Binds sidebar event handlers.
	 */
	bindSidebarEvents() {
		if (!this.sidebarToggle || !this.sidebar || !this.sidebarClose) return;

		this.sidebarToggle.addEventListener('click', () => {
			this.toggleSidebar();
		});

		this.sidebarClose.addEventListener('click', () => {
			this.closeSidebar();
		});

		document.addEventListener('keydown', (e) => {
			if (e.key === 'Escape' && this.isSidebarOpen()) {
				this.closeSidebar();
			}
		});

		this.sidebar.addEventListener('click', (e) => {
			if (e.target === this.sidebar && window.innerWidth <= 600) {
				this.closeSidebar();
			}
		});
	}

	/**
	 * Toggles sidebar visibility.
	 */
	toggleSidebar() {
		if (this.isSidebarOpen()) {
			this.closeSidebar();
		} else {
			this.openSidebar();
		}
	}

	/**
	 * Opens the actions sidebar.
	 */
	openSidebar() {
		if (!this.sidebar || !this.sidebarToggle) return;

		this.sidebar.classList.add('is-open');
		this.sidebar.setAttribute('aria-hidden', 'false');
		this.sidebarToggle.setAttribute('aria-expanded', 'true');
		this.sidebarToggle.setAttribute('aria-label', 'Close quick actions');

		this.loadSidebarActions();

		setTimeout(() => {
			const firstButton = this.sidebar.querySelector('button:not(.agenticwp-actions-close)');
			firstButton?.focus();
		}, 300);

		this.storeSidebarState(true);
	}

	/**
	 * Closes the actions sidebar.
	 */
	closeSidebar() {
		if (!this.sidebar || !this.sidebarToggle) return;

		this.sidebar.classList.remove('is-open');
		this.sidebar.setAttribute('aria-hidden', 'true');
		this.sidebarToggle.setAttribute('aria-expanded', 'false');
		this.sidebarToggle.setAttribute('aria-label', 'Open quick actions');

		this.sidebarToggle.focus();
		this.storeSidebarState(false);
	}

	/**
	 * Checks if sidebar is open.
	 *
	 * @return {boolean} True if sidebar is open.
	 */
	isSidebarOpen() {
		return this.sidebar?.classList.contains('is-open') || false;
	}

	/**
	 * Stores sidebar open state.
	 *
	 * @param {boolean} isOpen - Whether sidebar is open.
	 */
	storeSidebarState(isOpen) {
		try {
			localStorage.setItem('agenticwp_sidebar_open', JSON.stringify(isOpen));
		} catch (e) {
		}
	}

	/**
	 * Restores sidebar state from storage.
	 */
	restoreSidebarState() {
		try {
			const stored = localStorage.getItem('agenticwp_sidebar_open');
			if (stored && JSON.parse(stored)) {
				this.openSidebar();
			}
		} catch (e) {
		}
	}

	/**
	 * Loads available actions from API.
	 *
	 * @return {Promise<void>}
	 */
	async loadSidebarActions() {
		if (this.actionsLoaded || !this.sidebar) return;

		const content = this.sidebar.querySelector('.agenticwp-actions-content');
		if (!content) return;

		try {
			const response = await fetch(agenticwp_ajax.ajax_url, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/x-www-form-urlencoded',
				},
				body: new URLSearchParams({
					action: 'agenticwp_get_actions',
					_ajax_nonce: agenticwp_ajax.nonce
				})
			});

			if (!response.ok) {
				throw new Error(`HTTP ${response.status}: ${response.statusText}`);
			}

			const data = await response.json();

			if (data.success) {
				this.actionsData = data.data.actions;
				this.renderActions(data.data.actions);
				this.actionsLoaded = true;
			} else {
				this.renderActionsError();
			}
		} catch (error) {
			this.renderActionsError();
		}
	}

	/**
	 * Renders action buttons in sidebar.
	 *
	 * @param {Object} actions - Actions data from API.
	 */
	renderActions(actions) {
		const content = this.sidebar.querySelector('.agenticwp-actions-content');
		if (!content) return;

		let html = '';
		const categories = this.groupActionsByCategory(actions);

		Object.entries(categories).forEach(([category, categoryActions]) => {
			html += `
				<div class="agenticwp-actions-category">
					<h4 class="agenticwp-actions-category-title">${this.uiHelpers.escapeHtml(category)}</h4>
					<div class="agenticwp-actions-list">
			`;

			categoryActions.forEach(action => {
				const icon = this.getActionIcon(action);
				html += `
					<button
						class="agenticwp-action-button"
						data-action-key="${this.uiHelpers.escapeHtml(action.key)}"
						title="${this.uiHelpers.escapeHtml(action.prompt)}"
					>
						<span class="dashicons dashicons-${this.uiHelpers.escapeHtml(icon)}"></span>
						<span class="agenticwp-action-name">${this.uiHelpers.escapeHtml(action.name)}</span>
					</button>
				`;
			});

			html += `
					</div>
				</div>
			`;
		});

		content.innerHTML = html;
		this.bindActionButtons();
	}

	/**
	 * Groups actions by category.
	 *
	 * @param {Object} actions - Actions object.
	 * @return {Object} Grouped actions by category.
	 */
	groupActionsByCategory(actions) {
		const categories = {};

		Object.entries(actions).forEach(([key, action]) => {
			const category = action.category || 'General';
			if (!categories[category]) {
				categories[category] = [];
			}
			categories[category].push({ ...action, key });
		});

		return categories;
	}

	/**
	 * Gets icon name for an action.
	 *
	 * @param {Object} action - Action object.
	 * @return {string} Dashicon name.
	 */
	getActionIcon(action) {
		if (!action) {
			return 'admin-generic';
		}

		const categoryKey = String(action.category_key || '').toLowerCase();
		const categoryName = String(action.category || '').toLowerCase();
		const isCustom = action.is_custom === true
			|| action.is_custom === 'true'
			|| (categoryKey && categoryKey === 'custom');

		if (isCustom) {
			return 'admin-generic';
		}

		const iconMap = {
			content_creation: 'welcome-write-blog',
			content: 'welcome-write-blog',
			seo_optimization: 'chart-line',
			seo: 'chart-line',
			uncategorized: 'category',
		};

		if (iconMap[categoryKey]) {
			return iconMap[categoryKey];
		}

		if (iconMap[categoryName]) {
			return iconMap[categoryName];
		}

		return action.icon || 'admin-generic';
	}

	/**
	 * Binds click handlers to action buttons.
	 */
	bindActionButtons() {
		const actionButtons = this.sidebar.querySelectorAll('.agenticwp-action-button');

		actionButtons.forEach(button => {
			button.addEventListener('click', (e) => {
				const actionKey = e.currentTarget.dataset.actionKey;
				this.selectAction(actionKey);
			});
		});
	}

	/**
	 * Selects an action and fills input with prompt.
	 *
	 * @param {string} actionKey - Action key to select.
	 */
	selectAction(actionKey) {
		if (!this.actionsData || !this.actionsData[actionKey]) {
			this.closeSidebar();
			return;
		}

		const action = this.actionsData[actionKey];
		const messageInput = this.elements.messageInput;

		if (messageInput) {
			messageInput.value = action.prompt || '';
			this.uiHelpers.autoResizeTextarea(messageInput);
			messageInput.focus();
			messageInput.setSelectionRange(messageInput.value.length, messageInput.value.length);
		}

		this.closeSidebar();
	}

	/**
	 * Renders error message when actions fail to load.
	 */
	renderActionsError() {
		const content = this.sidebar.querySelector('.agenticwp-actions-content');
		if (!content) return;

		content.innerHTML = `
			<div class="agenticwp-actions-error">
				<span class="dashicons dashicons-warning"></span>
				<p>Failed to load actions. Please try again.</p>
				<button class="agenticwp-button agenticwp-button--small" onclick="this.closest('.agenticwp-actions-sidebar').dispatchEvent(new CustomEvent('reload-actions'))">
					Retry
				</button>
			</div>
		`;
	}

	/**
	 * Cleans up resources and event listeners.
	 */
	destroy() {
		window.removeEventListener('beforeunload', this.beforeUnloadHandler);
	}
}

if (typeof window !== 'undefined') {
	window.AgenticWPChat = AgenticWPChat;
}

if (typeof module !== 'undefined' && module.exports) {
	module.exports = AgenticWPChat;
}

if (document.readyState === 'loading') {
	document.addEventListener('DOMContentLoaded', () => {
		if (typeof agenticwp_ajax !== 'undefined') {
			new AgenticWPChat();
		}
	});
} else {
	if (typeof agenticwp_ajax !== 'undefined') {
		new AgenticWPChat();
	}
}
