// Cluster Members Component
class ClusterMembersComponent extends Component {
	constructor(container, viewModel, eventBus) {
		super(container, viewModel, eventBus);
		
		logger.debug('ClusterMembersComponent: Constructor called');
		logger.debug('ClusterMembersComponent: Container:', container);
		logger.debug('ClusterMembersComponent: Container ID:', container?.id);
		logger.debug('ClusterMembersComponent: Container innerHTML:', container?.innerHTML);
		
		// Track if we're in the middle of a render operation
		this.renderInProgress = false;
		this.lastRenderData = null;
		
		// Ensure initial render happens even if no data
		setTimeout(() => {
			if (this.isMounted && !this.renderInProgress) {
				logger.debug('ClusterMembersComponent: Performing initial render check');
				this.render();
			}
		}, 200);

		// Drawer state for desktop (shared singleton)
		this.drawer = new DrawerComponent();
		
		// Terminal panel container (shared with drawer)
		this.terminalPanelContainer = null;
		
		// Selection state for highlighting
		this.selectedMemberIp = null;
		
		// Filter state - now supports multiple active filters
		this.activeFilters = []; // Array of {labelKey, labelValue} objects
		this.allMembers = []; // Store unfiltered members
	}

	// Determine if we should use desktop drawer behavior
	isDesktop() {
		return this.drawer.isDesktop();
	}

	// Extract all unique label keys from members
	extractLabelKeys(members) {
		const labelKeys = new Set();
		
		members.forEach(member => {
			if (member.labels && typeof member.labels === 'object') {
				Object.keys(member.labels).forEach(key => {
					labelKeys.add(key);
				});
			}
		});
		
		return Array.from(labelKeys).sort();
	}

	// Extract unique values for a specific label key from members
	extractLabelValuesForKey(members, labelKey) {
		const labelValues = new Set();
		
		members.forEach(member => {
			if (member.labels && typeof member.labels === 'object' && member.labels[labelKey]) {
				labelValues.add(member.labels[labelKey]);
			}
		});
		
		return Array.from(labelValues).sort();
	}

	// Filter members based on current active filters
	filterMembers(members) {
		if (!this.activeFilters || this.activeFilters.length === 0) {
			return members;
		}
		
		return members.filter(member => {
			if (!member.labels || typeof member.labels !== 'object') {
				return false;
			}
			
			// All active filters must match (AND logic)
			return this.activeFilters.every(filter => {
				if (filter.labelKey && filter.labelValue) {
					// Both key and value specified - exact match
					return member.labels[filter.labelKey] === filter.labelValue;
				} else if (filter.labelKey && !filter.labelValue) {
					// Only key specified - member must have this key
					return member.labels.hasOwnProperty(filter.labelKey);
				} else if (!filter.labelKey && filter.labelValue) {
					// Only value specified - member must have this value for any key
					return Object.values(member.labels).includes(filter.labelValue);
				}
				return true;
			});
		});
	}

	// Get currently filtered members (public method for external access)
	getFilteredMembers() {
		return this.filterMembers(this.allMembers);
	}

	// Update filter dropdowns with current label data
	updateFilterDropdowns() {
		// Get currently filtered members to determine available options
		const filteredMembers = this.filterMembers(this.allMembers);
		
		// Extract available label keys from filtered members
		const availableLabelKeys = this.extractLabelKeys(filteredMembers);
		
		// Update label key dropdown
		const keySelect = document.getElementById('label-key-filter');
		if (keySelect) {
			const currentKey = keySelect.value;
			keySelect.innerHTML = '<option value="">All Labels</option>';
			availableLabelKeys.forEach(key => {
				const option = document.createElement('option');
				option.value = key;
				option.textContent = key;
				keySelect.appendChild(option);
			});
			
			// Restore selection if it still exists
			if (currentKey && availableLabelKeys.includes(currentKey)) {
				keySelect.value = currentKey;
			} else {
				keySelect.value = '';
			}
		}
		
		// Update label value dropdown based on selected key
		this.updateValueDropdown();
		
		// Update clear button state
		this.updateClearButtonState();
	}

	// Update clear button state based on current active filters
	updateClearButtonState() {
		const clearBtn = document.getElementById('clear-filters-btn');
		if (clearBtn) {
			const hasFilters = this.activeFilters && this.activeFilters.length > 0;
			clearBtn.disabled = !hasFilters;
			logger.debug('ClusterMembersComponent: Clear button state updated:', {
				hasFilters,
				disabled: clearBtn.disabled,
				activeFilters: this.activeFilters
			});
		}
	}

