// Port Manager Component - Handles port configuration for apps
class PortManager {
  constructor() {
    this.ports = [];
    this.availableServices = [];
    this.appName = null;
  }

  // Parse port configuration string into array of port objects
  parsePortConfig(configInput) {
    // Accepts either a single CFG_<APP>_PORT_N string OR an array of
    // them (preferred). The array form avoids the comma-join/split
    // round-trip that would shred multi-button button_text/url_path
    // values like "Speedtest,Results" and "/,/results/stats.php".
    let portEntries;
    if (Array.isArray(configInput)) {
      portEntries = configInput.filter(s => s && String(s).trim() !== '');
    } else {
      if (!configInput || String(configInput).trim() === '') return [];
      portEntries = String(configInput).split(',');
    }
    const ports = [];

    portEntries.forEach(entry => {
      const parts = entry.trim().split('|');
      // 12-col: parent|name|ext:int|access|proto|login|traefik|webui|label|url_path|subdomain|recommended
      // 10-col: parent|name|ext:int|access|proto|login|traefik|webui|label|url_path
      // 9-col:  parent|name|ext:int|access|proto|login|traefik|webui|label
      // 8-col:  parent|name|ext:int|access|proto|traefik|webui|label  (legacy, login defaults to false)
      if (parts.length >= 8) {
        const portMapping = parts[2].split(':');
        const external = portMapping[0] || '';
        const internal = portMapping[1] || '';

        const isTenCol = parts.length >= 10;
        const isNineCol = parts.length >= 9;
        const isTwelveCol = parts.length >= 12;
        // Recommended defaults to the webui flag when not stored on the row —
        // matches the panel's "primary list" expectation for apps that haven't
        // been migrated yet.
        const buttonEnabled = isNineCol ? (parts[7] === 'true') : (parts[6] === 'true');
        ports.push({
          service: parts[0] || '',
          name: parts[1] || '',
          external: external,
          internal: internal,
          access: parts[3] || 'private',
          protocol: parts[4] || 'tcp',
          login_required: isNineCol ? (parts[5] === 'true') : false,
          traefik_managed: isNineCol ? (parts[6] === 'true') : (parts[5] === 'true'),
          button_enabled: buttonEnabled,
          button_text: isNineCol ? (parts[8] || '') : (parts[7] || ''),
          url_path: isTenCol ? (parts[9] || '') : '',
          subdomain: isTwelveCol ? (parts[10] || '') : '',
          recommended: isTwelveCol ? (parts[11] === 'true') : buttonEnabled
        });
      }
    });
    
    return ports;
  }

  // Generate port configuration string from array of port objects.
  // Always emits the 12-col format (adds subdomain + recommended on top of the
  // existing 10-col login_required + url_path schema) so saves forward-migrate
  // any 8/9/10-col legacy entries automatically.
  generatePortConfig(ports) {
    return ports.map(port => {
      const portMapping = `${port.external}:${port.internal}`;
      const login = port.login_required ? 'true' : 'false';
      const urlPath = port.url_path || '';
      const subdomain = port.subdomain || '';
      const recommended = port.recommended ? 'true' : 'false';
      return `${port.service}|${port.name}|${portMapping}|${port.access}|${port.protocol}|${login}|${port.traefik_managed}|${port.button_enabled}|${port.button_text}|${urlPath}|${subdomain}|${recommended}`;
    }).join(',');
  }

