/**
 * HTML generation and endpoint methods for MenuUtils.
 * Handles generating dropdown HTML and serving MenuUtils code to the browser.
 */

const htmlGeneration = {
  generateHtml(htmlElement, options, savedValue) {
    htmlElement.innerHTML = options.length
      ? `<option value="">Select...</option>${options
          .map((opt) => `<option value="${opt}">${opt}</option>`)
          .join("")}`
      : "<option value=''>No options available</option>";

    if (savedValue && options.includes(savedValue)) {
      htmlElement.value = savedValue;
    }
  },

  createMenuUtilsEndpoint(RED, nodeName, customHelpers = {}, options = {}) {
    const basePath = `/${nodeName}/resources`;

    RED.httpAdmin.get(`${basePath}/menuUtilsData.json`, function(req, res) {
      res.json(this.generateMenuUtilsData(nodeName, customHelpers, options));
    }.bind(this));

    RED.httpAdmin.get(`${basePath}/menuUtils.legacy.js`, function(req, res) {
      res.set('Content-Type', 'application/javascript');
      const browserCode = this.generateLegacyMenuUtilsCode(nodeName, customHelpers);
      res.send(browserCode);
    }.bind(this));

    RED.httpAdmin.get(`${basePath}/menuUtils.js`, function(req, res) {
      res.set('Content-Type', 'application/javascript');
      res.send(this.generateMenuUtilsBootstrap(nodeName));
    }.bind(this));
  },

  generateMenuUtilsData(nodeName, customHelpers = {}, options = {}) {
    const defaultHelpers = {
      validateRequired: `function(value) {
        return value && value.toString().trim() !== '';
      }`,
      formatDisplayValue: `function(value, unit) {
        return \`\${value} \${unit || ''}\`.trim();
      }`
    };

    return {
      nodeName,
      helpers: { ...defaultHelpers, ...customHelpers },
      options: {
        autoLoadLegacy: options.autoLoadLegacy !== false,
      },
    };
  },

  generateMenuUtilsBootstrap(nodeName) {
    return `
    // Stable bootstrap for EVOLV menu utils (${nodeName})
    (function() {
      const nodeName = ${JSON.stringify(nodeName)};
      const basePath = '/' + nodeName + '/resources';

      window.EVOLV = window.EVOLV || {};
      window.EVOLV.nodes = window.EVOLV.nodes || {};
      window.EVOLV.nodes[nodeName] = window.EVOLV.nodes[nodeName] || {};
      window.EVOLV.nodes[nodeName].utils = window.EVOLV.nodes[nodeName].utils || {};

      function parseHelper(fnBody) {
        try {
          return (new Function('return (' + fnBody + ')'))();
        } catch (error) {
          console.error('[menuUtils] helper parse failed:', error);
          return function() { return null; };
        }
      }

      function loadLegacyIfNeeded(autoLoadLegacy) {
        if (!autoLoadLegacy || typeof window.MenuUtils === 'function') return Promise.resolve();
        return new Promise((resolve, reject) => {
          const script = document.createElement('script');
          script.src = basePath + '/menuUtils.legacy.js';
          script.onload = resolve;
          script.onerror = reject;
          document.head.appendChild(script);
        });
      }

      fetch(basePath + '/menuUtilsData.json')
        .then(function(res) { return res.json(); })
        .then(function(payload) {
          const helperFns = {};
          Object.entries(payload.helpers || {}).forEach(function(entry) {
            helperFns[entry[0]] = parseHelper(entry[1]);
          });
          window.EVOLV.nodes[nodeName].utils.helpers = helperFns;
          return loadLegacyIfNeeded(payload.options && payload.options.autoLoadLegacy);
        })
        .then(function() {
          if (typeof window.MenuUtils === 'function' && !window.EVOLV.nodes[nodeName].utils.menuUtils) {
            window.EVOLV.nodes[nodeName].utils.menuUtils = new window.MenuUtils();
          }
        })
        .catch(function(error) {
          console.error('[menuUtils] bootstrap failed for ' + nodeName, error);
        });
    })();
    `;
  },

  generateLegacyMenuUtilsCode(nodeName, customHelpers = {}) {
    const allHelpers = { ...this.generateMenuUtilsData(nodeName).helpers, ...customHelpers };

    const helpersCode = Object.entries(allHelpers)
      .map(([name, func]) => `        ${name}: ${func}`)
      .join(',\n');

    const classCode = this.constructor.toString(); // <-- this gives full class MenuUtils {...}

    return `
      // Create EVOLV namespace structure
      window.EVOLV = window.EVOLV || {};
      window.EVOLV.nodes = window.EVOLV.nodes || {};
      window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {};

      // Inject MenuUtils class
      ${classCode}

      // Expose MenuUtils instance to namespace
      window.EVOLV.nodes.${nodeName}.utils = {
        menuUtils: new MenuUtils(),

        helpers: {
${helpersCode}
        }
      };

      // Optionally expose globally
      window.MenuUtils = MenuUtils;

      console.log('${nodeName} utilities loaded in namespace');
    `;
  },

  // Backward-compatible alias
  generateMenuUtilsCode(nodeName, customHelpers = {}) {
    return this.generateLegacyMenuUtilsCode(nodeName, customHelpers);
  },
};

module.exports = htmlGeneration;
