/**
 * IP Whitelist Manager for LibrePortal
 * Handles multiple IP whitelist fields with validation and management
 */

class IPWhitelistManager {
  constructor() {
    this.maxWhitelistEntries = 20; // Maximum number of whitelist entries
  }

  // Render IP whitelist section with add/delete functionality
  async renderWhitelistSection(configItems, displaySubcategory, subcategoryDescription) {
    try {
      // Check if Traefik is installed
      const traefikStatus = await this.checkTraefikInstallation();
      
      let html = `
        <div class="config-category">
          <div class="domains-wrapper">
            <div class="domains-header">
              <div>
                <h3>${displaySubcategory}</h3>
                <p class="category-description">${subcategoryDescription}</p>
              </div>
            </div>
            <div class="domains-divider"></div>
            <div class="config-group">
            <!-- Hidden input to store the actual CFG_IPS_WHITELIST value -->
            <input type="hidden" name="CFG_IPS_WHITELIST" id="config-CFG_IPS_WHITELIST" value="">
            <div class="whitelist-building-blocks">
      `;

      // Extract existing whitelist entries from config
      const whitelistEntries = this.extractWhitelistEntries(configItems);
      
      // Get the original CFG_IPS_WHITELIST value for the hidden input
      const whitelistItem = configItems.find(item => item.key === 'CFG_IPS_WHITELIST');
      const originalValue = whitelistItem ? whitelistItem.value : '';
      
      if (whitelistEntries.length === 0) {
        // Show empty state with add button
        html += `
          <div class="whitelist-empty-state">
            <p>No IP whitelist entries configured. Add IP addresses, domains, or localhost to allow access to specific Traefik apps.</p>
            <div class="whitelist-actions">
              <button type="button" id="add-whitelist-btn" class="btn btn-primary" 
                      onclick="window.addWhitelistEntry()">
                <span class="add-icon">+</span>
                Add IP/Domain
              </button>
            </div>
          </div>
        `;
      } else {
        // Render existing whitelist entries
        whitelistEntries.forEach((entry, index) => {
          const entryId = `config-CFG_IPS_WHITELIST_${index + 1}`;
          const entryTitle = `Whitelist Entry ${index + 1}`;
          
          html += `
            <div class="whitelist-building-block">
              <div class="whitelist-header">
                ${this.generateField(entryId, `CFG_IPS_WHITELIST`, entry.value, entryTitle, '', { 
                  placeholder: '192.168.1.100, example.com, or localhost',
                  className: 'whitelist-input',
                  onblur: 'window.validateWhitelistEntry(this, true)'
                })}
                <button type="button" class="delete-whitelist-btn" 
                        onclick="window.deleteWhitelistEntry('${index}', this)"
                        title="Delete whitelist entry">
                  <span class="delete-icon">×</span>
                </button>
              </div>
            </div>
          `;
        });
        
        // Add button for new entries
        const isMaxEntries = whitelistEntries.length >= this.maxWhitelistEntries;
        html += `
          </div>
          <div class="whitelist-actions">
            <button type="button" id="add-whitelist-btn" class="btn ${isMaxEntries ? 'btn-secondary' : 'btn-primary'}" 
                    onclick="window.addWhitelistEntry()"
                    ${isMaxEntries ? 'disabled' : ''}>
              <span class="add-icon">${isMaxEntries ? '✓' : '+'}</span>
              ${isMaxEntries ? 'Maximum Entries Reached' : 'Add IP/Domain'}
            </button>
          </div>
        `;
      }

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

      // After rendering, set the hidden input value and update button states
      setTimeout(() => {
        const hiddenInput = document.getElementById('config-CFG_IPS_WHITELIST');
        if (hiddenInput) {
          hiddenInput.value = originalValue;
        }
        
        // Update delete button states
        this.updateWhitelistDeleteButtons();
      }, 100);

      return html;
    } catch (error) {
      console.error('Error rendering whitelist section:', error);
      return '<p>Error loading whitelist configuration.</p>';
    }
  }