  // Get available services for an app
  async getAvailableServices(appName) {
    //console.log(`🔌 PortManager: Getting services for app: ${appName}`);
    try {
      // Load apps data to get services for this app (with cache busting)
      const timestamp = Date.now();
      const response = await fetch(`/data/apps/generated/apps.json?t=${timestamp}`);
      if (!response.ok) {
        //console.log(`🔌 Failed to fetch apps.json: ${response.status}`);
        return [];
      }
      
      const appsData = await response.json();
      //console.log(`🔌 Apps data loaded:`, appsData);
      //console.log(`🔌 Available app names:`, appsData.apps.map(app => app.name));
      
      let app = appsData.apps.find(a => a.name === appName);
      //console.log(`🔌 Found app for ${appName}:`, app);
      
      // Try fuzzy matching if exact match fails
      if (!app) {
        const fuzzyApp = appsData.apps.find(a => 
          a.name.toLowerCase().includes(appName.toLowerCase()) || 
          appName.toLowerCase().includes(a.name.toLowerCase())
        );
        //console.log(`🔌 Fuzzy match for ${appName}:`, fuzzyApp);
        if (fuzzyApp) {
          app = fuzzyApp;
        }
      }
      
      if (app && app.services) {
        //console.log(`🔌 Services found for ${appName}:`, app.services);
        return app.services;
      }
      
      //console.log(`🔌 No services found for ${appName}`);
      return [];
    } catch (error) {
      console.error('Error loading services:', error);
      return [];
    }
  }

  // Validate port configuration
  validatePort(portData, allPorts) {
    const errors = [];

    // Check required fields
    if (!portData.service) errors.push('Service is required');
    if (!portData.internal) errors.push('Internal port is required');

    // Check port format
    if (portData.external && !portData.external.match(/^(random|\d+(:\d+)?)$/)) {
      errors.push('External port must be "random" or in format "8080" or "8080:8081"');
    }

    if (portData.internal && !portData.internal.match(/^\d+$/)) {
      errors.push('Internal port must be a valid port number');
    }

    // Check for conflicts (excluding current port)
    const conflicts = allPorts.filter((port, index) => {
      return port.internal === portData.internal && index !== allPorts.indexOf(portData);
    });

    if (conflicts.length > 0) {
      errors.push(`Internal port ${portData.internal} conflicts with another service`);
    }

    return errors;
  }

  // Add new port
  addPort() {
    const newPort = {
      service: '',
      external: 'random',
      internal: '',
      access: 'private',
      protocol: 'tcp',
      url_accessible: false,
      traefik_managed: true,
      login_required: false,
      label: '',
      autoMatched: false // Track if service was auto-matched
    };

    // Auto-select service if only one is available
    if (this.availableServices.length === 1) {
      newPort.service = this.availableServices[0];
      newPort.autoMatched = true;
    }

    this.ports.push(newPort);
    return newPort;
  }

  // Remove port with confirmation
  async removePort(index) {
    const port = this.ports[index];
    if (!port) return false;

    // Get app name from the port manager
    const appName = this.appName || document.querySelector('.port-manager')?.dataset.app;
    // Use internal port if available, otherwise show port number (index + 1)
    const portDisplay = port.internal ? `#${port.internal}` : `#${index + 1}`;
    
    // Get app title from the apps data for better display
    let appTitle = appName; // fallback to app name
    try {
      const response = await fetch(`/data/apps/generated/apps.json?t=${Date.now()}`);
      if (response.ok) {
        const appsData = await response.json();
        const app = appsData.apps.find(a => a.name === appName) || 
                   appsData.apps.find(a => a.name.toLowerCase().includes(appName.toLowerCase()));
        if (app) {
          appTitle = app.title || appName;
        }
      }
    } catch (error) {
      //console.log('Could not fetch app title, using app name');
    }

    // Show confirmation dialog
    const confirmed = await this.showConfirmation(
      'Remove Port',
      `Are you sure you want to remove port ${portDisplay} from ${appTitle}?`,
      'Remove'
    );

    if (confirmed) {
      this.ports.splice(index, 1);
      return true;
    }

    return false;
  }