	// Update the value dropdown based on the currently selected key
	updateValueDropdown() {
		const valueSelect = document.getElementById('label-value-filter');
		if (!valueSelect) return;
		
		const currentValue = valueSelect.value;
		valueSelect.innerHTML = '<option value="">All Values</option>';
		
		// Get currently filtered members to determine available values
		const filteredMembers = this.filterMembers(this.allMembers);
		
		// If a key is selected, show only values for that key from filtered members
		const selectedKey = document.getElementById('label-key-filter')?.value;
		if (selectedKey) {
			const labelValues = this.extractLabelValuesForKey(filteredMembers, selectedKey);
			labelValues.forEach(value => {
				const option = document.createElement('option');
				option.value = value;
				option.textContent = value;
				valueSelect.appendChild(option);
			});
			
			// Restore selection if it still exists for this key
			if (currentValue && labelValues.includes(currentValue)) {
				valueSelect.value = currentValue;
			} else {
				valueSelect.value = '';
			}
		} else {
			// If no key is selected, show all unique values from all keys in filtered members
			const allValues = new Set();
			filteredMembers.forEach(member => {
				if (member.labels && typeof member.labels === 'object') {
					Object.values(member.labels).forEach(value => {
						allValues.add(value);
					});
				}
			});
			
			const sortedValues = Array.from(allValues).sort();
			sortedValues.forEach(value => {
				const option = document.createElement('option');
				option.value = value;
				option.textContent = value;
				valueSelect.appendChild(option);
			});
			
			// Restore selection if it still exists
			if (currentValue && sortedValues.includes(currentValue)) {
				valueSelect.value = currentValue;
			} else {
				valueSelect.value = '';
			}
		}
	}

	// Add a new filter and create a pill
	addFilter(labelKey, labelValue) {
		// Check if this filter already exists
		const existingFilter = this.activeFilters.find(filter => 
			filter.labelKey === labelKey && filter.labelValue === labelValue
		);
		
		if (existingFilter) {
			logger.debug('ClusterMembersComponent: Filter already exists, skipping');
			return;
		}
		
		// Add the new filter
		this.activeFilters.push({ labelKey, labelValue });
		
		// Create and add the pill
		this.createFilterPill(labelKey, labelValue);
		
		// Update dropdowns and apply filter
		this.updateFilterDropdowns();
		this.applyFilter();
	}
	
	// Remove a filter and its pill
	removeFilter(labelKey, labelValue) {
		// Remove from active filters
		this.activeFilters = this.activeFilters.filter(filter => 
			!(filter.labelKey === labelKey && filter.labelValue === labelValue)
		);
		
		// Remove the pill from DOM
		this.removeFilterPill(labelKey, labelValue);
		
		// Update dropdowns and apply filter
		this.updateFilterDropdowns();
		this.applyFilter();
	}
	
	// Create a filter pill element
	createFilterPill(labelKey, labelValue) {
		const pillsContainer = document.getElementById('filter-pills-container');
		if (!pillsContainer) return;
		
		const pill = document.createElement('div');
		pill.className = 'filter-pill';
		pill.dataset.labelKey = labelKey;
		pill.dataset.labelValue = labelValue;
		
		// Create pill text
		const pillText = document.createElement('span');
		pillText.className = 'filter-pill-text';
		
		if (labelKey && labelValue) {
			pillText.textContent = `${labelKey}: ${labelValue}`;
		} else if (labelKey && !labelValue) {
			pillText.textContent = `${labelKey}: *`;
		} else if (!labelKey && labelValue) {
			pillText.textContent = `*: ${labelValue}`;
		}
		
		// Create remove button
		const removeBtn = document.createElement('button');
		removeBtn.className = 'filter-pill-remove';
		removeBtn.title = 'Remove filter';
		removeBtn.innerHTML = `
			<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
				<path d="M18 6L6 18M6 6l12 12"/>
			</svg>
		`;
		
		// Add click handler for remove button
		removeBtn.addEventListener('click', (e) => {
			e.stopPropagation();
			this.removeFilter(labelKey, labelValue);
		});
		
		// Assemble pill
		pill.appendChild(pillText);
		pill.appendChild(removeBtn);
		
		// Add to container
		pillsContainer.appendChild(pill);
	}
	
	// Remove a filter pill from DOM
	removeFilterPill(labelKey, labelValue) {
		const pillsContainer = document.getElementById('filter-pills-container');
		if (!pillsContainer) return;
		
		const pill = pillsContainer.querySelector(`[data-label-key="${labelKey}"][data-label-value="${labelValue}"]`);
		if (pill) {
			pill.remove();
		}
	}
	
	// Clear all filters and pills
	clearAllFilters() {
		this.activeFilters = [];
		
		// Clear all pills
		const pillsContainer = document.getElementById('filter-pills-container');
		if (pillsContainer) {
			pillsContainer.innerHTML = '';
		}
		
		// Reset dropdowns
		const keySelect = document.getElementById('label-key-filter');
		const valueSelect = document.getElementById('label-value-filter');
		if (keySelect) keySelect.value = '';
		if (valueSelect) valueSelect.value = '';
		
		// Update dropdowns and apply filter
		this.updateFilterDropdowns();
		this.applyFilter();
	}

	// Apply filter and re-render
	applyFilter() {
		const filteredMembers = this.filterMembers(this.allMembers);
		this.renderFilteredMembers(filteredMembers);
	}

