import 'dart:math';
import '../model/item.dart';
import '../data/item_table.dart'; // For ItemTemplate
import '../data/item_prefix_table.dart';
import '../data/name_generator.dart';
import '../enums.dart';
import '../config/item_config.dart'; // Import ItemConfig

class LootGenerator {
  static final Random _random = Random();

  /// Generates an Item instance from a template, applying prefixes/suffixes based on rarity.
  static Item generate(ItemTemplate template) {
    // Consumables have fixed stats and no prefixes.
    if (template.slot == EquipmentSlot.consumable) {
      return Item(
        id: template.id,
        name: template.name,
        description: template.description,
        atkBonus: template.atkBonus,
        hpBonus: template.hpBonus,
        armorBonus: template.armorBonus,
        dodge: template.dodge,
        slot: template.slot,
        effects: template.effects,
        price: template.price,
        image: template.image,
        luck: template.luck,
        rarity: template.rarity,
        tier: template.tier,
        weaponType: template.weaponType,
      );
    }

    String finalName = template.name;
    int finalAtk = template.atkBonus;
    int finalHp = template.hpBonus;
    int finalArmor = template.armorBonus;
    int finalLuck = template.luck;
    int finalDodge = template.dodge;

    // 0. Normal Rarity: Prefix logic for base stat variations
    if (template.rarity == ItemRarity.normal) {
      // Weighted Random Selection
      final prefixes = ItemPrefixTable.normalPrefixes;
      int totalWeight = prefixes.fold(0, (sum, p) => sum + p.weight);
      int roll = _random.nextInt(totalWeight);

      ItemModifier? selectedModifier;
      int currentSum = 0;
      for (var mod in prefixes) {
        currentSum += mod.weight;
        if (roll < currentSum) {
          selectedModifier = mod;
          break;
        }
      }

      if (selectedModifier != null) {
        if (selectedModifier.prefix.isNotEmpty) {
          finalName = "${selectedModifier.prefix} ${template.name}";
        }

        double mult = selectedModifier.multiplier;
        if (mult != 1.0) {
          finalAtk = (finalAtk * mult).floor();
          finalHp = (finalHp * mult).floor();
          finalArmor = (finalArmor * mult).floor();
          // Dodge typically stays integer, but if we want to scale it:
          // finalDodge = (finalDodge * mult).floor();
        }
      }
    }
    // 1. Magic Rarity: 50% chance to get a Magic Prefix (1 stat change)
    else if (template.rarity == ItemRarity.magic) {
      if (_random.nextDouble() < ItemConfig.magicPrefixChance) {
        // Use constant
        // Filter valid prefixes for this slot
        final validPrefixes = ItemPrefixTable.magicPrefixes.where((p) {
          return p.allowedSlots == null ||
              p.allowedSlots!.contains(template.slot);
        }).toList();

        if (validPrefixes.isNotEmpty) {
          final modifier = validPrefixes[_random.nextInt(validPrefixes.length)];
          finalName = "${modifier.prefix} ${template.name}";

          modifier.statChanges.forEach((stat, value) {
            switch (stat) {
              case StatType.atk:
                finalAtk += value;
                break;
              case StatType.maxHp:
                finalHp += value;
                break;
              case StatType.defense:
                finalArmor += value;
                break;
              case StatType.luck:
                finalLuck += value;
                break;
              case StatType.dodge: // Handle dodge
                finalDodge += value;
                break;
            }
          });
        }
      }
    }
    // 2. Rare Rarity: Always get a Rare Prefix (2 stat changes or stronger)
    else if (template.rarity == ItemRarity.rare) {
      bool nameChanged = false;

      // Always generate a completely new cool name for Rare items
      finalName = NameGenerator.generateName(template.slot);
      nameChanged = true;

      // Filter valid prefixes for this slot
      final validPrefixes = ItemPrefixTable.rarePrefixes.where((p) {
        return p.allowedSlots == null ||
            p.allowedSlots!.contains(template.slot);
      }).toList();

      if (validPrefixes.isNotEmpty) {
        final modifier = validPrefixes[_random.nextInt(validPrefixes.length)];

        // If name wasn't already changed by NameGenerator, apply prefix to name
        if (!nameChanged) {
          finalName = "${modifier.prefix} ${template.name}";
        }
        // Even if name changed, we STILL apply the stats from the prefix modifier!

        modifier.statChanges.forEach((stat, value) {
          switch (stat) {
            case StatType.atk:
              finalAtk += value;
              break;
            case StatType.maxHp:
              finalHp += value;
              break;
            case StatType.defense:
              finalArmor += value;
              break;
            case StatType.luck:
              finalLuck += value;
              break;
            case StatType.dodge: // Handle dodge
              finalDodge += value;
              break;
          }
        });
      }
    }
    // Legendary/Unique items usually keep their original names/stats.

    return Item(
      id: template.id,
      name: finalName,
      description: template.description,
      atkBonus: finalAtk,
      hpBonus: finalHp,
      armorBonus: finalArmor,
      dodge: finalDodge, // Pass dodge
      slot: template.slot,
      effects: template.effects,
      price: template.price,
      image: template.image,
      luck: finalLuck,
      rarity: template.rarity,
      tier: template.tier,
      weaponType: template.weaponType,
    );
  }
}