  // Show confirmation dialog
  showConfirmation(title, message, confirmText) {
    return new Promise((resolve) => {
      // Create modal overlay
      const modal = document.createElement('div');
      modal.className = 'port-manager-modal-overlay';
      modal.innerHTML = `
        <div class="port-manager-modal">
          <div class="port-manager-modal-header">
            <h3>${title}</h3>
            <button class="port-manager-modal-close">&times;</button>
          </div>
          <div class="port-manager-modal-body">
            <p>${message}</p>
          </div>
          <div class="port-manager-modal-footer">
            <button class="btn btn-secondary port-manager-cancel">Cancel</button>
            <button class="btn btn-danger port-manager-confirm">${confirmText}</button>
          </div>
        </div>
      </div>
      `;

      // Add to page
      document.body.appendChild(modal);

      // Handle events
      const close = () => {
        document.body.removeChild(modal);
        resolve(false);
      };

      const confirm = () => {
        document.body.removeChild(modal);
        resolve(true);
      };

      modal.querySelector('.port-manager-modal-close').addEventListener('click', close);
      modal.querySelector('.port-manager-cancel').addEventListener('click', close);
      modal.querySelector('.port-manager-confirm').addEventListener('click', confirm);
      modal.addEventListener('click', (e) => {
        if (e.target === modal) close();
      });
    });
  }

  // Generate HTML for port manager
  generateHTML(appName, configValue) {
    // Parse existing configuration
    this.ports = this.parsePortConfig(configValue);
    
    let html = `
      <div class="port-manager port-manager-full-width" data-app="${appName}">
        <div class="port-manager-header">
          <h4>Port Configuration</h4>
          <div class="port-manager-header-actions">
            <label class="port-manager-advanced-toggle">
              <input type="checkbox" class="port-manager-show-advanced">
              <span>Show advanced fields</span>
            </label>
            <button type="button" class="btn btn-primary btn-sm add-port-btn">
              <span class="add-icon">+</span> Add Port
            </button>
          </div>
        </div>
        <div class="port-manager-list">
    `;

    // Generate port cards (simplified without individual headers)
    this.ports.forEach((port, index) => {
      html += this.generateSimplePortCard(port, index);
    });

    html += `
        </div>
        <input type="hidden" name="CFG_${appName.toUpperCase()}_PORT_MANAGER" value="${this.generatePortConfig(this.ports)}" class="port-manager-hidden">
      </div>
    `;

    return html;
  }

