/**
 * taggcodeApp.js
 * Dynamische AssetMenu implementatie met TagcodeApp API
 * Vervangt de statische assetData met calls naar REST-endpoints.
 */

class TagcodeApp {
  constructor(baseURL = 'https://pimmoerman.nl/rdlab/tagcode.app/v2.1/api') {
    this.baseURL = baseURL;
  }

  async fetchData(path, params = {}) {
    const url = new URL(`${this.baseURL}/${path}`);
    Object.entries(params).forEach(([key, value]) => {
      url.searchParams.append(key, value);
    });
    const response = await fetch(url);
    if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    const json = await response.json();
    if (!json.success) throw new Error(json.error || json.message);
    return json.data;
  }

  // Asset endpoints
  getAllAssets() {
    return this.fetchData('asset/get_all_assets.php');
  }

  getAssetDetail(tag_code) {
    return this.fetchData('asset/get_detail_asset.php', { tag_code });
  }

  getAssetHistory(asset_tag_number) {
    return this.fetchData('asset/get_history_asset.php', { asset_tag_number });
  }

  getAssetHierarchy(asset_tag_number) {
    return this.fetchData('asset/get_asset_hierarchy.php', { asset_tag_number });
  }

  createOrUpdateAsset(params) {
    return this.fetchData('asset/create_asset.php', params);
  }

  // Product & vendor endpoints
  getVendors() {
    return this.fetchData('vendor/get_vendors.php');
  }

  getSubtypes(vendor_name) {
    return this.fetchData('product/get_subtypesFromVendor.php', { vendor_name });
  }

  getSubtypesForCategory(vendor_name, category) {
    return this.fetchData('product/get_subtypesFromVendorAndCategory.php', { 
      vendor_name, 
      category 
    });
  }

  getProductModels(vendor_name, product_subtype_name) {
    return this.fetchData('product/get_product_models.php', { vendor_name, product_subtype_name });
  }

  getLocations() {
    return this.fetchData('location/get_locations.php');
  }
}

class DynamicAssetMenu {
  constructor(nodeName, api = new TagcodeApp()) {
    
    this.nodeName = nodeName;
    this.api = api;

    //temp translation table for nodeName to API
    // Mapping van nodeName naar softwareType
    this.softwareTypeMapping = {
      'measurement': 'Sensor',
      'rotatingMachine': 'machine',
      'valve': 'valve',
      'pump': 'machine',
      'heatExchanger': 'machine',
      // Voeg meer mappings toe als nodig
    };
    
    // Bepaal automatisch de softwareType
    this.softwareType = this.softwareTypeMapping[nodeName] || nodeName;
    

    this.data = {
      vendors: [],
      subtypes: {},
      models: {}
    };
  }

  //Added missing getAllMenuData method

  getAllMenuData() {
    return {
      vendors: this.data.vendors || [],
      locations: this.data.locations || [],
      htmlTemplate: this.getHtmlTemplate()
    };
  }

