/**
 * WP PowerSuite Quick Launcher
 *
 * @package WP_PowerSuite\Admin\Assets
 * @since 1.0.0
 */

(function() {
	'use strict';

	/**
	 * Command Palette (Ctrl+Shift+K / Cmd+Shift+K): search modules and admin pages
	 * Uses Ctrl+Shift+K to avoid conflict with WordPress's built-in Command Palette (Ctrl+K).
	 * Type module name, then Enter to enable/disable. Or navigate to Settings, Performance, etc.
	 */
	const WPPSCommandPalette = {
		RECENT_KEY: 'wpps_cp_recent_v1',
		navItems: [
			{ type: 'nav', label: 'Go to Modules', url: 'admin.php?page=powersuite', keywords: 'modules main dashboard' },
			{ type: 'nav', label: 'Go to Settings', url: 'admin.php?page=powersuite-settings', keywords: 'settings configurations presets import export ai connections openai gemini claude openrouter deepseek grok' },
			{ type: 'nav', label: 'Go to License', url: 'admin.php?page=powersuite-license', keywords: 'license activate' }
		],
		allItems: [],
		modules: [],
		dataLoaded: false,
		loadPromise: null,
		modal: null,
		input: null,
		list: null,
		selectedIndex: 0,
		bodyScrollPrev: '',

		_escape: function(s) {
			return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
		},
		_palette: function() {
			return (window.wpPowerSuite && window.wpPowerSuite.palette) ? window.wpPowerSuite.palette : {};
		},
		_isMac: function() {
			return typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent || '');
		},
		_hintShortcutLabel: function() {
			var sh = (window.wpPowerSuite && window.wpPowerSuite.quickLauncherShortcut) || 'ctrl-shift-k';
			if (this._isMac()) {
				var mac = { 'ctrl-k': 'âŒ˜K', 'ctrl-shift-k': 'â‡§âŒ˜K', 'alt-p': 'âŒ¥P', 'ctrl-alt-k': 'âŒƒâŒ¥K' };
				return mac[sh] || mac['ctrl-shift-k'];
			}
			var win = { 'ctrl-k': 'Ctrl+K', 'ctrl-shift-k': 'Ctrl+Shift+K', 'alt-p': 'Alt+P', 'ctrl-alt-k': 'Ctrl+Alt+K' };
			return win[sh] || win['ctrl-shift-k'];
		},
		_loadRecent: function() {
			try {
				var raw = sessionStorage.getItem(this.RECENT_KEY);
				if (!raw) return [];
				var a = JSON.parse(raw);
				return Array.isArray(a) ? a.slice(0, 8) : [];
			} catch (err) {
				return [];
			}
		},
		_saveRecent: function(arr) {
			try {
				sessionStorage.setItem(this.RECENT_KEY, JSON.stringify(arr.slice(0, 8)));
			} catch (err) {}
		},
		_pushRecent: function(entry) {
			var items = this._loadRecent();
			var key = entry.kind === 'nav' ? 'nav:' + entry.url : 'mod:' + entry.id;
			items = items.filter(function(x) {
				var k = x.kind === 'nav' ? 'nav:' + x.url : 'mod:' + x.id;
				return k !== key;
			});
			items.unshift(entry);
			this._saveRecent(items);
		},
		_parseQuery: function(q) {
			return String(q || '').trim().toLowerCase().split(/\s+/).filter(Boolean);
		},
		_matchesTokens: function(haystack, tokens) {
			if (!tokens.length) return true;
			var h = haystack.toLowerCase();
			for (var ti = 0; ti < tokens.length; ti++) {
				if (h.indexOf(tokens[ti]) < 0) return false;
			}
			return true;
		},
		_navHaystack: function(n) {
			return (n.label || '') + ' ' + (n.keywords || '');
		},
		_rowKey: function(row) {
			if (row.type === 'nav') return 'nav:' + (row.data.url || '');
			if (row.type === 'module') return 'mod:' + (row.data.id || '');
			return '';
		},
		_moduleScore: function(m, tokens) {
			if (!tokens.length) return 0;
			var name = (m.name || '').toLowerCase();
			var kw = (m.keywords || '').toLowerCase();
			var desc = (m.description || '').toLowerCase();
			var cat = (m.category || '').toLowerCase();
			var score = 0;
			for (var i = 0; i < tokens.length; i++) {
				var tok = tokens[i];
				var ni = name.indexOf(tok);
				if (ni >= 0) score += 200 - Math.min(ni, 100);
				else if (kw.indexOf(tok) >= 0) score += 80;
				else if (cat.indexOf(tok) >= 0) score += 40;
				else if (desc.indexOf(tok) >= 0) score += 20;
			}
			return score;
		},
		_findNavByUrl: function(url) {
			for (var i = 0; i < this.navItems.length; i++) {
				if (this.navItems[i].url === url) return this.navItems[i];
			}
			return null;
		},
		_findModuleById: function(id) {
			for (var j = 0; j < this.modules.length; j++) {
				if (this.modules[j].id === id) return this.modules[j];
			}
			return null;
		},
		_buildRecentRows: function() {
			var self = this;
			var out = [];
			this._loadRecent().forEach(function(rec) {
				if (rec.kind === 'nav') {
					var nav = self._findNavByUrl(rec.url);
					if (nav) out.push({ type: 'nav', data: nav, fromRecent: true });
				} else if (rec.kind === 'module') {
					var mod = self._findModuleById(rec.id);
					if (mod) {
						out.push({ type: 'module', data: mod, label: (mod.enabled ? 'Disable ' : 'Enable ') + mod.name, fromRecent: true });
					}
				}
			});
			return out;
		},

		init: function() {
			if (!window.wpPowerSuite || !window.wpPowerSuite.ajaxUrl) return;
			if (!window.wpPowerSuite.licensePageUrl) {
				this.navItems = this.navItems.filter(function(i) { return i.label.indexOf('License') < 0; });
			}
			document.addEventListener('keydown', this.onShortcutKeyDown.bind(this));
		},

		_applyPayload: function(data) {
			if (data && data.navItems && data.navItems.length) {
				this.navItems = data.navItems.map(function(n) {
					return { type: 'nav', label: n.label, url: n.url, keywords: n.keywords || '' };
				});
			} else if (!window.wpPowerSuite.licensePageUrl) {
				this.navItems = this.navItems.filter(function(i) { return i.label.indexOf('License') < 0; });
			}
			this.modules = (data && data.modules) ? data.modules : [];
			this.dataLoaded = true;
		},

		loadData: function(force) {
			var self = this;
			if (!force && this.dataLoaded) {
				return Promise.resolve();
			}
			if (this.loadPromise && !force) {
				return this.loadPromise;
			}
			var action = window.wpPowerSuite.action && window.wpPowerSuite.action.commandPaletteData;
			if (!action) {
				return Promise.reject(new Error('command palette action missing'));
			}
			this.loadPromise = new Promise(function(resolve, reject) {
				jQuery.post(window.wpPowerSuite.ajaxUrl, {
					action: action,
					nonce: window.wpPowerSuite.nonce
				}).done(function(res) {
					if (res && res.success && res.data) {
						self._applyPayload(res.data);
						resolve();
					} else {
						reject(new Error((res && res.data && res.data.message) ? res.data.message : 'load failed'));
					}
				}).fail(function() {
					reject(new Error('request failed'));
				}).always(function() {
					self.loadPromise = null;
				});
			});
			return this.loadPromise;
		},

		showLoadingState: function() {
			if (!this.list) return;
			var p = this._palette();
			this.list.innerHTML = '';
			var wrap = document.createElement('li');
			wrap.className = 'wpps-command-palette-item--empty';
			wrap.setAttribute('role', 'presentation');
			wrap.innerHTML = '<div class="wpps-cp-empty-title">' + this._escape(p.loading || 'Loadingâ€¦') + '</div>';
			this.list.appendChild(wrap);
		},

		showErrorState: function() {
			if (!this.list) return;
			var p = this._palette();
			this.list.innerHTML = '';
			var wrap = document.createElement('li');
			wrap.className = 'wpps-command-palette-item--empty';
			wrap.setAttribute('role', 'presentation');
			wrap.innerHTML = '<div class="wpps-cp-empty-title">' + this._escape(p.loadError || 'Could not load Quick Launcher data.') + '</div>';
			this.list.appendChild(wrap);
		},

		onShortcutKeyDown: function(e) {
			if (this.modal && this.modal.classList.contains('is-open') && e.key === 'Escape') {
				e.preventDefault();
				this.hide();
				return;
			}
			var shortcut = (window.wpPowerSuite && window.wpPowerSuite.quickLauncherShortcut) || 'ctrl-shift-k';
			var lk = typeof e.key === 'string' && e.key.length === 1 ? e.key.toLowerCase() : e.key;
			var match = false;
			if (shortcut === 'ctrl-k') {
				match = (e.metaKey || e.ctrlKey) && lk === 'k' && !e.shiftKey && !e.altKey;
			} else if (shortcut === 'ctrl-shift-k') {
				match = (e.metaKey || e.ctrlKey) && e.shiftKey && lk === 'k';
			} else if (shortcut === 'alt-p') {
				match = e.altKey && lk === 'p';
			} else if (shortcut === 'ctrl-alt-k') {
				match = (e.metaKey || e.ctrlKey) && e.altKey && lk === 'k';
			}
			if (match) {
				e.preventDefault();
				e.stopPropagation();
				this.toggle();
			}
		},

		toggle: function() {
			if (this.modal && this.modal.classList.contains('is-open')) {
				this.hide();
			} else {
				this.show();
			}
		},

		show: function() {
			if (!this.modal) {
				this.create();
			}
			this.modal.classList.add('is-open');
			this.bodyScrollPrev = document.body.style.overflow;
			document.body.style.overflow = 'hidden';
			this.input.value = '';
			this.showLoadingState();
			var self = this;
			this.loadData().then(function() {
				if (!self.modal || !self.modal.classList.contains('is-open')) return;
				self.filter(self.input.value || '');
			}).catch(function() {
				if (!self.modal || !self.modal.classList.contains('is-open')) return;
				self.showErrorState();
			});
			requestAnimationFrame(function() {
				if (self.input) self.input.focus();
			});
			if (this.modal) this.modal.setAttribute('aria-hidden', 'false');
		},

		hide: function() {
			if (this.modal) {
				this.modal.classList.remove('is-open');
				this.modal.setAttribute('aria-hidden', 'true');
			}
			document.body.style.overflow = this.bodyScrollPrev || '';
		},

		create: function() {
			var self = this;
			var p = this._palette();
			var title = p.title || 'Quick Launcher';
			var sub = p.subtitle || '';
			var ph = p.searchPlaceholder || 'Search modules, pages, or go toâ€¦';
			var searchLabel = p.searchLabel || 'Search';
			var hl = this._hintShortcutLabel();
			var hinO = p.hintOpen || 'Open';
			var hinNav = p.hintNavigate || 'Navigate';
			var hinSel = p.hintSelect || 'Select';
			var hinClose = p.hintClose || 'Close';
			var footerHtml =
				'<kbd class="wpps-cp-kbd">' + this._escape(hl) + '</kbd> <span class="wpps-cp-footer-txt">' + this._escape(hinO) + '</span>' +
				' <span class="wpps-cp-footer-sep" aria-hidden="true">Â·</span> ' +
				'<span class="wpps-cp-footer-arrows" aria-hidden="true">â†‘â†“</span> <span class="wpps-cp-footer-txt">' + this._escape(hinNav) + '</span>' +
				' <span class="wpps-cp-footer-sep" aria-hidden="true">Â·</span> ' +
				'<kbd class="wpps-cp-kbd">Enter</kbd> <span class="wpps-cp-footer-txt">' + this._escape(hinSel) + '</span>' +
				' <span class="wpps-cp-footer-sep" aria-hidden="true">Â·</span> ' +
				'<kbd class="wpps-cp-kbd">Esc</kbd> <span class="wpps-cp-footer-txt">' + this._escape(hinClose) + '</span>';
			this.modal = document.createElement('div');
			this.modal.className = 'wpps-command-palette';
			this.modal.setAttribute('aria-hidden', 'true');
			this.modal.innerHTML =
				'<div class="wpps-command-palette-backdrop" tabindex="-1" aria-hidden="true"></div>' +
				'<div class="wpps-command-palette-box" role="dialog" aria-modal="true" aria-labelledby="wpps-cp-title">' +
					'<div class="wpps-command-palette-header">' +
						'<span class="dashicons dashicons-search wpps-command-palette-dashicon" aria-hidden="true"></span>' +
						'<div class="wpps-command-palette-headings">' +
							'<div id="wpps-cp-title" class="wpps-command-palette-title">' + this._escape(title) + '</div>' +
							(sub ? '<div class="wpps-command-palette-sub">' + this._escape(sub) + '</div>' : '') +
						'</div>' +
					'</div>' +
					'<div class="wpps-command-palette-input-wrap">' +
						'<label for="wpps-cp-input" class="screen-reader-text">' + this._escape(searchLabel) + '</label>' +
						'<input type="text" id="wpps-cp-input" class="wpps-command-palette-input" placeholder="' + this._escape(ph) + '" autocomplete="off" autocapitalize="off" spellcheck="false" />' +
					'</div>' +
					'<div class="wpps-command-palette-list-wrap">' +
						'<ul class="wpps-command-palette-list" role="listbox" aria-labelledby="wpps-cp-title"></ul>' +
					'</div>' +
					'<div class="wpps-command-palette-footer">' + footerHtml + '</div>' +
				'</div>';
			document.body.appendChild(this.modal);

			var backdrop = this.modal.querySelector('.wpps-command-palette-backdrop');
			backdrop.addEventListener('click', this.hide.bind(this));

			this.input = this.modal.querySelector('.wpps-command-palette-input');
			this.input.addEventListener('input', function() { self.filter(self.input.value); });
			this.input.addEventListener('keydown', this.onInputKeyDown.bind(this));

			this.list = this.modal.querySelector('.wpps-command-palette-list');
			this.modal.querySelector('.wpps-command-palette-box').addEventListener('click', function(e) { e.stopPropagation(); });
		},

		buildItems: function(qRaw) {
			var self = this;
			var tokens = this._parseQuery(qRaw);
			var pal = this._palette();
			var secRecent = pal.recent || 'Recent';
			var secPlaces = pal.navigation || 'Places';
			var secModules = pal.modulesSection || 'Modules';
			var items = [];
			var excluded = {};
			if (!tokens.length) {
				var recentRows = self._buildRecentRows();
				if (recentRows.length) {
					items.push({ type: 'section', label: secRecent });
					recentRows.forEach(function(r) {
						items.push(r);
						excluded[self._rowKey(r)] = true;
					});
				}
			}
			var navFiltered = [];
			this.navItems.forEach(function(n) {
				var hs = self._navHaystack(n);
				if (!self._matchesTokens(hs, tokens)) return;
				var row = { type: 'nav', data: n };
				if (excluded[self._rowKey(row)]) return;
				navFiltered.push(row);
			});
			var modFiltered = [];
			this.modules.forEach(function(m) {
				var hay = (m.keywords || '') + ' ' + (m.name || '') + ' ' + (m.description || '') + ' ' + (m.category || '');
				if (!self._matchesTokens(hay, tokens)) return;
				var row = { type: 'module', data: m, label: (m.enabled ? 'Disable ' : 'Enable ') + m.name };
				if (excluded[self._rowKey(row)]) return;
				modFiltered.push(row);
			});
			if (tokens.length) {
				modFiltered.sort(function(a, b) {
					return self._moduleScore(b.data, tokens) - self._moduleScore(a.data, tokens);
				});
			}
			if (navFiltered.length) {
				items.push({ type: 'section', label: secPlaces });
				items = items.concat(navFiltered);
			}
			if (modFiltered.length) {
				items.push({ type: 'section', label: secModules });
				items = items.concat(modFiltered);
			}
			return items;
		},

		filter: function(q) {
			this.allItems = this.buildItems(q);
			this.render(this.allItems);
			this.selectedIndex = 0;
			while (this.selectedIndex < this.allItems.length && this.allItems[this.selectedIndex] && this.allItems[this.selectedIndex].type === 'section') {
				this.selectedIndex++;
			}
			if (this.selectedIndex >= this.allItems.length) this.selectedIndex = 0;
			this.updateSelection();
		},

		render: function(items) {
			var self = this;
			var p = this._palette();
			this.list.innerHTML = '';
			if (items.length === 0) {
				var wrap = document.createElement('li');
				wrap.className = 'wpps-command-palette-item--empty';
				wrap.setAttribute('role', 'presentation');
				var nh = p.noResultsHint ? '<div class="wpps-cp-empty-hint">' + this._escape(p.noResultsHint) + '</div>' : '';
				wrap.innerHTML = '<div class="wpps-cp-empty-title">' + this._escape(p.noResults || 'No matches') + '</div>' + nh;
				this.list.appendChild(wrap);
				return;
			}
			items.forEach(function(item, i) {
				var li = document.createElement('li');
				var isSection = item.type === 'section';
				li.setAttribute('role', isSection ? 'presentation' : 'option');
				li.className = 'wpps-command-palette-item' + (isSection ? ' wpps-cp-section' : '') + (i === self.selectedIndex ? ' is-selected' : '');
				li.dataset.index = String(i);
				if (isSection) {
					li.setAttribute('role', 'presentation');
					li.textContent = item.label || '';
				} else {
					var badgeNav = (p.badgeNav || 'Open');
					var badgeOn = (p.badgeToggleOn || 'Enable');
					var badgeOff = (p.badgeToggleOff || 'Disable');
					var label = item.type === 'nav' ? item.data.label : ((item.data && item.data.name) ? item.data.name : '');
					var sub = '';
					if (item.type === 'nav') {
						sub = item.data.keywords ? String(item.data.keywords).split(/\s+/).slice(0, 3).join(', ') : '';
					} else if (item.data.category) {
						sub = item.data.category;
					}
					var badge = item.type === 'nav'
						? '<span class="wpps-cp-badge wpps-cp-badge--nav">' + self._escape(badgeNav) + '</span>'
						: '<span class="wpps-cp-badge' + (item.data.enabled ? ' wpps-cp-badge--off' : ' wpps-cp-badge--on') + '">' + self._escape(item.data.enabled ? badgeOff : badgeOn) + '</span>';
					if (item.type === 'module') {
						li.dataset.moduleState = item.data.enabled ? 'on' : 'off';
					}
					li.innerHTML =
						'<div class="wpps-cp-row-main">' +
							'<span class="wpps-cp-label">' + self._escape(label || '') + '</span>' +
							badge +
						'</div>' +
						(sub ? '<span class="wpps-cp-meta">' + self._escape(sub) + '</span>' : '');
					li.setAttribute('aria-selected', i === self.selectedIndex ? 'true' : 'false');
					li.addEventListener('mouseenter', function() {
						self.selectedIndex = parseInt(li.dataset.index, 10);
						self.updateSelection();
					});
					li.addEventListener('click', function() { self.execute(items[parseInt(li.dataset.index, 10)]); });
				}
				self.list.appendChild(li);
			});
		},

		updateSelection: function() {
			var domItems = this.list.querySelectorAll('.wpps-command-palette-item');
			var self = this;
			domItems.forEach(function(el, i) {
				el.classList.toggle('is-selected', i === self.selectedIndex);
				if (el.getAttribute('role') === 'option') {
					el.setAttribute('aria-selected', i === self.selectedIndex ? 'true' : 'false');
				}
			});
			domItems[this.selectedIndex] && domItems[this.selectedIndex].scrollIntoView({ block: 'nearest' });
		},

		_firstSelectableIndex: function() {
			var i = 0;
			while (i < this.allItems.length && this.allItems[i] && this.allItems[i].type === 'section') i++;
			return Math.min(i, this.allItems.length - 1);
		},

		_lastSelectableIndex: function() {
			var i = this.allItems.length - 1;
			while (i >= 0 && this.allItems[i] && this.allItems[i].type === 'section') i--;
			return Math.max(i, 0);
		},

		onInputKeyDown: function(e) {
			var domItems = this.list.querySelectorAll('.wpps-command-palette-item');
			if (e.key === 'ArrowDown') {
				e.preventDefault();
				do {
					this.selectedIndex = Math.min(this.selectedIndex + 1, domItems.length - 1);
				} while (this.allItems[this.selectedIndex] && this.allItems[this.selectedIndex].type === 'section' && this.selectedIndex < domItems.length - 1);
				this.updateSelection();
			} else if (e.key === 'ArrowUp') {
				e.preventDefault();
				do {
					this.selectedIndex = Math.max(this.selectedIndex - 1, 0);
				} while (this.allItems[this.selectedIndex] && this.allItems[this.selectedIndex].type === 'section' && this.selectedIndex > 0);
				this.updateSelection();
			} else if (e.key === 'Home') {
				e.preventDefault();
				this.selectedIndex = this._firstSelectableIndex();
				this.updateSelection();
			} else if (e.key === 'End') {
				e.preventDefault();
				this.selectedIndex = this._lastSelectableIndex();
				this.updateSelection();
			} else if (e.key === 'Enter' && domItems.length > 0 && this.allItems[this.selectedIndex] && this.allItems[this.selectedIndex].type !== 'section') {
				e.preventDefault();
				this.execute(this.allItems[this.selectedIndex]);
			} else if (e.key === 'Escape') {
				e.preventDefault();
				this.hide();
			}
		},

		execute: function(item) {
			if (!item || item.type === 'section') return;
			if (item.type === 'nav') {
				this._pushRecent({ kind: 'nav', url: item.data.url });
				var mx = (window.wpPowerSuite.ajaxUrl || '').match(/^(.+)\/admin-ajax\.php/);
				window.location.href = (mx ? mx[1] + '/' : '') + item.data.url;
				return;
			}
			if (item.type === 'module') {
				this._pushRecent({ kind: 'module', id: item.data.id });
				this.toggleModule(item.data);
			}
		},

		toggleModule: function(module) {
			var enable = !module.enabled;
			if (enable && module.is_pro && !window.wpPowerSuite.licenseValid) {
				var lm = window.wpPowerSuite.strings && window.wpPowerSuite.strings.licenseRequired;
				this.showToast(lm ? lm : 'License required for premium modules');
				return;
			}
			this.hide();
			var self = this;
			var st = window.wpPowerSuite.strings || {};
			jQuery.post(window.wpPowerSuite.ajaxUrl, {
				action: window.wpPowerSuite.action.toggleModule,
				nonce: window.wpPowerSuite.nonce,
				module_id: module.id,
				enable: enable ? 1 : 0
			}).done(function(res) {
				if (res.success) {
					self.showToast(
						(enable ? (st.enabled || 'Enabled') : (st.disabled || 'Disabled')) + ' ' + module.name
					);
					module.enabled = enable;
					self.dataLoaded = false;
				} else {
					self.showToast(res.data && res.data.message ? res.data.message : (st.error || 'Failed'));
				}
			}).fail(function() {
				self.showToast(st.error || 'Request failed');
			});
		},

		showToast: function(msg) {
			var t = document.createElement('div');
			t.className = 'wp-powersuite-toast wpps-command-palette-toast';
			t.textContent = msg;
			document.body.appendChild(t);
			setTimeout(function() {
				t.style.opacity = '0';
				t.style.transition = 'opacity 0.2s';
				setTimeout(function() { if (t.parentNode) t.remove(); }, 200);
			}, 2600);
		}
	};

	function onReady() {
		WPPSCommandPalette.init();
	}
	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', onReady);
	} else {
		onReady();
	}
})();