  // Generate simplified HTML for individual port card (with header)
  generateSimplePortCard(port, index) {
    return `
      <div class="port-card" data-index="${index}" data-access="${port.access}">
        <div class="port-card-header">
          <div class="port-card-title">Port ${index + 1}</div>
          <button type="button" class="btn btn-danger btn-xs remove-port-btn" data-index="${index}" title="Remove Port">
            <span class="remove-icon">×</span>
          </button>
        </div>
        <div class="port-card-body">
          <div class="port-row">
            <div class="port-field">
              <label>Service <span class="help-icon" title="The Docker service this port belongs to">?</span><span class="auto-match-indicator" title="✓ Auto-assigned: Only one service available" style="display:none;">✓</span></label>
              <select class="port-service" data-index="${index}">
                <option value="">Select a service...</option>
              </select>
            </div>
            <div class="port-field">
              <label>Name <span class="help-icon" title="Internal name for this port (e.g., webui, ssh, dns)">?</span></label>
              <input type="text" class="port-name" placeholder="webui, ssh, etc." value="${port.name}" data-index="${index}">
            </div>
            <div class="port-field">
              <label>External Port <span class="help-icon" title="External port mapping (use 'random' for auto-assignment)">?</span></label>
              <input type="text" class="port-external" placeholder="random or 8080" value="${port.external}" data-index="${index}">
            </div>
            <div class="port-field">
              <label>Internal Port <span class="help-icon" title="The port number inside the container">?</span></label>
              <input type="text" class="port-internal" placeholder="1111" value="${port.internal}" data-index="${index}">
            </div>
            <div class="port-field port-field-advanced">
              <label>Protocol <span class="help-icon" title="Network protocol for this port connection">?</span></label>
              <select class="port-protocol" data-index="${index}">
                <option value="tcp" ${port.protocol === 'tcp' ? 'selected' : ''}>TCP</option>
                <option value="udp" ${port.protocol === 'udp' ? 'selected' : ''}>UDP</option>
              </select>
            </div>
          </div>
          <div class="port-row">
            <div class="port-field">
              <label>Access <span class="help-icon" title="Who can access this port from the network">?</span></label>
              <select class="port-access" data-index="${index}">
                <option value="disabled" ${port.access === 'disabled' ? 'selected' : ''}>Disabled</option>
                <option value="private" ${port.access === 'private' ? 'selected' : ''}>Private</option>
                <option value="public" ${port.access === 'public' ? 'selected' : ''}>Public</option>
              </select>
            </div>
            <div class="port-field port-field-advanced">
              <label>Traefik Managed <span class="help-icon" title="Let Traefik handle reverse proxy for this port">?</span></label>
              <select class="port-traefik" data-index="${index}">
                <option value="false" ${!port.traefik_managed ? 'selected' : ''}>False</option>
                <option value="true" ${port.traefik_managed ? 'selected' : ''}>True</option>
              </select>
            </div>
            <div class="port-field port-field-advanced">
              <label>Button Enabled <span class="help-icon" title="Show this port as a clickable button in the main interface">?</span></label>
              <select class="port-button-enabled" data-index="${index}">
                <option value="false" ${!port.button_enabled ? 'selected' : ''}>False</option>
                <option value="true" ${port.button_enabled ? 'selected' : ''}>True</option>
              </select>
            </div>
            <div class="port-field port-field-advanced">
              <label>Login Required <span class="help-icon" title="Put this route behind Traefik basic auth (uses CFG_TRAEFIK_USER / CFG_TRAEFIK_PASS). Ignored when Authelia is enabled — Authelia takes precedence.">?</span></label>
              <select class="port-login-required" data-index="${index}" ${!port.traefik_managed ? 'disabled' : ''}>
                <option value="false" ${!port.login_required ? 'selected' : ''}>False</option>
                <option value="true" ${port.login_required ? 'selected' : ''}>True</option>
              </select>
            </div>
            <div class="port-field port-field-advanced">
              <label>Recommended <span class="help-icon" title="If true, this port shows up by default in the Traefik routing panel's primary list. Independent of Button Enabled — multiple ports per app can be recommended.">?</span></label>
              <select class="port-recommended" data-index="${index}">
                <option value="false" ${!port.recommended ? 'selected' : ''}>False</option>
                <option value="true" ${port.recommended ? 'selected' : ''}>True</option>
              </select>
            </div>
            <div class="port-field">
              <label>Button Text <span class="help-icon" title="Text displayed on the interface button for this service. Comma-separate to render multiple buttons sharing this port (line up with URL paths below).">?</span></label>
              <input type="text" class="port-button-text" placeholder="e.g. Speedtest,Results" value="${port.button_text}" data-index="${index}">
            </div>
            <div class="port-field port-field-advanced">
              <label>URL Path <span class="help-icon" title="Path appended to the URL when opening (e.g. /admin/). Leave empty for root. Comma-separate when paired with multiple Button Text labels for multi-button entries.">?</span></label>
              <input type="text" class="port-url-path" placeholder="e.g. /,/results/stats.php" value="${port.url_path || ''}" data-index="${index}">
            </div>
            <div class="port-field port-field-advanced">
              <label>Subdomain <span class="help-icon" title="The subdomain this port is served on — e.g. 'vault' → vault.example.com, or 'admin.app' for a multi-level host. Use @ for the root of your domain. Leave empty to default to the app's name.">?</span></label>
              <input type="text" class="port-subdomain" placeholder="vault  ·  @ = root  ·  blank = app name" value="${port.subdomain || ''}" data-index="${index}">
            </div>
          </div>
        </div>
      </div>
    `;
  }