  // Extract whitelist entries from config items
  extractWhitelistEntries(configItems) {
    const whitelistItem = configItems.find(item => item.key === 'CFG_IPS_WHITELIST');
    if (!whitelistItem || !whitelistItem.value) {
      return [];
    }

    // Split comma-separated values and filter out empty ones
    const entries = whitelistItem.value
      .split(',')
      .map(entry => entry.trim())
      .filter(entry => entry.length > 0 && entry !== 'HOSTIPHERE');

    return entries.map((entry, index) => ({
      key: `CFG_IPS_WHITELIST_${index + 1}`, // For field naming only
      value: entry,
      originalIndex: index // Keep track of original position
    }));
  }

  // Save whitelist entries back to single CFG_IPS_WHITELIST config
  saveWhitelistEntries() {
    try {
      // Get only the visible whitelist input values (exclude hidden input)
      const whitelistInputs = document.querySelectorAll('input[name="CFG_IPS_WHITELIST"]:not([type="hidden"])');
      //console.log('saveWhitelistEntries: Found inputs:', whitelistInputs.length);
      whitelistInputs.forEach((input, index) => {
        //console.log(`  Input ${index}: id="${input.id}", value="${input.value}"`);
      });
      
      const values = Array.from(whitelistInputs)
        .map(input => input.value.trim())
        .filter(value => value.length > 0); // Filter out empty values

      //console.log('saveWhitelistEntries: Filtered values:', values);

      // Find the hidden CFG_IPS_WHITELIST input and update it
      const hiddenInput = document.querySelector('input[name="CFG_IPS_WHITELIST"][type="hidden"]');
      if (hiddenInput) {
        hiddenInput.value = values.join(', ');
        //console.log('Saved whitelist values:', values.join(', '));
      }
    } catch (error) {
      console.error('Error saving whitelist entries:', error);
    }
  }

  // Validate individual whitelist entry
  validateWhitelistEntry(input, showNotifications = true) {
    //console.log('validateWhitelistEntry called with:', input.value, 'showNotifications:', showNotifications);
    
    const value = input.value.trim();
    
    // Clear previous validation styling
    input.style.borderColor = '';
    input.style.animation = '';
    input.title = '';
    
    if (!value) {
      //console.log('Empty value - allowing for now');
      // Empty is allowed for now (validation happens on add)
      return true;
    }
    
    // Special case for localhost
    if (value.toLowerCase() === 'localhost') {
      //console.log('localhost detected - valid');
      return true;
    }
    
    // Check for valid IP address or domain format
    const ipPattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
    const ipv6Pattern = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
    // Fixed domain pattern - requires at least one dot and proper TLD
    const domainPattern = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
    
    const isValidIP = ipPattern.test(value) || ipv6Pattern.test(value);
    const isValidDomain = domainPattern.test(value);
    const isValidFormat = isValidIP || isValidDomain || value.toLowerCase() === 'localhost';
    
    //console.log('Format validation:', {
      //value: value,
      //isValidIP: isValidIP,
      //isValidDomain: isValidDomain,
      //isValidFormat: isValidFormat
    //});
    
    if (!isValidFormat) {
      //console.log('Invalid format detected - showing error');
      // Flash the input field
      input.style.animation = 'whitelist-flash 0.5s ease-in-out 2';
      input.focus();
      setTimeout(() => {
        input.style.animation = '';
      }, 1000);
      
      // Show notification
      if (showNotifications && window.notificationSystem) {
        //console.log('Showing notification for invalid format');
        window.notificationSystem.error(`Invalid whitelist format: "${value}". Please use a valid IP address, domain (e.g., example.com), or localhost`);
      } else {
        //console.log('Notification system not available or showNotifications is false');
      }
      
      input.title = 'Invalid IP address, domain, or localhost format (e.g., 192.168.1.100, example.com, or localhost)';
      return false; // IMPORTANT: Return false for invalid format
    }
    
    // Check for duplicates
    const allWhitelistInputs = document.querySelectorAll('input[name="CFG_IPS_WHITELIST"]:not([type="hidden"])');
    //console.log('Checking for duplicates among', allWhitelistInputs.length, 'inputs');
    
    const duplicates = [];
    
    allWhitelistInputs.forEach(otherInput => {
      if (otherInput !== input) {
        const otherValue = otherInput.value.trim();
        if (otherValue.toLowerCase() === value.toLowerCase()) {
          duplicates.push(otherValue);
        }
      }
    });
    
    //console.log('Found duplicates:', duplicates);
    
    if (duplicates.length > 0) {
      //console.log('Duplicate detected - showing error');
      // Flash the input field
      input.style.animation = 'whitelist-flash 0.5s ease-in-out 2';
      input.focus();
      setTimeout(() => {
        input.style.animation = '';
      }, 1000);
      
      // Show notification
      if (showNotifications && window.notificationSystem) {
        //console.log('Showing notification for duplicate');
        window.notificationSystem.error(`"${value}" already exists in the whitelist`);
      }
      
      input.title = 'This entry already exists in the whitelist';
      return false; // IMPORTANT: Return false for duplicates
    }
    
    // Valid entry - save it
    //console.log('Valid entry - saving');
    this.saveWhitelistEntries();
    return true;
  }

