/**
 * SkillTreeFactory.js
 * Generates class-specific skill trees by merging a Master Topology with Class Configuration.
 */
export class SkillTreeFactory {
  /**
   * @param {Object} templateRegistry - Map of Template IDs to JSON structures.
   * @param {Object} skillRegistry - Map of Skill IDs to Skill Definitions.
   */
  constructor(templateRegistry, skillRegistry) {
    this.templates = templateRegistry;
    this.skills = skillRegistry;
  }

  /**
   * Creates a fully hydrated Skill Tree for a specific class.
   * @param {Object} classConfig - The Class definition containing 'skillTreeData'.
   * @param {string} templateId - The ID of the topology to use (default: 'TEMPLATE_STANDARD_30').
   */
  createTree(classConfig, templateId = "TEMPLATE_STANDARD_30") {
    const template = this.templates[templateId];
    if (!template) throw new Error(`Template not found: ${templateId}`);

    const config = classConfig.skillTreeData;
    if (!config)
      throw new Error(`Class ${classConfig.id} missing skillTreeData`);

    const newTree = {
      id: `TREE_${classConfig.id}`,
      nodes: {},
    };

    // Iterate and Inject
    for (const [nodeId, templateNode] of Object.entries(template.nodes)) {
      // Clone the node structure to avoid mutating the template
      let realNode = JSON.parse(JSON.stringify(templateNode));

      // Hydrate based on Slot Type
      this.hydrateNode(realNode, config, templateNode.tier);

      newTree.nodes[nodeId] = realNode;
    }

    return newTree;
  }

  hydrateNode(node, config, tier) {
    // Scaling Logic for Stats
    const statValue = this.getTierStatValue(tier);

    switch (node.type) {
      case "SLOT_STAT_PRIMARY":
        node.type = "STAT_BOOST";
        node.data = {
          stat: config.primary_stat,
          value: statValue * 2, // Primary gets double value
        };
        break;

      case "SLOT_STAT_SECONDARY":
        node.type = "STAT_BOOST";
        node.data = {
          stat: config.secondary_stat,
          value: statValue,
        };
        break;

      case "SLOT_SKILL_ACTIVE_1":
        node.type = "ACTIVE_SKILL";
        // Map tier/slot to specific index in the config array
        // Example: Slot 1 is the 0th skill
        if (config.active_skills && config.active_skills[0]) {
          node.data = this.getSkillData(config.active_skills[0]);
        } else {
          node.data = { id: "UNKNOWN", name: "Unknown Skill" };
        }
        break;

      case "SLOT_SKILL_ACTIVE_2":
        node.type = "ACTIVE_SKILL";
        if (config.active_skills && config.active_skills[1]) {
          node.data = this.getSkillData(config.active_skills[1]);
        } else {
          node.data = { id: "UNKNOWN", name: "Unknown Skill" };
        }
        break;

      case "SLOT_SKILL_ACTIVE_3":
        node.type = "ACTIVE_SKILL";
        if (config.active_skills && config.active_skills[2]) {
          node.data = this.getSkillData(config.active_skills[2]);
        } else {
          node.data = { id: "UNKNOWN", name: "Unknown Skill" };
        }
        break;

      case "SLOT_SKILL_ACTIVE_4":
        node.type = "ACTIVE_SKILL";
        if (config.active_skills && config.active_skills[3]) {
          node.data = this.getSkillData(config.active_skills[3]);
        } else {
          node.data = { id: "UNKNOWN", name: "Unknown Skill" };
        }
        break;

      case "SLOT_SKILL_PASSIVE_1":
        node.type = "PASSIVE_ABILITY";
        if (config.passive_skills && config.passive_skills[0]) {
          node.data = {
            effect_id: config.passive_skills[0],
            name: config.passive_skills[0],
          };
        } else {
          node.data = { effect_id: "UNKNOWN", name: "Unknown Passive" };
        }
        break;

      case "SLOT_SKILL_PASSIVE_2":
        node.type = "PASSIVE_ABILITY";
        if (config.passive_skills && config.passive_skills[1]) {
          node.data = {
            effect_id: config.passive_skills[1],
            name: config.passive_skills[1],
          };
        } else {
          node.data = { effect_id: "UNKNOWN", name: "Unknown Passive" };
        }
        break;

      case "SLOT_SKILL_PASSIVE_3":
        node.type = "PASSIVE_ABILITY";
        if (config.passive_skills && config.passive_skills[2]) {
          node.data = {
            effect_id: config.passive_skills[2],
            name: config.passive_skills[2],
          };
        } else {
          node.data = { effect_id: "UNKNOWN", name: "Unknown Passive" };
        }
        break;

      case "SLOT_SKILL_PASSIVE_4":
        node.type = "PASSIVE_ABILITY";
        if (config.passive_skills && config.passive_skills[3]) {
          node.data = {
            effect_id: config.passive_skills[3],
            name: config.passive_skills[3],
          };
        } else {
          node.data = { effect_id: "UNKNOWN", name: "Unknown Passive" };
        }
        break;

      // ... Add cases for other slots (ULTIMATE, etc)

      default:
        // If it's already a concrete type (e.g. fixed layout), leave it alone
        break;
    }
  }

  getSkillData(skillId) {
    const skill = this.skills[skillId];
    if (!skill) return { id: skillId, name: "Unknown Skill" }; // Fallback
    return skill;
  }

  getTierStatValue(tier) {
    // Scaling logic: Tier 1 = 1, Tier 5 = 5
    return tier;
  }
}