  // Generate HTML for individual port card
  generatePortCard(port, index) {
    return `
      <div class="port-card" data-index="${index}">
        <div class="port-card-header">
          <button type="button" class="btn btn-danger btn-xs remove-port-btn" data-index="${index}" title="Remove Port">
            <span class="remove-icon">×</span>
          </button>
        </div>
        <div class="port-card-body">
          <div class="port-row">
            <div class="port-field">
              <label>Service</label>
              <select class="port-service" data-index="${index}">
                <option value="">Select a service...</option>
              </select>
            </div>
            <div class="port-field">
              <label>Name</label>
              <input type="text" class="port-name" placeholder="webui, ssh, etc." value="${port.name}" data-index="${index}">
            </div>
            <div class="port-field">
              <label>External Port</label>
              <input type="text" class="port-external" placeholder="random or 8080" value="${port.external}" data-index="${index}">
            </div>
            <div class="port-field">
              <label>Internal Port</label>
              <input type="text" class="port-internal" placeholder="1111" value="${port.internal}" data-index="${index}">
            </div>
          </div>
          <div class="port-row">
            <div class="port-field">
              <label>Protocol</label>
              <select class="port-protocol" data-index="${index}">
                <option value="tcp" ${port.protocol === 'tcp' ? 'selected' : ''}>TCP</option>
                <option value="udp" ${port.protocol === 'udp' ? 'selected' : ''}>UDP</option>
              </select>
            </div>
            <div class="port-field">
              <label>Access</label>
              <select class="port-access" data-index="${index}">
                <option value="disabled" ${port.access === 'disabled' ? 'selected' : ''}>Disabled</option>
                <option value="private" ${port.access === 'private' ? 'selected' : ''}>Private</option>
                <option value="public" ${port.access === 'public' ? 'selected' : ''}>Public</option>
              </select>
            </div>
            <div class="port-field">
              <label>Traefik Managed</label>
              <select class="port-traefik" data-index="${index}">
                <option value="false" ${!port.traefik_managed ? 'selected' : ''}>False</option>
                <option value="true" ${port.traefik_managed ? 'selected' : ''}>True</option>
              </select>
            </div>
          </div>
          <div class="port-row">
            <div class="port-field">
              <label>Button Enabled</label>
              <select class="port-button-enabled" data-index="${index}">
                <option value="false" ${!port.button_enabled ? 'selected' : ''}>False</option>
                <option value="true" ${port.button_enabled ? 'selected' : ''}>True</option>
              </select>
            </div>
            <div class="port-field">
              <label>Login Required</label>
              <select class="port-login-required" data-index="${index}" ${!port.traefik_managed ? 'disabled' : ''}>
                <option value="false" ${!port.login_required ? 'selected' : ''}>False</option>
                <option value="true" ${port.login_required ? 'selected' : ''}>True</option>
              </select>
            </div>
            <div class="port-field">
              <label>Button Text</label>
              <input type="text" class="port-button-text" placeholder="e.g. Speedtest,Results" value="${port.button_text}" data-index="${index}">
            </div>
            <div class="port-field">
              <label>URL Path</label>
              <input type="text" class="port-url-path" placeholder="e.g. /,/results/stats.php" value="${port.url_path || ''}" data-index="${index}">
            </div>
          </div>
        </div>
      </div>
    `;
  }