  // Generate field HTML (similar to ConfigShared.generateField)
  generateField(fieldId, fieldName, value, title, description, options = {}) {
    const defaultOptions = {
      type: 'text',
      placeholder: '',
      className: '',
      required: false
    };
    
    const fieldOptions = { ...defaultOptions, ...options };
    
    return `
      <div class="field-group">
        <label class="field-label" for="${fieldId}">${title}</label>
        <input type="${fieldOptions.type}" 
               id="${fieldId}" 
               name="${fieldName}" 
               value="${value || ''}" 
               class="form-control ${fieldOptions.className}" 
               placeholder="${fieldOptions.placeholder}"
               onchange="validateWhitelistEntry(this, true)"
               oninput="validateWhitelistEntry(this, true)"
               onblur="validateWhitelistEntry(this, true)"
               onkeydown="if(event.key === 'Enter') { event.preventDefault(); window.validateWhitelistEntry(this, true); }"
               ${fieldOptions.required ? 'required' : ''}>
        ${description ? `<small class="field-description">${description}</small>` : ''}
      </div>
    `;
  }

  // Check if Traefik is installed
  async checkTraefikInstallation() {
    try {
      if (typeof DataLoader !== 'undefined') {
        return await DataLoader.isAppInstalled('traefik');
      }
      return false;
    } catch (error) {
      //console.log('Traefik check failed:', error.message);
      return false;
    }
  }