	// Set up filter event listeners
	setupFilterListeners() {
		logger.debug('ClusterMembersComponent: Setting up filter listeners...');
		const keySelect = document.getElementById('label-key-filter');
		const valueSelect = document.getElementById('label-value-filter');
		const clearBtn = document.getElementById('clear-filters-btn');
		
		logger.debug('ClusterMembersComponent: Filter elements found:', {
			keySelect: !!keySelect,
			valueSelect: !!valueSelect,
			clearBtn: !!clearBtn
		});
		
		if (keySelect) {
			keySelect.addEventListener('change', (e) => {
				const selectedKey = e.target.value;
				const selectedValue = valueSelect ? valueSelect.value : '';
				
				// If both key and value are selected, add as a filter pill
				if (selectedKey && selectedValue) {
					this.addFilter(selectedKey, selectedValue);
					// Reset dropdowns after adding filter
					keySelect.value = '';
					valueSelect.value = '';
				} else if (selectedKey && !selectedValue) {
					// Only key selected, update value dropdown
					this.updateValueDropdown();
				}
			});
		}
		
		if (valueSelect) {
			valueSelect.addEventListener('change', (e) => {
				const selectedValue = e.target.value;
				const selectedKey = keySelect ? keySelect.value : '';
				
				// If both key and value are selected, add as a filter pill
				if (selectedKey && selectedValue) {
					this.addFilter(selectedKey, selectedValue);
					// Reset dropdowns after adding filter
					keySelect.value = '';
					valueSelect.value = '';
				}
			});
		}
		
		if (clearBtn) {
			clearBtn.addEventListener('click', (e) => {
				e.preventDefault();
				e.stopPropagation();
				logger.debug('ClusterMembersComponent: Clear filters button clicked');
				this.clearAllFilters();
			});
		} else {
			logger.warn('ClusterMembersComponent: Clear filters button not found');
		}
	}


	openDrawerForMember(memberIp) {
		// Set selected member and update highlighting
		this.setSelectedMember(memberIp);
		
		// Get display name for drawer title
		let displayName = memberIp;
		try {
			const members = (this.viewModel && typeof this.viewModel.get === 'function') ? this.viewModel.get('members') : [];
			const member = Array.isArray(members) ? members.find(m => m && m.ip === memberIp) : null;
			const hostname = (member && member.hostname) ? member.hostname : '';
			const ip = (member && member.ip) ? member.ip : memberIp;
			
			if (hostname && ip) {
				displayName = `${hostname} - ${ip}`;
			} else if (hostname) {
				displayName = hostname;
			} else if (ip) {
				displayName = ip;
			}
		} catch (_) {
			// no-op if anything goes wrong, default title remains
		}

		// Open drawer with content callback
		this.drawer.openDrawer(displayName, (contentContainer, setActiveComponent) => {
			// Load and mount NodeDetails into drawer
			const nodeDetailsVM = new NodeDetailsViewModel();
			const nodeDetailsComponent = new NodeDetailsComponent(contentContainer, nodeDetailsVM, this.eventBus);
			setActiveComponent(nodeDetailsComponent);

			nodeDetailsVM.loadNodeDetails(memberIp).then(() => {
				nodeDetailsComponent.mount();
			}).catch((error) => {
				logger.error('Failed to load node details for drawer:', error);
				contentContainer.innerHTML = `
					<div class="error">
						<strong>Error loading node details:</strong><br>
						${this.escapeHtml(error.message)}
					</div>
				`;
			});
		}, null, () => {
			// Close callback - clear selection when drawer is closed
			this.clearSelectedMember();
		});
	}

	closeDrawer() {
		this.drawer.closeDrawer();
	}

	mount() {
		logger.debug('ClusterMembersComponent: Starting mount...');
		super.mount();
		
		// Show loading state immediately when mounted
		logger.debug('ClusterMembersComponent: Showing initial loading state');
		this.showLoadingState();
		
		// Set up loading timeout safeguard
		this.setupLoadingTimeout();
		
		// Set up filter listeners
		this.setupFilterListeners();
		
		logger.debug('ClusterMembersComponent: Mounted successfully');
	}

	// Setup loading timeout safeguard to prevent getting stuck in loading state
	setupLoadingTimeout() {
		this.loadingTimeout = setTimeout(() => {
			const isLoading = this.viewModel.get('isLoading');
			if (isLoading) {
				logger.warn('ClusterMembersComponent: Loading timeout reached, forcing render check');
				this.forceRenderCheck();
			}
		}, 10000); // 10 second timeout
	}

	// Force a render check when loading gets stuck
	forceRenderCheck() {
		logger.debug('ClusterMembersComponent: Force render check called');
		const members = this.viewModel.get('members');
		const error = this.viewModel.get('error');
		const isLoading = this.viewModel.get('isLoading');
		
		logger.debug('ClusterMembersComponent: Force render check state:', { members, error, isLoading });
		
		if (error) {
			this.showErrorState(error);
		} else if (members && members.length > 0) {
			this.renderMembers(members);
		} else if (!isLoading) {
			this.showEmptyState();
		}
	}

	setupEventListeners() {
		logger.debug('ClusterMembersComponent: Setting up event listeners...');
		// Note: Refresh button is now handled by ClusterViewComponent
		// since it's in the cluster header, not in the members container
	}

	setupViewModelListeners() {
		logger.debug('ClusterMembersComponent: Setting up view model listeners...');
		// Listen to cluster members changes with change detection
		this.subscribeToProperty('members', this.handleMembersUpdate.bind(this));
		this.subscribeToProperty('isLoading', this.handleLoadingUpdate.bind(this));
		this.subscribeToProperty('error', this.handleErrorUpdate.bind(this));
		logger.debug('ClusterMembersComponent: View model listeners set up');
	}