  // Initialize port manager after HTML is generated
  async initialize(appName) {
    this.appName = appName;
    this.availableServices = await this.getAvailableServices(appName);
    
    //console.log(`🔌 PortManager: Available services for ${appName}:`, this.availableServices);
    //console.log(`🔌 PortManager: Number of services: ${this.availableServices.length}`);
    
    // Force full-width layout for port manager containers
    this.forceFullWidthLayout();
    
    // Populate service dropdowns with auto-matching
    const serviceSelects = document.querySelectorAll('.port-service');
    serviceSelects.forEach(select => {
      const index = parseInt(select.dataset.index);
      const currentService = this.ports[index]?.service || '';
      
      //console.log(`🔌 PortManager: Port ${index} current service: "${currentService}"`);
      
      // Clear existing options
      select.innerHTML = '<option value="">Select a service...</option>';
      
      // Add service options
      this.availableServices.forEach(service => {
        const option = document.createElement('option');
        option.value = service;
        option.textContent = service;
        
        // Auto-matching logic
        let shouldAutoSelect = false;
        let isAutoMatched = false;
        
        if (this.availableServices.length === 1 && !currentService) {
          // Case 1: Only one service and no current service - auto-select
          shouldAutoSelect = true;
          isAutoMatched = true;
          //console.log(`🔌 PortManager: Auto-selecting single service "${service}" for port ${index}`);
        } else if (this.availableServices.length === 1 && currentService && currentService !== service) {
          // Case 2: Only one service but current service doesn't match - auto-match
          shouldAutoSelect = true;
          isAutoMatched = true;
          //console.log(`🔌 PortManager: Auto-matching service "${service}" (was "${currentService}") for port ${index}`);
        } else if (this.availableServices.length === 1 && currentService === service) {
          // Case 3: Single service and current service matches - still show auto-match indicator
          shouldAutoSelect = true;
          isAutoMatched = true;
          //console.log(`🔌 PortManager: Single service matches "${service}" for port ${index} - showing auto-match indicator`);
        } else if (this.availableServices.length > 1 && currentService === service) {
          // Case 4: Multiple services and current service matches - normal selection
          shouldAutoSelect = true;
          isAutoMatched = false;
          //console.log(`🔌 PortManager: Normal selection of service "${service}" for port ${index}`);
        }
        
        if (shouldAutoSelect) {
          option.selected = true;
          // Update the port data to reflect the selected service
          if (this.ports[index]) {
            this.ports[index].service = service;
            // Mark if this was auto-matched
            this.ports[index].autoMatched = isAutoMatched;
          }
        }
        
        select.appendChild(option);
      });
      
      // Add visual indicator for auto-matched services
      if (this.ports[index]?.autoMatched) {
        select.style.borderColor = '#28a745'; // Green border for auto-matched
        select.style.boxShadow = '0 0 0 2px rgba(40, 167, 69, 0.3)';
        
        // Show the auto-match indicator next to the help icon
        const autoMatchIndicator = select.parentElement.querySelector('.auto-match-indicator');
        if (autoMatchIndicator) {
          autoMatchIndicator.style.display = 'inline-flex';
        }
      }
    });

    // Add event listeners
    this.attachEventListeners();
    
    // Update all port fields after auto-selection
    this.updateAllPortFields();
  }

  // Force full-width layout for port manager containers
  forceFullWidthLayout() {
    const portContainers = document.querySelectorAll('.form-field[id^="PORT_"]');
    portContainers.forEach(container => {
      container.style.gridColumn = '1 / -1';
      container.style.width = '100%';
    });
  }

  // Attach event listeners
  attachEventListeners() {
    // Add port button
    const addBtn = document.querySelector('.add-port-btn');
    if (addBtn) {
      addBtn.addEventListener('click', () => {
        const newPort = this.addPort();
        this.refreshPortList();
      });
    }

    // Remove port buttons
    document.querySelectorAll('.remove-port-btn').forEach(btn => {
      btn.addEventListener('click', async (e) => {
        const index = parseInt(e.currentTarget.dataset.index);
        const removed = await this.removePort(index);
        if (removed) {
          this.refreshPortList();
        }
      });
    });

    // Show-advanced toggle — flips `show-advanced` class on the port-manager root;
    // CSS hides .port-field-advanced when the class isn't present.
    document.querySelectorAll('.port-manager-show-advanced').forEach(cb => {
      const mgr = cb.closest('.port-manager');
      const apply = () => { if (mgr) mgr.classList.toggle('show-advanced', cb.checked); };
      cb.addEventListener('change', apply);
      apply();
    });

    // Port field changes. Selector must include EVERY rendered class — fields not
    // listed here silently no-op when the user edits them, so port name and button
    // text edits were never persisted into the hidden CFG_*_PORT_N fields.
    document.querySelectorAll(
      '.port-service, .port-name, .port-external, .port-internal, ' +
      '.port-access, .port-protocol, .port-traefik, ' +
      '.port-button-enabled, .port-button-text, .port-url-path, ' +
      '.port-recommended, .port-subdomain'
    ).forEach(field => {
      field.addEventListener('change', () => this.updatePortData(field));
      field.addEventListener('input', () => this.updatePortData(field));
    });
  }

