import 'package:flutter_test/flutter_test.dart';
import 'package:game_test/game/model/entity.dart';
import 'package:game_test/game/model/item.dart';
import 'package:game_test/game/enums.dart';

void main() {
  group('Character Equipment & HP Logic', () {
    late Character player;
    late Item armorHp50;
    late Item armorHp100;
    late Item armorHp20;

    setUp(() {
      player = Character(name: "TestPlayer", maxHp: 100, armor: 0, atk: 10);
      armorHp50 = Item(
        id: "armor_hp_50",
        name: "Armor +50",
        description: "HP +50",
        atkBonus: 0,
        hpBonus: 50,
        slot: EquipmentSlot.armor,
        price: 100,
      );
      armorHp100 = Item(
        id: "armor_hp_100",
        name: "Armor +100",
        description: "HP +100",
        atkBonus: 0,
        hpBonus: 100,
        slot: EquipmentSlot.armor,
        price: 200,
      );
      armorHp20 = Item(
        id: "armor_hp_20",
        name: "Armor +20",
        description: "HP +20",
        atkBonus: 0,
        hpBonus: 20,
        slot: EquipmentSlot.armor,
        price: 50,
      );

      // Add items to inventory initially
      player.addToInventory(armorHp50);
      player.addToInventory(armorHp100);
      player.addToInventory(armorHp20);
    });

    test(
      'Equipping item increases MaxHP and scales Current HP proportionally',
      () {
        expect(player.hp, 100);
        expect(player.totalMaxHp, 100);

        player.equip(armorHp50); // From 100/100 (100% HP) to 150 MaxHP

        expect(player.totalMaxHp, 150, reason: "Max HP should increase by 50");
        expect(
          player.hp,
          150,
          reason: "Current HP should scale to 100% of new MaxHP",
        );
      },
    );

    test(
      'Unequipping item decreases MaxHP and scales Current HP proportionally',
      () {
        player.equip(armorHp50); // HP becomes 150/150
        player.unequip(armorHp50); // MaxHP becomes 100

        expect(player.totalMaxHp, 100);
        expect(
          player.hp,
          100,
          reason: "Current HP should scale to 100% of new MaxHP",
        );
      },
    );

    test(
      'Unequipping item clamps Current HP if it exceeds new MaxHP (Already 100% HP)',
      () {
        player.equip(armorHp50); // HP becomes 150/150
        // No need to heal(50) as it's already 150/150.
        expect(player.hp, 150);

        player.unequip(armorHp50); // MaxHP 100

        expect(player.totalMaxHp, 100);
        expect(
          player.hp,
          100,
          reason: "Current HP should scale to 100% of new MaxHP",
        );
      },
    );

    test(
      'Swapping items handles HP correctly (Upgrade and maintain percentage)',
      () {
        player.equip(armorHp50); // HP 100/100 -> equip -> 150/150 (100%)
        player.hp = 75; // Set HP to 75/150 (50%)
        expect(player.hp, 75);
        expect(player.totalMaxHp, 150);

        player.equip(
          armorHp100,
        ); // Swap armorHp50 (HP+50) with armorHp100 (HP+100). New MaxHP is 200.

        expect(player.totalMaxHp, 200);
        expect(
          player.hp,
          100,
          reason: "HP should scale to 50% of new MaxHP (200 * 0.5 = 100)",
        );
        expect(
          player.inventory.contains(armorHp50),
          true,
          reason: "Old item returned to inventory",
        );
      },
    );

    test(
      'Swapping items handles HP correctly (Downgrade causing clamp due to percentage)',
      () {
        player.equip(armorHp50); // HP 100/100 -> equip -> 150/150 (100%)

        player.equip(
          armorHp20,
        ); // Swap armorHp50 (HP+50) with armorHp20 (HP+20). New MaxHP is 120.

        expect(player.totalMaxHp, 120);
        expect(
          player.hp,
          120,
          reason: "HP should scale to 100% of new MaxHP (120 * 1.0 = 120)",
        );
      },
    );

    test('Weapon can be equipped as subweapon for dual wielding', () {
      final mainSword = Item(
        id: "main_sword",
        name: "Main Sword",
        description: "ATK +5",
        atkBonus: 5,
        hpBonus: 0,
        slot: EquipmentSlot.weapon,
        price: 100,
      );
      final offhandDagger = Item(
        id: "offhand_dagger",
        name: "Offhand Dagger",
        description: "ATK +3",
        atkBonus: 3,
        hpBonus: 0,
        slot: EquipmentSlot.weapon,
        price: 80,
      );

      player.addToInventory(mainSword);
      player.addToInventory(offhandDagger);

      expect(player.equipToSlot(mainSword, EquipmentSlot.weapon), true);
      expect(player.equipToSlot(offhandDagger, EquipmentSlot.shield), true);

      expect(player.equipment[EquipmentSlot.weapon], mainSword);
      expect(player.equipment[EquipmentSlot.shield], offhandDagger);
      expect(player.totalAtk, 18);
    });
  });
}