	// Handle members update
	handleMembersUpdate(newMembers, previousMembers) {
		logger.debug('ClusterMembersComponent: Members updated:', { newMembers, previousMembers });
		
		// Prevent multiple simultaneous renders
		if (this.renderInProgress) {
			logger.debug('ClusterMembersComponent: Render already in progress, skipping update');
			return;
		}
		
		// Check if we're currently loading - if so, let the loading handler deal with it
		const isLoading = this.viewModel.get('isLoading');
		if (isLoading) {
			logger.debug('ClusterMembersComponent: Currently loading, skipping members update (will be handled by loading completion)');
			return;
		}
		
		// On first load (no previous members), always render
		if (!previousMembers || !Array.isArray(previousMembers) || previousMembers.length === 0) {
			logger.debug('ClusterMembersComponent: First load or no previous members, performing full render');
			this.render();
			return;
		}
		
		if (this.shouldSkipFullRender(newMembers, previousMembers)) {
			// Perform partial update
			logger.debug('ClusterMembersComponent: Skipping full render, performing partial update');
			this.updateMembersPartially(newMembers, previousMembers);
		} else {
			// Full re-render if structure changed significantly
			logger.debug('ClusterMembersComponent: Structure changed, performing full re-render');
			this.render();
		}
	}

	// Handle loading state update
	handleLoadingUpdate(isLoading) {
		logger.debug('ClusterMembersComponent: Loading state changed:', isLoading);
		
		if (isLoading) {
			logger.debug('ClusterMembersComponent: Showing loading state');
			this.renderLoading(`
				<div class="loading">
					<div>Loading cluster members...</div>
				</div>
			`);
			
			// Set up a loading completion check
			this.checkLoadingCompletion();
		} else {
			logger.debug('ClusterMembersComponent: Loading completed, checking if we need to render');
			// When loading completes, check if we have data to render
			this.handleLoadingCompletion();
		}
	}

	// Check if loading has completed and handle accordingly
	handleLoadingCompletion() {
		const members = this.viewModel.get('members');
		const error = this.viewModel.get('error');
		const isLoading = this.viewModel.get('isLoading');
		
		logger.debug('ClusterMembersComponent: Handling loading completion:', { members, error, isLoading });
		
		if (error) {
			logger.debug('ClusterMembersComponent: Loading completed with error, showing error state');
			this.showErrorState(error);
		} else if (members && members.length > 0) {
			logger.debug('ClusterMembersComponent: Loading completed with data, rendering members');
			this.renderMembers(members);
		} else if (!isLoading) {
			logger.debug('ClusterMembersComponent: Loading completed but no data, showing empty state');
			this.showEmptyState();
		}
	}

	// Set up a check to ensure loading completion is handled
	checkLoadingCompletion() {
		// Clear any existing completion check
		if (this.loadingCompletionCheck) {
			clearTimeout(this.loadingCompletionCheck);
		}
		
		// Set up a completion check that runs after a short delay
		this.loadingCompletionCheck = setTimeout(() => {
			const isLoading = this.viewModel.get('isLoading');
			if (!isLoading) {
				logger.debug('ClusterMembersComponent: Loading completion check triggered');
				this.handleLoadingCompletion();
			}
		}, 1000); // Check after 1 second
	}

	// Handle error state update
	handleErrorUpdate(error) {
		if (error) {
			this.showErrorState(error);
		}
	}

	// Check if we should skip full re-render during update
	shouldSkipFullRender(newMembers, previousMembers) {
		if (!previousMembers || !Array.isArray(previousMembers)) return false;
		if (!Array.isArray(newMembers)) return false;
		
		// If member count changed, we need to re-render
		if (newMembers.length !== previousMembers.length) return false;
		
		// Check if member IPs are the same (same nodes)
		const newIps = new Set(newMembers.map(m => m.ip));
		const prevIps = new Set(previousMembers.map(m => m.ip));
		
		// If IPs are the same, we can skip full re-render
		return newIps.size === prevIps.size && 
			   [...newIps].every(ip => prevIps.has(ip));
	}

	// Check if we should skip rendering during view switches
	shouldSkipRender() {
		// Rely on lifecycle flags controlled by App
		if (!this.isMounted || this.isPaused) {
			logger.debug('ClusterMembersComponent: Not mounted or paused, skipping render');
			return true;
		}
		return false;
	}

	// Update members partially
	updateMembersPartially(newMembers, previousMembers) {
		logger.debug('ClusterMembersComponent: Performing partial update');
		
		// Build previous map by IP for stable diffs
		const prevByIp = new Map((previousMembers || []).map(m => [m.ip, m]));
		newMembers.forEach((newMember) => {
			const prevMember = prevByIp.get(newMember.ip);
			if (prevMember && this.hasMemberChanged(newMember, prevMember)) {
				logger.debug('ClusterMembersComponent: Member changed, updating card for:', newMember.ip);
				this.updateMemberCard(newMember);
			}
		});
	}