  // Update port data when field changes
  updatePortData(field) {
    const index = parseInt(field.dataset.index);
    const port = this.ports[index];
    if (!port) return;

    // Match by classList rather than === on className so additional classes added
    // elsewhere (e.g. validation styles) don't break the switch.
    if (field.classList.contains('port-service')) {
      port.service = field.value;
    } else if (field.classList.contains('port-name')) {
      port.name = field.value;
    } else if (field.classList.contains('port-external')) {
      port.external = field.value;
    } else if (field.classList.contains('port-internal')) {
      port.internal = field.value;
    } else if (field.classList.contains('port-access')) {
      port.access = field.value;
      const portCard = field.closest('.port-card');
      if (portCard) portCard.setAttribute('data-access', field.value);
    } else if (field.classList.contains('port-protocol')) {
      port.protocol = field.value;
    } else if (field.classList.contains('port-traefik')) {
      // <select> with "true"/"false" — treat as string-to-bool, not checkbox.
      port.traefik_managed = field.value === 'true';
      // Login Required only applies to Traefik-routed ports — disable +
      // force false when traefik is turned off so the saved config can't
      // claim "protected" on a port that bypasses Traefik.
      const loginSel = field.closest('.port-card')?.querySelector('.port-login-required');
      if (loginSel) {
        loginSel.disabled = !port.traefik_managed;
        if (!port.traefik_managed) {
          loginSel.value = 'false';
          port.login_required = false;
        }
      }
    } else if (field.classList.contains('port-button-enabled')) {
      port.button_enabled = field.value === 'true';
    } else if (field.classList.contains('port-login-required')) {
      port.login_required = field.value === 'true';
    } else if (field.classList.contains('port-button-text')) {
      port.button_text = field.value;
    } else if (field.classList.contains('port-url-path')) {
      port.url_path = field.value;
    } else if (field.classList.contains('port-recommended')) {
      port.recommended = field.value === 'true';
    } else if (field.classList.contains('port-subdomain')) {
      port.subdomain = field.value;
    }

    // Update hidden field and individual PORT_X fields
    this.updateAllPortFields();
  }

  // Update both the consolidated hidden field and individual PORT_X fields
  updateAllPortFields() {
    const consolidatedConfig = this.generatePortConfig(this.ports);
    
    // Update the main hidden field
    const hiddenField = document.querySelector('.port-manager-hidden');
    if (hiddenField) {
      hiddenField.value = consolidatedConfig;
    }
    
    // Update individual PORT_X fields
    this.updateIndividualPortFields();
  }

  // Update individual PORT_X fields in the form
  updateIndividualPortFields() {
    const appName = this.appName || document.querySelector('.port-manager')?.dataset.app;
    
    this.ports.forEach((port, index) => {
      const login = port.login_required ? 'true' : 'false';
      const portConfig = `${port.service}|${port.name}|${port.external}:${port.internal}|${port.access}|${port.protocol}|${login}|${port.traefik_managed}|${port.button_enabled}|${port.button_text}|${port.url_path || ''}`;
      const fieldName = `CFG_${appName.toUpperCase()}_PORT_${index + 1}`;
      
      // Find and update the individual PORT_X field
      const portField = document.querySelector(`[name="${fieldName}"]`);
      if (portField) {
        portField.value = portConfig;
      } else {
        // Create hidden field if it doesn't exist
        const hiddenField = document.createElement('input');
        hiddenField.type = 'hidden';
        hiddenField.name = fieldName;
        hiddenField.value = portConfig;
        const portManager = document.querySelector('.port-manager');
        if (portManager) {
          portManager.appendChild(hiddenField);
        }
      }
    });
  }