  /**
   * Initialiseer: haal alleen de vendor-lijst en locaties op
   */
  async init() {
    try {
      this.data.suppliers = await this.api.getVendors();
      this.data.locations = await this.api.getLocations();
    } catch (error) {
      console.error('Failed to initialize DynamicAssetMenu:', error);
      this.data.suppliers = [];
      this.data.locations = [];
    }
  }


//Complete getClientInitCode method with full TagcodeApp definition

getClientInitCode(nodeName) {
  return `
    // --- DynamicAssetMenu voor ${nodeName} ---
    
    // ✅ Define COMPLETE TagcodeApp class in browser context
    window.TagcodeApp = window.TagcodeApp || class {
      constructor(baseURL = 'https://pimmoerman.nl/rdlab/tagcode.app/v2.1/api') {
        this.baseURL = baseURL;
      }

      async fetchData(path, params = {}) {
        const url = new URL(this.baseURL + '/' + path);
        Object.entries(params).forEach(([key, value]) => {
          url.searchParams.append(key, value);
        });
        const response = await fetch(url);
        if (!response.ok) throw new Error('HTTP ' + response.status + ': ' + response.statusText);
        const json = await response.json();
        if (!json.success) throw new Error(json.error || json.message);
        return json.data;
      }

      // ✅ ALL API methods defined here
      getAllAssets() { 
        return this.fetchData('asset/get_all_assets.php'); 
      }
      
      getAssetDetail(tag_code) { 
        return this.fetchData('asset/get_detail_asset.php', { tag_code }); 
      }
      
      getVendors() { 
        return this.fetchData('vendor/get_vendors.php'); 
      }
      
      getSubtypes(vendor_name, category = null) { 
        const params = { vendor_name };
        if (category) params.category = category;
        return this.fetchData('product/get_subtypesFromVendor.php', params); 
      }
      
      getProductModels(vendor_name, product_subtype_name) { 
        return this.fetchData('product/get_product_models.php', { vendor_name, product_subtype_name }); 
      }
      
      getLocations() { 
        return this.fetchData('location/get_locations.php'); 
      }
    };

    // ✅ Initialize the API instance BEFORE it's needed
    window.assetAPI = window.assetAPI || new window.TagcodeApp();

    // Helper populate function
    function populate(el, opts, sel) {
      if (!el) return;
      const old = el.value;
      el.innerHTML = '<option value="">Select…</option>';
      (opts||[]).forEach(o=>{
        const opt = document.createElement('option');
        opt.value = o; 
        opt.textContent = o;
        el.appendChild(opt);
      });
      el.value = sel || '';
      if (el.value !== old) el.dispatchEvent(new Event('change'));
    }

    // ✅ Ensure namespace exists and initialize properly
    if (!window.EVOLV.nodes.${nodeName}.assetMenu) {
      window.EVOLV.nodes.${nodeName}.assetMenu = {};
    }

    // ✅ Complete initEditor function
    window.EVOLV.nodes.${nodeName}.assetMenu.initEditor = async function(node) {
      try {
        console.log('🚀 Starting asset menu initialization for ${nodeName}');
        console.log('🎯 Automatic softwareType: ${this.softwareType}');

        // ✅ Verify API is available
        if (!window.assetAPI) {
          console.error('❌ window.assetAPI not available');
          return;
        }

        // ✅ Wait for DOM to be ready and inject HTML with retry
        const waitForDialogAndInject = () => {
          return new Promise((resolve) => {
            let attempts = 0;
            const maxAttempts = 20;
            
            const tryInject = () => {
              attempts++;
              console.log('Injection attempt ' + attempts + '/' + maxAttempts);
              
              const injectionSuccess = this.injectHtml ? this.injectHtml() : false;
              
              if (injectionSuccess) {
                console.log('✅ HTML injection successful on attempt:', attempts);
                resolve(true);
              } else if (attempts < maxAttempts) {
                setTimeout(tryInject, 100);
              } else {
                console.warn('⚠️ HTML injection failed after ' + maxAttempts + ' attempts');
                resolve(false);
              }
            };
            
            setTimeout(tryInject, 200);
          });
        };

        // Wait for HTML injection
        const htmlReady = await waitForDialogAndInject();
        
        if (!htmlReady) {
          console.error('❌ Could not inject HTML, continuing without asset menu');
          return;
        }

        console.log('🔧 Setting up asset menu functionality');

        // ✅ Load vendor list with error handling
        try {
          console.log('📡 Loading vendors...');
          const vendors = await window.assetAPI.getVendors();
          console.log('✅ Vendors loaded:', vendors.length);
          
          // ✅ Handle both string arrays and object arrays
          const vendorNames = vendors.map(v => v.name || v);
          populate(document.getElementById('node-input-supplier'), vendorNames, node.supplier);
        } catch (vendorError) {
          console.error('❌ Error loading vendors:', vendorError);
        }

        // ✅ Get form elements
        const elems = {
          supplier: document.getElementById('node-input-supplier'),
          category: document.getElementById('node-input-category'),
          type: document.getElementById('node-input-assetType'),
          model: document.getElementById('node-input-model'),
          unit: document.getElementById('node-input-unit')
        };

        // ✅ Set automatic category value
        if (elems.category) {
          elems.category.value = '${this.softwareType}';
          console.log('✅ Automatic category set to:', elems.category.value);
        }

        // ✅ Supplier change: load subtypes for automatic category
        if (elems.supplier) {
          elems.supplier.addEventListener('change', async () => {
            const vendor = elems.supplier.value;
            const category = '${this.softwareType}';
            
            if (!vendor) {
              populate(elems.type, [], '');
              populate(elems.model, [], '');
              populate(elems.unit, [], '');
              return;
            }
            
            try {
              console.log('📡 Loading subtypes for vendor:', vendor, 'category:', category);
              const subtypes = await window.assetAPI.getSubtypes(vendor, category);
              console.log('✅ Subtypes loaded:', subtypes.length);
              
              const subtypeNames = subtypes.map(s => s.name || s.subtype_name || s);
              populate(elems.type, subtypeNames, node.assetType);
              
              populate(elems.model, [], '');
              populate(elems.unit, [], '');
              
            } catch (error) {
              console.error('❌ Error loading subtypes:', error);
              populate(elems.type, [], '');
            }
          });
        }

        // ✅ Type change: load models for vendor + selected subtype
        if (elems.type) {
          elems.type.addEventListener('change', async () => {
            const vendor = elems.supplier.value;
            const selectedSubtype = elems.type.value;
            
            if (!vendor || !selectedSubtype) {
              populate(elems.model, [], '');
              populate(elems.unit, [], '');
              return;
            }
            
            try {
              console.log('📡 Loading models for vendor:', vendor, 'subtype:', selectedSubtype);
              const models = await window.assetAPI.getProductModels(vendor, selectedSubtype);
              console.log('✅ Models loaded:', models.length);
              
              window._currentModels = models;
              const modelNames = models.map(m => m.name || m.model_name || m);
              populate(elems.model, modelNames, node.model);
              
              populate(elems.unit, [], '');
              
            } catch (error) {
              console.error('❌ Error loading models:', error);
              populate(elems.model, [], '');
            }
          });
        }

        // ✅ Model change: show units for selected model
        if (elems.model) {
          elems.model.addEventListener('change', () => {
            const selectedModelName = elems.model.value;
            const models = window._currentModels || [];
            const selectedModel = models.find(m => 
              (m.name || m.model_name) === selectedModelName
            );
            
            const units = selectedModel && selectedModel.product_model_meta ? 
              Object.keys(selectedModel.product_model_meta) : [];
            populate(elems.unit, units, node.unit);
          });
        }

        // ✅ Trigger supplier change if there's a saved value
        if (node.supplier && elems.supplier) {
          setTimeout(() => {
            elems.supplier.dispatchEvent(new Event('change'));
          }, 100);
        }

        console.log('✅ Asset menu initialization complete for ${nodeName}');

      } catch (error) {
        console.error('❌ Error in asset menu initialization:', error);
      }
    };
  `;
}