  // Add new whitelist entry
  addWhitelistEntry() {
    //console.log('Add whitelist entry button clicked!');
    
    try {
      // Before adding new entry, validate that all existing entries have valid format
      //console.log('About to call validateBeforeAddWhitelist()');
      
      // Test if the function exists
      if (typeof this.validateBeforeAddWhitelist !== 'function') {
        console.error('validateBeforeAddWhitelist function does not exist!');
        return;
      }
      
      const canAdd = this.validateBeforeAddWhitelist();
      //console.log('validateBeforeAddWhitelist() returned:', canAdd);
      
      if (!canAdd) {
        //console.log('Validation failed - not adding new entry');
        return; // Validation failed, don't add new entry
      }
      
      //console.log('Validation passed - proceeding with add');
      
      // Find the hidden CFG_IPS_WHITELIST input
      const hiddenInput = document.querySelector('input[name="CFG_IPS_WHITELIST"]');
      if (!hiddenInput) {
        console.error('Hidden CFG_IPS_WHITELIST input not found!');
        return;
      }
      
      // Get current values and split them
      const currentValues = hiddenInput.value
        .split(',')
        .map(entry => entry.trim())
        .filter(entry => entry.length > 0); // Don't filter out empty strings for counting
      
      //console.log('Current values:', currentValues);
      //console.log('Current values length:', currentValues.length);
      
      // Check if we've reached the maximum
      if (currentValues.length >= this.maxWhitelistEntries) {
        //console.log('Maximum of ' + this.maxWhitelistEntries + ' whitelist entries reached');
        return;
      }
      
      // Add a new empty entry
      // Find the highest existing whitelist number from the DOM (like domain manager)
      const allBlocks = document.querySelectorAll('.whitelist-building-block');
      const allNumbers = [];
      allBlocks.forEach(block => {
        const input = block.querySelector('input');
        if (input) {
          const inputId = input.id;
          const match = inputId.match(/config-CFG_IPS_WHITELIST_(\d+)/);
          if (match) {
            allNumbers.push(parseInt(match[1]));
          }
        }
      });
      
      const highestNumber = allNumbers.length > 0 ? Math.max(...allNumbers) : 0;
      const newEntryNumber = highestNumber + 1;
      
      //console.log('Highest existing number:', highestNumber, 'New entry number:', newEntryNumber);
      
      currentValues.push('');
      
      // Update the hidden input
      hiddenInput.value = currentValues.join(', ');
      //console.log('Updated hidden input to:', hiddenInput.value);
      
      // Create new entry HTML and add to DOM
      const newEntryHTML = `
        <div class="whitelist-building-block">
          <div class="whitelist-header">
            <div class="field-group">
              <label class="field-label" for="config-CFG_IPS_WHITELIST_${newEntryNumber}">Whitelist Entry ${newEntryNumber}</label>
              <input type="text" 
                     id="config-CFG_IPS_WHITELIST_${newEntryNumber}" 
                     name="CFG_IPS_WHITELIST" 
                     value="" 
                     class="form-control whitelist-input" 
                     placeholder="192.168.1.100, example.com, or localhost"
                     onblur="window.validateWhitelistEntry(this, true)"
                     onkeydown="if(event.key === 'Enter') { event.preventDefault(); window.validateWhitelistEntry(this, true); }">
            </div>
            <button type="button" class="delete-whitelist-btn" 
                    onclick="window.deleteWhitelistEntry('${newEntryNumber - 1}', this)"
                    title="Delete whitelist entry">
              <span class="delete-icon">×</span>
            </button>
          </div>
        </div>
      `;
      
      // Add the new entry to the DOM
      const whitelistContainer = document.querySelector('.whitelist-building-blocks');
      //console.log('Step 1: Found whitelist container:', !!whitelistContainer);
      
      if (whitelistContainer) {
        // Remove empty state if it exists
        const emptyState = whitelistContainer.querySelector('.whitelist-empty-state');
        //console.log('Step 2: Found empty state:', !!emptyState);
        if (emptyState) {
          emptyState.remove();
          //console.log('Step 3: Removed empty state');
        }
        
        // Add new entry
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = newEntryHTML;
        const newBlock = tempDiv.firstElementChild;
        //console.log('Step 4: Created new block:', !!newBlock);
        
        whitelistContainer.appendChild(newBlock);
        //console.log('Step 5: Added new block to container');
        
        // Focus on the new input
        const newInput = newBlock.querySelector('input');
        //console.log('Step 6: Found new input:', !!newInput);
        if (newInput) {
          newInput.focus();
          //console.log('Step 7: Focused new input');
        }
        
        // Update add button state
        this.updateAddEntryButton();
        //console.log('Step 8: Updated add button state');
        
        //console.log('Step 9: Add function completed successfully');
      } else {
        //console.log('Step 1: Whitelist container not found!');
      }
      
    } catch (error) {
      console.error('Error adding new whitelist entry:', error);
    }
  }

  // Check if all entries are valid before allowing new entry addition
  validateBeforeAddWhitelist() {
    //console.log('=== validateBeforeAddWhitelist START ===');
    
    // Simple test - just check for empty entries
    const allInputs = document.querySelectorAll('input[name="CFG_IPS_WHITELIST"]:not([type="hidden"])');
    //console.log('Found', allInputs.length, 'inputs');
    
    allInputs.forEach((input, index) => {
      //console.log(`Input ${index}: value="${input.value}"`);
    });
    
    for (const input of allInputs) {
      const entryValue = input.value.trim();
      
      // Check if entry is empty
      if (!entryValue) {
        //console.log('Found empty entry - blocking add');
        // Flash the empty input field
        input.style.animation = 'whitelist-flash 0.5s ease-in-out 2';
        input.focus();
        setTimeout(() => {
          input.style.animation = '';
        }, 1000);
        
        // Show notification
        if (window.notificationSystem) {
          window.notificationSystem.error('Whitelist entry cannot be empty');
        }
        //console.log('=== validateBeforeAddWhitelist END (false - empty) ===');
        return false;
      }
      
      // Check entry format with notification (always show)
      if (this.checkForInvalidWhitelistFormat(input, entryValue, false)) {
        //console.log('Found invalid format - blocking add');
        //console.log('=== validateBeforeAddWhitelist END (false - invalid) ===');
        return false;
      }
      
      // Check for duplicates with notification (always show)
      if (this.checkForDuplicateWhitelistEntry(input, entryValue)) {
        //console.log('Found duplicate entry - blocking add');
        //console.log('=== validateBeforeAddWhitelist END (false - duplicate) ===');
        return false;
      }
    }
    
    //console.log('=== validateBeforeAddWhitelist END (true) ===');
    return true;
  }