	// Check if a specific member has changed
	hasMemberChanged(newMember, prevMember) {
		// Check basic properties
		if (newMember.status !== prevMember.status ||
			newMember.latency !== prevMember.latency ||
			newMember.hostname !== prevMember.hostname) {
			return true;
		}
		
		// Check labels for changes
		const newLabels = newMember.labels || {};
		const prevLabels = prevMember.labels || {};
		
		// Compare label keys
		const newKeys = Object.keys(newLabels);
		const prevKeys = Object.keys(prevLabels);
		
		if (newKeys.length !== prevKeys.length) {
			return true;
		}
		
		// Compare label values
		for (const key of newKeys) {
			if (newLabels[key] !== prevLabels[key]) {
				return true;
			}
		}
		
		return false;
	}

	// Update a specific member card without re-rendering the entire component
	updateMemberCard(member) {
		const card = this.findElement(`[data-member-ip="${member.ip}"]`);
		if (!card) return;
		
		// Update status
		const statusElement = card.querySelector('.member-status');
		if (statusElement) {
		let statusClass, statusIcon;
		if (member.status && member.status.toUpperCase() === 'ACTIVE') {
			statusClass = 'status-online';
			statusIcon = window.icon('dotGreen', { width: 12, height: 12 });
		} else if (member.status && member.status.toUpperCase() === 'INACTIVE') {
			statusClass = 'status-dead';
			statusIcon = window.icon('dotRed', { width: 12, height: 12 });
		} else {
			statusClass = 'status-offline';
			statusIcon = window.icon('dotRed', { width: 12, height: 12 });
		}

		statusElement.className = `member-status ${statusClass}`;
		statusElement.innerHTML = `${statusIcon}`;
		}
		
		// Update latency
		const latencyElement = card.querySelector('.latency-value');
		if (latencyElement) {
			latencyElement.textContent = member.latency ? member.latency + 'ms' : 'N/A';
		}
		
		// Update hostname if changed
		const hostnameElement = card.querySelector('.member-hostname');
		if (hostnameElement && member.hostname !== hostnameElement.textContent) {
			hostnameElement.textContent = member.hostname || 'Unknown Device';
		}

		// Update labels (add/update/remove labels row as needed)
		const labels = (member && typeof member.labels === 'object') ? member.labels : {};
		const hasLabels = labels && Object.keys(labels).length > 0;
		let labelsRow = card.querySelector('.member-row-2');
		if (hasLabels) {
			const chipsHtml = Object.entries(labels)
				.map(([key, value]) => `<span class="label-chip">${this.escapeHtml(String(key))}: ${this.escapeHtml(String(value))}</span>`)
				.join('');
			if (labelsRow) {
				const labelsContainer = labelsRow.querySelector('.member-labels');
				if (labelsContainer) {
					labelsContainer.innerHTML = chipsHtml;
				}
			} else {
				// Create labels row below row-1
				const memberInfo = card.querySelector('.member-info');
				if (memberInfo) {
					labelsRow = document.createElement('div');
					labelsRow.className = 'member-row-2';
					const labelsContainer = document.createElement('div');
					labelsContainer.className = 'member-labels';
					labelsContainer.innerHTML = chipsHtml;
					labelsRow.appendChild(labelsContainer);
					// Insert after the first row if present, otherwise append
					const firstRow = memberInfo.querySelector('.member-row-1');
					if (firstRow && firstRow.nextSibling) {
						memberInfo.insertBefore(labelsRow, firstRow.nextSibling);
					} else {
						memberInfo.appendChild(labelsRow);
					}
				}
			}
		} else if (labelsRow) {
			// No labels now: remove the labels row if it exists
			labelsRow.remove();
		}
	}

	render() {
		if (this.renderInProgress) {
			logger.debug('ClusterMembersComponent: Render already in progress, skipping');
			return;
		}
		
		// Check if we should skip rendering during view switches
		if (this.shouldSkipRender()) {
			return;
		}
		
		this.renderInProgress = true;
		
		try {
			logger.debug('ClusterMembersComponent: render() called');
			logger.debug('ClusterMembersComponent: Container element:', this.container);
			logger.debug('ClusterMembersComponent: Is mounted:', this.isMounted);
			
			const members = this.viewModel.get('members');
			const isLoading = this.viewModel.get('isLoading');
			const error = this.viewModel.get('error');
		
			logger.debug('ClusterMembersComponent: render data:', { members, isLoading, error });
		
			if (isLoading) {
				logger.debug('ClusterMembersComponent: Showing loading state');
				this.showLoadingState();
				return;
			}
		
			if (error) {
				logger.debug('ClusterMembersComponent: Showing error state');
				this.showErrorState(error);
				return;
			}
		
			if (!members || members.length === 0) {
				logger.debug('ClusterMembersComponent: Showing empty state');
				this.showEmptyState();
				return;
			}
		
			logger.debug('ClusterMembersComponent: Rendering members:', members);
			this.renderMembers(members);
			
		} finally {
			this.renderInProgress = false;
		}
	}

	// Show loading state
	showLoadingState() {
		logger.debug('ClusterMembersComponent: showLoadingState() called');
		this.renderLoading(`
			<div class="loading">
				<div>Loading cluster members...</div>
			</div>
		`);
	}