  getHtmlTemplate() {
  return `
    <!-- Asset Properties -->
    <hr />
    <h3>Asset selection (${this.softwareType})</h3>
    <div class="form-row">
      <label for="node-input-supplier"><i class="fa fa-industry"></i> Supplier</label>
      <select id="node-input-supplier" style="width:70%;"></select>
    </div>
    <!-- ✅ Toon softwareType als readonly info -->
    <div class="form-row">
      <label><i class="fa fa-sitemap"></i> Category</label>
      <input type="text" value="${this.softwareType}" readonly style="width:70%; background-color: #f5f5f5;" />
      <input type="hidden" id="node-input-category" value="${this.softwareType}" />
    </div>
    <div class="form-row">
      <label for="node-input-assetType"><i class="fa fa-puzzle-piece"></i> Type</label>
      <select id="node-input-assetType" style="width:70%;"></select>
    </div>
    <div class="form-row">
      <label for="node-input-model"><i class="fa fa-wrench"></i> Model</label>
      <select id="node-input-model" style="width:70%;"></select>
    </div>
    <div class="form-row">
      <label for="node-input-unit"><i class="fa fa-balance-scale"></i> Unit</label>
      <select id="node-input-unit" style="width:70%;"></select>
    </div>
    <hr />
  `;
}

