// asset.js
const fs   = require('fs');
const path = require('path');


class AssetMenu {
  /** Define path where to find data of assets in constructor for now */
  constructor(relPath = '../../datasets/assetData') {
    this.baseDir = path.resolve(__dirname, relPath);
    this.assetData = this._loadJSON('assetData');
  }

  _loadJSON(...segments) {
    const filePath = path.resolve(this.baseDir, ...segments) + '.json';
    try {
      return JSON.parse(fs.readFileSync(filePath, 'utf8'));
    } catch (err) {
      throw new Error(`Failed to load ${filePath}: ${err.message}`);
    }
  }
  
  /**
   * ADD THIS METHOD
   * Compiles all menu data from the file system into a single nested object.
   * This is run once on the server to pre-load everything.
   * @returns {object} A comprehensive object with all menu options.
   */
  getAllMenuData() {
    // load the raw JSON once
    const data = this._loadJSON('assetData');
    const allData = {};

    data.suppliers.forEach(sup => {
      allData[sup.name] = {};
      sup.categories.forEach(cat => {
        allData[sup.name][cat.name] = {};
        cat.types.forEach(type => {
          // here: store the full array of model objects, not just names
          allData[sup.name][cat.name][type.name] = type.models;
        });
      });
    });

    return allData;
  }

  /**
   * Convert the static initEditor function to a string that can be served to the client
   * @param {string} nodeName - The name of the node type
   * @returns {string} JavaScript code as a string
   */
getClientInitCode(nodeName) {
  // step 1: get the two helper strings
  const htmlCode = this.getHtmlInjectionCode(nodeName);
  const dataCode   = this.getDataInjectionCode(nodeName);
  const eventsCode = this.getEventInjectionCode(nodeName);
  const saveCode = this.getSaveInjectionCode(nodeName);


   return `
      // --- AssetMenu for ${nodeName} ---
      window.EVOLV.nodes.${nodeName}.assetMenu =
        window.EVOLV.nodes.${nodeName}.assetMenu || {};

      ${htmlCode}
      ${dataCode}
      ${eventsCode}
      ${saveCode}

      // wire it all up when the editor loads
      window.EVOLV.nodes.${nodeName}.assetMenu.initEditor = function(node) {
      // ------------------  BELOW sequence is important! -------------------------------
        console.log('Initializing asset properties for ${nodeName}…');
        this.injectHtml();
        // load the data and wire up events
        // this will populate the fields and set up the event listeners
        this.wireEvents(node);
        // this will load the initial data into the fields
        // this is important to ensure the fields are populated correctly
        this.loadData(node);
      };
    `;
  
}

getDataInjectionCode(nodeName) {
    return `
      // Asset Data loader for ${nodeName}
      window.EVOLV.nodes.${nodeName}.assetMenu.loadData = function(node) {
        const data = window.EVOLV.nodes.${nodeName}.menuData.asset;
        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')
        };
        function populate(el, opts, sel) {
          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'));
        }
        // initial population
        populate(elems.supplier, Object.keys(data), node.supplier);
      };
    `
  }

getEventInjectionCode(nodeName) {
    return `
      // Asset Event wiring for ${nodeName}
      window.EVOLV.nodes.${nodeName}.assetMenu.wireEvents = function(node) {
        const data = window.EVOLV.nodes.${nodeName}.menuData.asset;
        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')
        };
        function populate(el, opts, sel) {
          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'));
        }
        elems.supplier.addEventListener('change', ()=>{
          populate(elems.category,
            elems.supplier.value? Object.keys(data[elems.supplier.value]||{}) : [],
            node.category);
        });
        elems.category.addEventListener('change', ()=>{
          const s=elems.supplier.value, c=elems.category.value;
          populate(elems.type,
            (s&&c)? Object.keys(data[s][c]||{}) : [],
            node.assetType);
        });
        elems.type.addEventListener('change', ()=>{
          const s=elems.supplier.value, c=elems.category.value, t=elems.type.value;
          const md = (s&&c&&t)? data[s][c][t]||[] : [];
          populate(elems.model, md.map(m=>m.name), node.model);
        });
        elems.model.addEventListener('change', ()=>{
          const s=elems.supplier.value, c=elems.category.value, t=elems.type.value, m=elems.model.value;
          const md = (s&&c&&t)? data[s][c][t]||[] : [];
          const entry = md.find(x=>x.name===m);
          populate(elems.unit, entry? entry.units : [], node.unit);
        });
      };
    `
  }

/**
   * Generate HTML template for asset fields
   */
  getHtmlTemplate() {
    return `
      <!-- Asset Properties -->
      <hr />
      <h3>Asset selection</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>
      <div class="form-row">
        <label for="node-input-category"><i class="fa fa-sitemap"></i> Category</label>
        <select id="node-input-category" style="width:70%;"></select>
      </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 />
    `;
  }

  /**
   * Get client-side HTML injection code
   */
  getHtmlInjectionCode(nodeName) {
    const htmlTemplate = this.getHtmlTemplate().replace(/`/g, '\\`').replace(/\$/g, '\\$');
    
    return `
      // Asset HTML injection for ${nodeName}
      window.EVOLV.nodes.${nodeName}.assetMenu.injectHtml = function() {
        const placeholder = document.getElementById('asset-fields-placeholder');
        if (placeholder && !placeholder.hasChildNodes()) {
          placeholder.innerHTML = \`${htmlTemplate}\`;
          console.log('Asset HTML injected successfully');
        }
      };
    `;
  }

  /** 
   * Returns the JS that injects the saveEditor function 
   */
  getSaveInjectionCode(nodeName) {
    return `
      // Asset Save injection for ${nodeName}
      window.EVOLV.nodes.${nodeName}.assetMenu.saveEditor = function(node) {
        console.log('Saving asset properties for ${nodeName}…');
        const fields = ['supplier','category','assetType','model','unit'];
        const errors = [];
        fields.forEach(f => {
          const el = document.getElementById(\`node-input-\${f}\`);
          node[f] = el ? el.value : '';
        });
        if (node.assetType && !node.unit) errors.push('Unit must be set when type is specified.');
        if (!node.unit)             errors.push('Unit is required.');
        errors.forEach(e=>RED.notify(e,'error'));
        
        // --- DEBUG: show exactly what was saved ---
        const saved = fields.reduce((o,f) => { o[f] = node[f]; return o; }, {});
        console.log('→ assetMenu.saveEditor result:', saved);

        return errors.length===0;
      };
    `;
  }

}

module.exports = AssetMenu;