  // Check for duplicate whitelist entries
  checkForDuplicateWhitelistEntry(input, entryValue) {
    const allWhitelistInputs = document.querySelectorAll('input[name="CFG_IPS_WHITELIST"]:not([type="hidden"])');
    const duplicates = [];
    
    allWhitelistInputs.forEach(otherInput => {
      if (otherInput !== input) {
        const otherValue = otherInput.value.trim();
        if (otherValue.toLowerCase() === entryValue.toLowerCase()) {
          duplicates.push(otherValue);
        }
      }
    });
    
    if (duplicates.length > 0) {
      // Flash the input field
      input.style.animation = 'whitelist-flash 0.5s ease-in-out 2';
      input.focus();
      setTimeout(() => {
        input.style.animation = '';
      }, 1000);
      
      // Show notification
      if (window.notificationSystem) {
        window.notificationSystem.error(`"${entryValue}" already exists in the whitelist`);
      } else {
        console.error(`Duplicate whitelist entry: ${entryValue}`);
      }
      return true;
    }
    
    return false;
  }

  // Check for invalid whitelist entry format
  checkForInvalidWhitelistFormat(input, entryValue, showNotifications = true) {
    // Special case for localhost
    if (entryValue.toLowerCase() === 'localhost') {
      return false; // localhost is valid
    }
    
    // Check for valid IP address or domain format
    const ipPattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
    const ipv6Pattern = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
    // Fixed domain pattern - requires at least one dot and proper TLD
    const domainPattern = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
    
    const isValidIP = ipPattern.test(entryValue) || ipv6Pattern.test(entryValue);
    const isValidDomain = domainPattern.test(entryValue);
    
    //console.log('checkForInvalidWhitelistFormat validation:', {
      //entryValue: entryValue,
      //isValidIP: isValidIP,
      //isValidDomain: isValidDomain,
      //isValidFormat: isValidIP || isValidDomain || entryValue.toLowerCase() === 'localhost'
    //});
    
    if (!isValidIP && !isValidDomain) {
      // Flash the input field
      input.style.animation = 'whitelist-flash 0.5s ease-in-out 2';
      input.focus();
      setTimeout(() => {
        input.style.animation = '';
      }, 1000);
      
      // Show notification only if requested
      if (showNotifications && window.notificationSystem) {
        window.notificationSystem.error(`Invalid whitelist format: "${entryValue}". Please use a valid IP address, domain (e.g., example.com), or localhost`);
      } else if (showNotifications) {
        console.error(`Invalid whitelist format: ${entryValue}`);
      }
      return true; // Invalid format found
    }
    
    return false; // Valid format
  }