	// Show error state
	showErrorState(error) {
		logger.debug('ClusterMembersComponent: showErrorState() called with error:', error);
		this.renderError(`Error loading cluster members: ${error}`);
	}

	// Show empty state
	showEmptyState() {
		logger.debug('ClusterMembersComponent: showEmptyState() called');
		this.renderEmpty(`
			<div class="empty-state">
				<div class="empty-state-icon">${window.icon('cluster', { width: 24, height: 24 })}</div>
				<div>No cluster members found</div>
				<div style="font-size: 0.9rem; margin-top: 0.5rem; opacity: 0.7;">
					The cluster might be empty or not yet discovered
				</div>
			</div>
		`);
	}

	renderMembers(members) {
		logger.debug('ClusterMembersComponent: renderMembers() called with', members.length, 'members');
		
		// Store all members for filtering
		this.allMembers = members;
		
		// Update filter dropdowns with current label data
		this.updateFilterDropdowns();
		
		// Apply current filter to get filtered members
		const filteredMembers = this.filterMembers(members);
		
		const membersHTML = filteredMembers.map(member => {
		let statusClass, statusIcon;
		if (member.status && member.status.toUpperCase() === 'ACTIVE') {
			statusClass = 'status-online';
			statusIcon = window.icon('dotGreen', { width: 12, height: 12 });
		} else if (member.status && member.status.toUpperCase() === 'INACTIVE') {
			statusClass = 'status-dead';
			statusIcon = window.icon('dotRed', { width: 12, height: 12 });
		} else {
			statusClass = 'status-offline';
			statusIcon = window.icon('dotRed', { width: 12, height: 12 });
		}
			
			logger.debug('ClusterMembersComponent: Rendering member:', member);
			
			return `
				<div class="member-card" data-member-ip="${member.ip}">
					<div class="member-header">
						<div class="member-info">
							<div class="member-row-1">
								<div class="status-hostname-group">
									<div class="member-status ${statusClass}">
										${statusIcon}
									</div>
									<div class="member-hostname">${this.escapeHtml(member.hostname || 'Unknown Device')}</div>
								</div>
								<div class="member-ip">${this.escapeHtml(member.ip || 'No IP')}</div>
								<div class="member-latency">
									<span class="latency-label">Latency:</span>
									<span class="latency-value">${member.latency ? member.latency + 'ms' : 'N/A'}</span>
								</div>
							</div>
							${member.labels && Object.keys(member.labels).length ? `
							<div class="member-row-2">
								<div class="member-labels">
									${Object.entries(member.labels).map(([key, value]) => `<span class=\"label-chip\">${this.escapeHtml(key)}: ${this.escapeHtml(value)}</span>`).join('')}
								</div>
							</div>
							` : ''}
						</div>
						<div class="member-actions">
							<button class="member-terminal-btn" title="Open Terminal" aria-label="Open Terminal">
								<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
									<path d="M4 17l6-6-6-6"></path>
									<path d="M12 19h8"></path>
								</svg>
							</button>
							<div class="expand-icon">
								<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
									<path d="M6 9l6 6 6-6"/>
								</svg>
							</div>
						</div>
					</div>
					<div class="member-details">
						<div class="loading-details">Loading detailed information...</div>
					</div>
				</div>
			`;
		}).join('');

		logger.debug('ClusterMembersComponent: Setting HTML, length:', membersHTML.length);
		this.setHTML('', membersHTML);
		logger.debug('ClusterMembersComponent: HTML set, setting up member cards...');
		this.setupMemberCards(filteredMembers);
	}

	// Apply filter and re-render
	applyFilter() {
		const filteredMembers = this.filterMembers(this.allMembers);
		this.renderFilteredMembers(filteredMembers);
	}

	// Render filtered members without updating dropdowns
	renderFilteredMembers(filteredMembers) {
		logger.debug('ClusterMembersComponent: renderFilteredMembers() called with', filteredMembers.length, 'members');
		
		const membersHTML = filteredMembers.map(member => {
		let statusClass, statusIcon;
		if (member.status && member.status.toUpperCase() === 'ACTIVE') {
			statusClass = 'status-online';
			statusIcon = window.icon('dotGreen', { width: 12, height: 12 });
		} else if (member.status && member.status.toUpperCase() === 'INACTIVE') {
			statusClass = 'status-dead';
			statusIcon = window.icon('dotRed', { width: 12, height: 12 });
		} else {
			statusClass = 'status-offline';
			statusIcon = window.icon('dotRed', { width: 12, height: 12 });
		}
			
			logger.debug('ClusterMembersComponent: Rendering member:', member);
			
			return `
				<div class="member-card" data-member-ip="${member.ip}">
					<div class="member-header">
						<div class="member-info">
							<div class="member-row-1">
								<div class="status-hostname-group">
									<div class="member-status ${statusClass}">
										${statusIcon}
									</div>
									<div class="member-hostname">${this.escapeHtml(member.hostname || 'Unknown Device')}</div>
								</div>
								<div class="member-ip">${this.escapeHtml(member.ip || 'No IP')}</div>
								<div class="member-latency">
									<span class="latency-label">Latency:</span>
									<span class="latency-value">${member.latency ? member.latency + 'ms' : 'N/A'}</span>
								</div>
							</div>
							${member.labels && Object.keys(member.labels).length ? `
							<div class="member-row-2">
								<div class="member-labels">
									${Object.entries(member.labels).map(([key, value]) => `<span class=\"label-chip\">${this.escapeHtml(key)}: ${this.escapeHtml(value)}</span>`).join('')}
								</div>
							</div>
							` : ''}
						</div>
						<div class="member-actions">
							<button class="member-terminal-btn" title="Open Terminal" aria-label="Open Terminal">
								<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
									<path d="M4 17l6-6-6-6"></path>
									<path d="M12 19h8"></path>
								</svg>
							</button>
							<div class="expand-icon">
								<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
									<path d="M6 9l6 6 6-6"/>
								</svg>
							</div>
						</div>
					</div>
					<div class="member-details">
						<div class="loading-details">Loading detailed information...</div>
					</div>
				</div>
			`;
		}).join('');

		logger.debug('ClusterMembersComponent: Setting HTML, length:', membersHTML.length);
		this.setHTML('', membersHTML);
		logger.debug('ClusterMembersComponent: HTML set, setting up member cards...');
		this.setupMemberCards(filteredMembers);
	}

