// Map a child's raw softwareType (the lowercased node name from
// buildConfig) to the "role" key that parent registerChild() handlers
// dispatch on. Without this, MGC/pumpingStation register-handlers (which
// branch on 'machine' / 'machinegroup' / 'pumpingstation' / 'measurement')
// silently miss every real production child because rotatingMachine
// reports softwareType='rotatingmachine' and machineGroupControl reports
// 'machinegroupcontrol'. Existing tests that pass already-aliased keys
// ('machine', 'machinegroup') stay green because those aren't in the
// alias map and pass through unchanged.
const SOFTWARE_TYPE_ALIASES = {
  rotatingmachine: 'machine',
  machinegroupcontrol: 'machinegroup',
};

class ChildRegistrationUtils {
  constructor(mainClass) {
    this.mainClass = mainClass;
    this.logger = mainClass.logger;
    this.registeredChildren = new Map();
  }

  async registerChild(child, positionVsParent, distance) {
    if (!child || typeof child !== 'object') {
      this.logger?.warn('registerChild skipped: invalid child payload');
      return false;
    }
    if (!child.config?.functionality || !child.config?.general) {
      this.logger?.warn('registerChild skipped: missing child config/functionality/general');
      return false;
    }

    const rawSoftwareType = (child.config.functionality.softwareType || '').toLowerCase();
    const softwareType = SOFTWARE_TYPE_ALIASES[rawSoftwareType] || rawSoftwareType;
    const name = child.config.general.name || child.config.general.id || 'unknown';
    const id = child.config.general.id || name;

    this.logger.debug(`Registering child: ${name} (${id}) as ${softwareType} at ${positionVsParent}`);

    // Enhanced child setup - multiple parents
    if (Array.isArray(child.parent)) {
      child.parent.push(this.mainClass);
    } else {
      child.parent = [this.mainClass];
    }
    child.positionVsParent = positionVsParent;

    // Enhanced measurement container with rich context
    if (child.measurements) {
      child.measurements.setChildId(id);
      child.measurements.setChildName(name);
      child.measurements.setParentRef(this.mainClass);
    }

    // Store child in your expected structure
    this._storeChild(child, softwareType);

    // Track registration for utilities
    this.registeredChildren.set(id, {
      child,
      softwareType,
      position: positionVsParent,
      registeredAt: Date.now()
    });

    // IMPORTANT: Only call parent registration - no automatic handling and if parent has this function then try to register this child
    if (typeof this.mainClass.registerChild === 'function') {
      return this.mainClass.registerChild(child, softwareType);
    }

    this.logger.info(`✅ Child ${name} registered successfully`);
    return true;
  }

  _storeChild(child, softwareType) {
    // Maintain your existing structure
    if (!this.mainClass.child) this.mainClass.child = {};
    const typeKey = softwareType || 'unknown';
    if (!this.mainClass.child[typeKey]) this.mainClass.child[typeKey] = {};
    
    const { category = "sensor" } = child.config.asset || {};
    if (!this.mainClass.child[typeKey][category]) {
      this.mainClass.child[typeKey][category] = [];
    }
    
    this.mainClass.child[typeKey][category].push(child);
  }

  // NEW: Utility methods for parent to use
  getChildrenOfType(softwareType, category = null) {
    if (!this.mainClass.child[softwareType]) return [];
    
    if (category) {
      return this.mainClass.child[softwareType][category] || [];
    }
    
    // Return all children of this software type
    return Object.values(this.mainClass.child[softwareType]).flat();
  }

  getChildById(childId) {
    return this.registeredChildren.get(childId)?.child || null;
  }

  getAllChildren() {
    return Array.from(this.registeredChildren.values()).map(r => r.child);
  }

  // NEW: Debugging utilities
  logChildStructure() {
    this.logger.debug('Current child structure:', JSON.stringify(
      Object.keys(this.mainClass.child).reduce((acc, softwareType) => {
        acc[softwareType] = Object.keys(this.mainClass.child[softwareType]).reduce((catAcc, category) => {
          catAcc[category] = this.mainClass.child[softwareType][category].map(c => ({
            id: c.config.general.id,
            name: c.config.general.name
          }));
          return catAcc;
        }, {});
        return acc;
      }, {}), null, 2
    ));
  }
}

module.exports = ChildRegistrationUtils;