  // Delete whitelist entry
  deleteWhitelistEntry(entryIndex, buttonElement) {
    //console.log(`Delete whitelist entry button clicked for index: ${entryIndex}`);
    
    try {
      // Get the actual whitelist number from the input ID
      const entryBlock = buttonElement.closest('.whitelist-building-block');
      if (!entryBlock) {
        console.error('Could not find entry block');
        return;
      }
      
      const input = entryBlock.querySelector('input');
      if (!input) {
        console.error('Could not find input in entry block');
        return;
      }
      
      const inputId = input.id;
      const match = inputId.match(/config-CFG_IPS_WHITELIST_(\d+)/);
      const whitelistNumber = match ? parseInt(match[1]) : 0;
      
      //console.log(`Actual whitelist number: ${whitelistNumber}`);
      
      // Find all whitelist numbers to determine the highest
      const allBlocks = document.querySelectorAll('.whitelist-building-block');
      const allNumbers = [];
      allBlocks.forEach(block => {
        const blockInput = block.querySelector('input');
        if (blockInput) {
          const blockId = blockInput.id;
          const blockMatch = blockId.match(/config-CFG_IPS_WHITELIST_(\d+)/);
          if (blockMatch) {
            allNumbers.push(parseInt(blockMatch[1]));
          }
        }
      });
      
      const highestNumber = Math.max(...allNumbers);
      //console.log(`Highest whitelist number: ${highestNumber}`);
      
      // Only allow deletion if this is the highest numbered entry AND it's not #1
      if (whitelistNumber === 1) {
        //console.log('Cannot delete entry #1');
        if (window.notificationSystem) {
          window.notificationSystem.error('Entry 1 cannot be deleted');
        }
        return;
      }
      
      if (whitelistNumber !== highestNumber) {
        //console.log('Can only delete the highest numbered entry');
        if (window.notificationSystem) {
          window.notificationSystem.error('Can only delete the highest numbered entry');
        }
        return;
      }
      
      // Clear the input value first (like domain manager)
      input.value = '';
      
      // Remove the building block from DOM
      entryBlock.remove();
      //console.log('Removed entry block from DOM');
      
      // Update the hidden input with remaining values
      this.saveWhitelistEntries();
      
      // Update add button state
      this.updateAddEntryButton();
      
      // Update delete button states
      this.updateWhitelistDeleteButtons();
      
    } catch (error) {
      console.error('Error deleting whitelist entry:', error);
    }
  }

  // Rebuild whitelist section after changes
  rebuildWhitelistSection() {
    try {
      // Get the current config data
      const configData = window.configManager.core.configData;
      const networkData = configData.network || {};
      
      // Get the current CFG_IPS_WHITELIST value
      const hiddenInput = document.querySelector('input[name="CFG_IPS_WHITELIST"]');
      if (hiddenInput) {
        networkData.CFG_IPS_WHITELIST = hiddenInput.value;
      }
      
      // Find the whitelist section and re-render only that part
      const whitelistSection = document.querySelector('.config-category');
      if (whitelistSection) {
        // Create config items for the whitelist
        const configItems = [{
          key: 'CFG_IPS_WHITELIST',
          value: hiddenInput ? hiddenInput.value : ''
        }];
        
        // Re-render the whitelist section
        this.renderWhitelistSection(configItems, 'IP Whitelist', 'Allow specific IPs for Specified Traefik Apps')
          .then(html => {
            whitelistSection.innerHTML = html;
            
            // Re-attach event listeners and set hidden input value
            setTimeout(() => {
              if (hiddenInput) {
                const newHiddenInput = document.getElementById('config-CFG_IPS_WHITELIST');
                if (newHiddenInput) {
                  newHiddenInput.value = hiddenInput.value;
                }
              }
            }, 100);
          });
      }
    } catch (error) {
      console.error('Error rebuilding whitelist section:', error);
      // Fallback to full render if partial fails
      if (window.configManager) {
        window.configManager.renderConfig('network');
      }
    }
  }

  // Update delete button states
  updateWhitelistDeleteButtons() {
    // Find all whitelist building blocks
    const allWhitelistBlocks = document.querySelectorAll('.whitelist-building-block');
    
    // Find all whitelist numbers from existing blocks (using input IDs since all have same name)
    const allWhitelistNumbers = [];
    allWhitelistBlocks.forEach(block => {
      const input = block.querySelector('input');
      if (input) {
        const inputId = input.id;
        const match = inputId.match(/config-CFG_IPS_WHITELIST_(\d+)/);
        if (match) {
          allWhitelistNumbers.push(parseInt(match[1]));
        }
      }
    });
    
    // Update delete button states (only highest numbered whitelist can be deleted, but NEVER Entry 1)
    allWhitelistBlocks.forEach((block, index) => {
      const deleteBtn = block.querySelector('.delete-whitelist-btn');
      if (deleteBtn) {
        const input = block.querySelector('input');
        if (input) {
          const inputId = input.id;
          const whitelistNum = inputId.match(/config-CFG_IPS_WHITELIST_(\d+)/);
          const whitelistNumber = whitelistNum ? parseInt(whitelistNum[1]) : 0;
          
          // Find the highest whitelist number among all visible blocks
          const highestWhitelistNumber = Math.max(...allWhitelistNumbers);
          
          // Only highest numbered whitelist can be deleted, but NEVER Entry 1
          const canDelete = whitelistNumber === highestWhitelistNumber && whitelistNumber !== 1;
          
          deleteBtn.disabled = !canDelete;
          deleteBtn.className = `delete-whitelist-btn ${!canDelete ? 'disabled' : ''}`;
          deleteBtn.title = canDelete 
            ? 'Delete whitelist entry' 
            : whitelistNumber === 1 
            ? 'Entry 1 cannot be deleted' 
            : 'Can only delete highest numbered entry';
        }
      }
    });
  }