	setupMemberCards(members) {
		setTimeout(() => {
			this.findAllElements('.member-card').forEach((card, index) => {
				const terminalBtn = card.querySelector('.member-terminal-btn');
				const expandIcon = card.querySelector('.expand-icon');
				const memberDetails = card.querySelector('.member-details');
				const memberIp = card.dataset.memberIp;

				// Ensure all cards start collapsed by default
				card.classList.remove('expanded');
				if (expandIcon) {
					expandIcon.classList.remove('expanded');
				}
				
				// Clear any previous content
				memberDetails.innerHTML = '<div class="loading-details">Loading detailed information...</div>';

				// Make the entire card clickable
				this.addEventListener(card, 'click', async (e) => {
					if (e.target === expandIcon) return;
					
					// On desktop, open slide-in drawer instead of inline expand
					if (this.isDesktop()) {
						e.preventDefault();
						e.stopPropagation();
						this.openDrawerForMember(memberIp);
						return;
					}
					
					// Mobile/low-res: keep inline expand/collapse
					const isExpanding = !card.classList.contains('expanded');
					if (isExpanding) {
						await this.expandCard(card, memberIp, memberDetails);
					} else {
						this.collapseCard(card, expandIcon);
					}
				});
				
				// Keep the expand icon click handler for visual feedback
				if (expandIcon) {
					this.addEventListener(expandIcon, 'click', async (e) => {
						e.stopPropagation();
						if (this.isDesktop()) {
							this.openDrawerForMember(memberIp);
							return;
						}
						const isExpanding = !card.classList.contains('expanded');
						if (isExpanding) {
							await this.expandCard(card, memberIp, memberDetails);
						} else {
							this.collapseCard(card, expandIcon);
						}
					});
				}

			if (terminalBtn) {
				this.addEventListener(terminalBtn, 'click', async (e) => {
					e.stopPropagation();
					e.preventDefault();
					try {
						if (!window.TerminalPanel) return;
						this.ensureTerminalContainer();
						const panel = window.TerminalPanel;
						const wasMinimized = panel.isMinimized;
						panel.open(this.terminalPanelContainer, memberIp);
						if (wasMinimized && panel.restore) {
							panel.restore();
						}
					} catch (err) {
						console.error('Failed to open member terminal:', err);
					}
				});
			}
			});
		}, 100);
	}

	async expandCard(card, memberIp, memberDetails) {
		try {
			// Create node details view model and component
			const nodeDetailsVM = new NodeDetailsViewModel();
			const nodeDetailsComponent = new NodeDetailsComponent(memberDetails, nodeDetailsVM, this.eventBus);
			
			// Load node details
			await nodeDetailsVM.loadNodeDetails(memberIp);
			
			// Mount the component
			nodeDetailsComponent.mount();
			
			// Update UI
			card.classList.add('expanded');
			const expandIcon = card.querySelector('.expand-icon');
			if (expandIcon) {
				expandIcon.classList.add('expanded');
			}
			
		} catch (error) {
			logger.error('Failed to expand card:', error);
			memberDetails.innerHTML = `
				<div class="error">
					<strong>Error loading node details:</strong><br>
					${error.message}
				</div>
			`;
		}
	}

	collapseCard(card, expandIcon) {
		card.classList.remove('expanded');
		if (expandIcon) {
			expandIcon.classList.remove('expanded');
		}
	}

	setupTabs(container) {
		super.setupTabs(container, {
			onChange: (targetTab) => {
				const memberCard = container.closest('.member-card');
				if (memberCard) {
					const memberIp = memberCard.dataset.memberIp;
					this.viewModel.storeActiveTab(memberIp, targetTab);
				}
			}
		});
	}