  // Refresh port list HTML
  refreshPortList() {
    const portList = document.querySelector('.port-manager-list');
    if (!portList) return;

    let html = '';
    this.ports.forEach((port, index) => {
      html += this.generateSimplePortCard(port, index);
    });

    portList.innerHTML = html;
    this.reinitializeAfterRefresh();
  }

  // Reinitialize after refresh (without duplicating event listeners)
  reinitializeAfterRefresh() {
    const appName = this.appName || document.querySelector('.port-manager')?.dataset.app;
    
    // Repopulate service dropdowns with auto-matching
    const serviceSelects = document.querySelectorAll('.port-service');
    serviceSelects.forEach(select => {
      const index = parseInt(select.dataset.index);
      const currentService = this.ports[index]?.service || '';
      
      //console.log(`🔌 PortManager: Port ${index} current service: "${currentService}"`);
      
      // Clear existing options
      select.innerHTML = '<option value="">Select a service...</option>';
      
      // Add service options
      this.availableServices.forEach(service => {
        const option = document.createElement('option');
        option.value = service;
        option.textContent = service;
        
        // Auto-matching logic
        let shouldAutoSelect = false;
        let isAutoMatched = false;
        
        if (this.availableServices.length === 1 && !currentService) {
          // Case 1: Only one service and no current service - auto-select
          shouldAutoSelect = true;
          isAutoMatched = true;
          //console.log(`🔌 PortManager: Auto-selecting single service "${service}" for port ${index}`);
        } else if (this.availableServices.length === 1 && currentService && currentService !== service) {
          // Case 2: Only one service but current service doesn't match - auto-match
          shouldAutoSelect = true;
          isAutoMatched = true;
          //console.log(`🔌 PortManager: Auto-matching service "${service}" (was "${currentService}") for port ${index}`);
        } else if (this.availableServices.length === 1 && currentService === service) {
          // Case 3: Single service and current service matches - still show auto-match indicator
          shouldAutoSelect = true;
          isAutoMatched = true;
          //console.log(`🔌 PortManager: Single service matches "${service}" for port ${index} - showing auto-match indicator`);
        } else if (this.availableServices.length > 1 && currentService === service) {
          // Case 4: Multiple services and current service matches - normal selection
          shouldAutoSelect = true;
          isAutoMatched = false;
          //console.log(`🔌 PortManager: Normal selection of service "${service}" for port ${index}`);
        }
        
        if (shouldAutoSelect) {
          option.selected = true;
          // Update the port data to reflect the selected service
          if (this.ports[index]) {
            this.ports[index].service = service;
            // Mark if this was auto-matched
            this.ports[index].autoMatched = isAutoMatched;
          }
        }
        
        select.appendChild(option);
      });
      
      // Add visual indicator for auto-matched services
      if (this.ports[index]?.autoMatched) {
        select.style.borderColor = '#28a745'; // Green border for auto-matched
        select.style.boxShadow = '0 0 0 2px rgba(40, 167, 69, 0.3)';
        
        // Show the auto-match indicator next to the help icon
        const autoMatchIndicator = select.parentElement.querySelector('.auto-match-indicator');
        if (autoMatchIndicator) {
          autoMatchIndicator.style.display = 'inline-flex';
        }
      }
    });

    // Re-attach remove port button listeners (these are new elements)
    document.querySelectorAll('.remove-port-btn').forEach(btn => {
      btn.addEventListener('click', async (e) => {
        const index = parseInt(e.currentTarget.dataset.index);
        const removed = await this.removePort(index);
        if (removed) {
          this.refreshPortList();
        }
      });
    });

    // Re-attach port field change listeners (these are new elements)
    document.querySelectorAll('.port-service, .port-external, .port-internal, .port-access, .port-protocol, .port-traefik, .port-url, .port-label').forEach(field => {
      field.addEventListener('change', () => this.updatePortData(field));
    });
  }
}

// Export for use in other modules
if (typeof module !== 'undefined' && module.exports) {
  module.exports = PortManager;
} else {
  window.PortManager = PortManager;
}