  // Update add entry button state
  updateAddEntryButton() {
    const addEntryBtn = document.getElementById('add-whitelist-btn');
    if (addEntryBtn) {
      // Find all whitelist building blocks
      const allWhitelistBlocks = document.querySelectorAll('.whitelist-building-block');
      
      // Check if we've reached the maximum of 20 entries
      const isMaxEntries = allWhitelistBlocks.length >= this.maxWhitelistEntries;
      
      // Update button state
      addEntryBtn.disabled = isMaxEntries;
      addEntryBtn.className = `btn ${isMaxEntries ? 'btn-secondary' : 'btn-primary'}`;
      addEntryBtn.innerHTML = `<span class="add-icon">${isMaxEntries ? '✓' : '+'}</span>${isMaxEntries ? 'Maximum Entries Reached' : 'Add IP/Domain'}`;
    }
    
    // Also update delete button states
    this.updateWhitelistDeleteButtons();
  }

  // Check if all entries are valid before allowing new entry addition
  canAddNewEntry() {
    const allWhitelistInputs = document.querySelectorAll('input[name^="CFG_IPS_WHITELIST_"]');
    for (const input of allWhitelistInputs) {
      const entryValue = input.value.trim();
      
      // Check if entry is empty
      if (!entryValue) {
        // Flash empty input field
        input.style.animation = 'flash 0.5s ease-in-out 2';
        input.focus();
        setTimeout(() => {
          input.style.animation = '';
        }, 1000);
        
        // Show notification with safety check
        if (window.notificationSystem) {
          window.notificationSystem.error('Whitelist entry cannot be empty');
        } else {
          console.error('Whitelist entry cannot be empty');
        }
        return false; // Empty entry - don't allow adding new entry
      }
      
      // Check for duplicates with notification (always show)
      if (checkForDuplicateWhitelistEntry(input, entryValue)) {
        return false;
      }
      
      // Check entry format
      if (!validateWhitelistEntry(input, false)) { // Don't show notifications during bulk check
        // Flash invalid input field
        input.style.animation = 'flash 0.5s ease-in-out 2';
        input.focus();
        setTimeout(() => {
          input.style.animation = '';
        }, 1000);
        return false; // At least one entry has invalid format or duplicate
      }
    }
    return true; // All entries are valid and non-empty
  }
}

// Separate function to check for duplicates that always shows notifications
function checkForDuplicateWhitelistEntry(input, entryValue) {
  if (!entryValue) return false;
  
  const allWhitelistInputs = document.querySelectorAll('input[name^="CFG_IPS_WHITELIST_"]');
  const duplicates = Array.from(allWhitelistInputs).filter(otherInput => 
    otherInput !== input && otherInput.value.trim() === entryValue
  );
  const hasDuplicate = duplicates.length > 0;
  
  if (hasDuplicate) {
    input.style.borderColor = '#dc3545';
    input.title = 'Whitelist entry already exists';
    if (window.notificationSystem) {
      //console.log('Showing duplicate whitelist entry notification');
      window.notificationSystem.error('Whitelist entry "' + entryValue + '" already exists');
    } else {
      console.error('Whitelist entry already exists - notification system not available');
    }
    return true;
  }
  
  return false;
}