	// Restore active tab state
	restoreActiveTab(container, activeTab) {
		const tabButtons = container.querySelectorAll('.tab-button');
		const tabContents = container.querySelectorAll('.tab-content');
		
		// Remove active class from all buttons and contents
		tabButtons.forEach(btn => btn.classList.remove('active'));
		tabContents.forEach(content => content.classList.remove('active'));
		
		// Add active class to the restored tab
		const activeButton = container.querySelector(`[data-tab="${activeTab}"]`);
		const activeContent = container.querySelector(`#${activeTab}-tab`);
		
		if (activeButton) activeButton.classList.add('active');
		if (activeContent) activeContent.classList.add('active');
	}

	// Note: handleRefresh method has been moved to ClusterViewComponent
	// since the refresh button is in the cluster header, not in the members container

	// Debug method to check component state
	debugState() {
		const members = this.viewModel.get('members');
		const isLoading = this.viewModel.get('isLoading');
		const error = this.viewModel.get('error');
		const expandedCards = this.viewModel.get('expandedCards');
		const activeTabs = this.viewModel.get('activeTabs');
		
		logger.debug('ClusterMembersComponent: Debug State:', {
			isMounted: this.isMounted,
			container: this.container,
			members: members,
			membersCount: members?.length || 0,
			isLoading: isLoading,
			error: error,
			expandedCardsCount: expandedCards?.size || 0,
			activeTabsCount: activeTabs?.size || 0,
			loadingTimeout: this.loadingTimeout
		});
		
		return { members, isLoading, error, expandedCards, activeTabs };
	}

	// Manual refresh method that bypasses potential state conflicts
	async manualRefresh() {
		logger.debug('ClusterMembersComponent: Manual refresh called');
		
		try {
			// Clear any existing loading state
			this.viewModel.set('isLoading', false);
			this.viewModel.set('error', null);
			
			// Force a fresh data load
			await this.viewModel.updateClusterMembers();
			
			logger.debug('ClusterMembersComponent: Manual refresh completed');
		} catch (error) {
			logger.error('ClusterMembersComponent: Manual refresh failed:', error);
			this.showErrorState(error.message);
		}
	}

	unmount() {
		if (!this.isMounted) return;
		
		this.isMounted = false;
		
		// Clear any pending timeouts
		if (this.loadingTimeout) {
			clearTimeout(this.loadingTimeout);
			this.loadingTimeout = null;
		}
		
		if (this.loadingCompletionCheck) {
			clearTimeout(this.loadingCompletionCheck);
			this.loadingCompletionCheck = null;
		}
		
		// Clear any pending render operations
		this.renderInProgress = false;
		
		this.cleanupEventListeners();
		this.cleanupViewModelListeners();
		
		logger.debug(`${this.constructor.name} unmounted`);
	}

	// Override pause method to handle timeouts and operations
	onPause() {
		logger.debug('ClusterMembersComponent: Pausing...');
		
		// Clear any pending timeouts
		if (this.loadingTimeout) {
			clearTimeout(this.loadingTimeout);
			this.loadingTimeout = null;
		}
		
		if (this.loadingCompletionCheck) {
			clearTimeout(this.loadingCompletionCheck);
			this.loadingCompletionCheck = null;
		}
		
		// Mark as paused to prevent new operations
		this.isPaused = true;
	}

	// Override resume method to restore functionality
	onResume() {
		logger.debug('ClusterMembersComponent: Resuming...');
		
		this.isPaused = false;
		
		// Re-setup loading timeout if needed
		if (!this.loadingTimeout) {
			this.setupLoadingTimeout();
		}
		
		// Check if we need to handle any pending operations
		this.checkPendingOperations();
	}

	// Check for any operations that need to be handled after resume
	checkPendingOperations() {
		const isLoading = this.viewModel.get('isLoading');
		const members = this.viewModel.get('members');
		
		// If we were loading and it completed while paused, handle the completion
		if (!isLoading && members && members.length > 0) {
			logger.debug('ClusterMembersComponent: Handling pending loading completion after resume');
			this.handleLoadingCompletion();
		}
	}

	// Override to determine if re-render is needed on resume
	shouldRenderOnResume() {
		// Don't re-render on resume - maintain current state
		return false;
	}

	// Set selected member and update highlighting
	setSelectedMember(memberIp) {
		// Clear previous selection
		this.clearSelectedMember();
		
		// Set new selection
		this.selectedMemberIp = memberIp;
		
		// Add selected class to the member card
		const card = this.findElement(`[data-member-ip="${memberIp}"]`);
		if (card) {
			card.classList.add('selected');
		}
	}

	// Clear selected member highlighting
	clearSelectedMember() {
		if (this.selectedMemberIp) {
			const card = this.findElement(`[data-member-ip="${this.selectedMemberIp}"]`);
			if (card) {
				card.classList.remove('selected');
			}
			this.selectedMemberIp = null;
		}
	}

	ensureTerminalContainer() {
		if (!this.terminalPanelContainer) {
			try {
				const drawer = this.drawer;
				if (drawer && drawer.ensureDrawer) {
					drawer.ensureDrawer();
					this.terminalPanelContainer = drawer.terminalPanelContainer;
				}
			} catch (err) {
				console.error('Failed to ensure terminal container:', err);
			}
		}
	}
}

window.ClusterMembersComponent = ClusterMembersComponent; 