  /**
   *  Fixed getHtmlInjectionCode method
   */
/**
 *  Fixed getHtmlInjectionCode method with better element detection
 */
getHtmlInjectionCode(nodeName) {
  const htmlTemplate = this.getHtmlTemplate().replace(/`/g, '\\`').replace(/\${/g, '\\${');
  
  return `
    //  Enhanced HTML injection with multiple fallback strategies
    window.EVOLV.nodes.${nodeName}.assetMenu.injectHtml = function() {
      try {
        // Strategy 1: Find the dialog form container
        let targetContainer = document.querySelector('#red-ui-editor-dialog .red-ui-editDialog-content');
        
        // Strategy 2: Fallback to the main dialog form
        if (!targetContainer) {
          targetContainer = document.querySelector('#dialog-form');
        }
        
        // Strategy 3: Fallback to any form in the editor dialog
        if (!targetContainer) {
          targetContainer = document.querySelector('#red-ui-editor-dialog form');
        }
        
        // Strategy 4: Find by Red UI classes
        if (!targetContainer) {
          targetContainer = document.querySelector('.red-ui-editor-dialog .editor-tray-content');
        }

        if (targetContainer) {
          // Remove any existing asset menu to prevent duplicates
          const existingAssetMenu = targetContainer.querySelector('.asset-menu-section');
          if (existingAssetMenu) {
            existingAssetMenu.remove();
          }

          // Create container div
          const assetMenuDiv = document.createElement('div');
          assetMenuDiv.className = 'asset-menu-section';
          assetMenuDiv.innerHTML = \`${htmlTemplate}\`;
          
          // Insert at the beginning of the form
          targetContainer.insertBefore(assetMenuDiv, targetContainer.firstChild);
          
          console.log(' Asset menu HTML injected successfully into:', targetContainer.className || targetContainer.tagName);
          return true;
        } else {
          console.warn('⚠️ Could not find dialog form container. Available elements:');
          console.log('Available dialogs:', document.querySelectorAll('[id*="dialog"], [class*="dialog"]'));
          console.log('Available forms:', document.querySelectorAll('form'));
          return false;
        }
      } catch (error) {
        console.error('❌ Error injecting HTML:', error);
        return false;
      }
    };
  `;
}
}

// Exporteer voor gebruik in Node-RED
module.exports = { TagcodeApp, DynamicAssetMenu };

/*
// --- Test CLI ---
// Voer deze test uit met `node tagcodeApp.js` om de API-client en menu-init logica te controleren
if (require.main === module) {
  (async () => {
    const api = new TagcodeApp();
    console.log('=== Test: getVendors() ===');
    let vendors;
    try {
      vendors = await api.getVendors();
      console.log('Vendors:', vendors);
    } catch (e) {
      console.error('getVendors() error:', e.message);
      return;
    }

    console.log('=== Test: getLocations() ===');
    try {
      const locations = await api.getLocations();
      console.log('Locations:', locations);
    } catch (e) {
      console.error('getLocations() error:', e.message);
      return;
    }

    // ✅ Test verschillende nodeNames met automatische softwareType mapping
    const testNodes = [
      { nodeName: 'measurement', expectedSoftwareType: 'Sensor' },
      { nodeName: 'rotatingMachine', expectedSoftwareType: 'machine' },
      { nodeName: 'valve', expectedSoftwareType: 'valve' }
    ];

    for (const testNode of testNodes) {
      console.log(`\n=== Test: ${testNode.nodeName} → ${testNode.expectedSoftwareType} ===`);
      
      // Initialize DynamicAssetMenu met automatische softwareType
      const menu = new DynamicAssetMenu(testNode.nodeName, api);
      console.log(`✅ Automatic softwareType for ${testNode.nodeName}:`, menu.softwareType);
      
      try {
        await menu.init();
        console.log('Preloaded suppliers:', menu.data.suppliers.map(v=>v.name || v));
      } catch (e) {
        console.error(`DynamicAssetMenu.init() error for ${testNode.nodeName}:`, e.message);
        continue;
      }

      console.log(`=== Sequential dropdown simulation for ${testNode.nodeName} ===`);
      
      // 1. Select supplier
      const supplier = menu.data.suppliers[0];
      const supplierName = supplier.name || supplier;
      console.log('Selected supplier:', supplierName);

      // 2. ✅ Gebruik automatische softwareType in plaats van dropdown
      const automaticCategory = menu.softwareType;
      console.log('Automatic category (softwareType):', automaticCategory);

      // 3. ✅ Direct naar models met supplier + automatische category
      let models;
      try {
        console.log(`📡 Loading models for supplier: "${supplierName}", category: "${automaticCategory}"`);
        models = await api.getProductModels(supplierName, automaticCategory);
        console.log('Fetched models:', models.map(m=>m.name || m));
        
        if (models.length === 0) {
          console.warn(`⚠️ No models found for ${supplierName} + ${automaticCategory}`);
          continue;
        }
      } catch (e) {
        console.error(`getProductModels error for ${supplierName} + ${automaticCategory}:`, e.message);
        continue;
      }

      // 4. Extract unique types from models
      const types = Array.from(new Set(models.map(m => m.product_model_type || m.type || 'Unknown')));
      console.log('Available types:', types);
      
      if (types.length === 0) {
        console.warn('⚠️ No types found in models');
        continue;
      }

      // 5. Choose first type
      const selectedType = types[0];
      console.log('Selected type:', selectedType);

      // 6. Filter models by type
      const filteredModels = models.filter(m => 
        (m.product_model_type || m.type) === selectedType
      );
      console.log('Models for selected type:', filteredModels.map(m => m.name || m));

      if (filteredModels.length === 0) {
        console.warn('⚠️ No models found for selected type');
        continue;
      }

      // 7. Choose first model and show units
      const model = filteredModels[0];
      console.log('Selected model:', model.name || model);
      
      const units = model.product_model_meta ? Object.keys(model.product_model_meta) : [];
      console.log('Available units:', units);
      const unit = units[0] || 'N/A';
      console.log('Selected unit:', unit);

      console.log(`✅ Complete flow for ${testNode.nodeName}:`);
      console.log(`   Supplier: ${supplierName}`);
      console.log(`   Category: ${automaticCategory} (automatic)`);
      console.log(`   Type: ${selectedType}`);
      console.log(`   Model: ${model.name || model}`);
      console.log(`   Unit: ${unit}`);
    }

    console.log('\n=== Test verschillende softwareTypes ===');
    
    // Test of de API verschillende categories ondersteunt
    const testCategories = ['Sensor', 'machine', 'valve', 'pump'];
    const testSupplier = 'Vega'; // Bijvoorbeeld
    
    for (const category of testCategories) {
      try {
        console.log(`\n📡 Testing category: ${category} with supplier: ${testSupplier}`);
        const models = await api.getProductModels(testSupplier, category);
        console.log(`✅ Found ${models.length} models for ${testSupplier} + ${category}`);
        
        if (models.length > 0) {
          const sampleModel = models[0];
          console.log(`   Sample model:`, sampleModel.name || sampleModel);
          
          const types = Array.from(new Set(models.map(m => m.product_model_type || m.type)));
          console.log(`   Available types:`, types);
        }
      } catch (e) {
        console.warn(`⚠️ No models found for ${testSupplier} + ${category}: ${e.message}`);
      }
    }

    console.log('\n=== Klaar met alle tests ===');
  })();
}
  */