// Separate function to check for invalid format that always shows notifications
function checkForInvalidWhitelistFormat(input, entryValue) {
  if (!entryValue) return false;
  
  // IP address regex (supports IPv4 and IPv6)
  const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/i;
  // Domain regex (supports subdomains and multiple TLD levels)
  const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?(?:\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?)*\.[a-zA-Z]{2,}$/;
  
  const isValidIP = ipRegex.test(entryValue);
  const isValidDomain = domainRegex.test(entryValue);
  const isValidFormat = isValidIP || isValidDomain;
  
  if (!isValidFormat) {
    input.style.borderColor = '#dc3545';
    input.title = 'Invalid IP address or domain format (e.g., 192.168.1.100 or example.com)';
    if (window.notificationSystem) {
      //console.log('Showing invalid whitelist format notification');
      window.notificationSystem.error('Invalid whitelist format: "' + entryValue + '". Please use a valid IP address or domain like 192.168.1.100 or example.com');
    } else {
      console.error('Invalid whitelist format - notification system not available');
    }
    return true;
  }
  
  return false;
}

// Validate whitelist entry format when user tries to add a new entry
function validateWhitelistEntry(input, showNotifications = true) {
  const value = input.value.trim();
  //console.log('validateWhitelistEntry called with:', value, 'showNotifications:', showNotifications);
  //console.log('window.notificationSystem available:', !!window.notificationSystem);
  
  if (!value) {
    // Clear styling for empty fields
    input.style.borderColor = '#dc3545';
    input.title = 'Whitelist entry cannot be empty';
    if (showNotifications && window.notificationSystem) {
      //console.log('Attempting to show empty whitelist notification');
      window.notificationSystem.error('Whitelist entry cannot be empty');
    } else {
      console.error('Whitelist entry cannot be empty - notification system not available');
    }
    return false; // Empty fields are not valid for adding new entries
  }
  
  // Special case for localhost
  if (value.toLowerCase() === 'localhost') {
    input.style.borderColor = '';
    input.title = '';
    return true; // localhost is always valid
  }
  
  // IP address regex (supports IPv4 and IPv6)
  const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/i;
  // Domain regex (supports subdomains and multiple TLD levels)
  const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?(?:\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?)*\.[a-zA-Z]{2,}$/;
  
  const isValidIP = ipRegex.test(value);
  const isValidDomain = domainRegex.test(value);
  const isValidFormat = isValidIP || isValidDomain || value.toLowerCase() === 'localhost';
  
  if (!isValidFormat) {
    input.style.borderColor = '#dc3545';
    input.title = 'Invalid IP address, domain, or localhost format (e.g., 192.168.1.100, example.com, or localhost)';
    if (showNotifications && window.notificationSystem) {
      //console.log('Attempting to show invalid whitelist format notification');
      window.notificationSystem.error('Invalid whitelist format: "' + value + '". Please use a valid IP address, domain, or localhost like 192.168.1.100, example.com, or localhost');
    } else {
      console.error('Invalid whitelist format - notification system not available');
    }
    return false;
  } else {
    input.style.borderColor = '';
    input.title = '';
    return true;
  }
}

// Standalone whitelist management functions - immediately available
window.addWhitelistEntry = function() {
  if (typeof window.IPWhitelistManager !== 'undefined' && window.IPWhitelistManager.addWhitelistEntry) {
    return window.IPWhitelistManager.addWhitelistEntry();
  }
  console.error('addWhitelistEntry called but IPWhitelistManager not available');
};

window.deleteWhitelistEntry = function(entryKey, buttonElement) {
  if (typeof window.IPWhitelistManager !== 'undefined' && window.IPWhitelistManager.deleteWhitelistEntry) {
    return window.IPWhitelistManager.deleteWhitelistEntry(entryKey, buttonElement);
  }
  console.error('deleteWhitelistEntry called but IPWhitelistManager not available');
};

window.validateWhitelistEntry = function(input, showNotifications) {
  if (typeof window.IPWhitelistManager !== 'undefined' && window.IPWhitelistManager.validateWhitelistEntry) {
    return window.IPWhitelistManager.validateWhitelistEntry(input, showNotifications);
  }
  console.error('validateWhitelistEntry called but IPWhitelistManager not available');
};

// Standalone functions - immediately available
window.saveWhitelistEntries = function() {
  if (typeof window.IPWhitelistManager !== 'undefined' && window.IPWhitelistManager.saveWhitelistEntries) {
    return window.IPWhitelistManager.saveWhitelistEntries();
  }
  console.error('saveWhitelistEntries called but IPWhitelistManager not available');
};

// IP Whitelist Manager initialization is now handled by SystemLoader
// IPWhitelistManager instance will be created centrally
