import 'package:asciineverdie/data/skill_data.dart';
import 'package:asciineverdie/src/core/engine/item_service.dart';
import 'package:asciineverdie/src/core/model/equipment_slot.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/pq_config.dart';
import 'package:asciineverdie/src/core/util/pq_logic.dart' as pq_logic;

/// Game state mutations that mirror the original PQ win/reward logic.
class GameMutations {
  const GameMutations(this.config);

  final PqConfig config;

  /// 장비 획득 (원본 Main.pas:791-830 WinEquip)
  ///
  /// [slotIndex]: 0-10 (원본 Equips.Items.Count = 11)
  /// ItemService를 사용하여 스탯과 공속을 가진 장비 생성
  GameState winEquipByIndex(GameState state, int level, int slotIndex) {
    final rng = state.rng;
    final name = pq_logic.winEquip(config, rng, level, slotIndex);
    final slot = EquipmentSlot.values[slotIndex];

    // ItemService로 스탯이 있는 장비 생성
    final itemService = ItemService(rng: rng);
    final newItem = itemService.generateEquipment(
      name: name,
      slot: slot,
      level: level,
    );

    final updatedEquip = state.equipment
        .setItemByIndex(slotIndex, newItem)
        .copyWith(bestIndex: slotIndex);
    return state.copyWith(rng: rng, equipment: updatedEquip);
  }

  /// EquipmentSlot enum을 사용하는 편의 함수
  GameState winEquip(GameState state, int level, EquipmentSlot slot) {
    return winEquipByIndex(state, level, slot.index);
  }

  GameState winStat(GameState state) {
    final updatedStats = pq_logic.winStat(state.stats, state.rng);
    return state.copyWith(rng: state.rng, stats: updatedStats);
  }

  /// 스펠 획득 (원본 WinSpell)
  ///
  /// 스펠북에 추가하고, 전투용 스킬 슬롯에도 자동으로 장착 시도.
  /// 슬롯이 가득 찬 경우 기존 스킬보다 강할 때만 교체됨.
  GameState winSpell(GameState state, int wisdom, int level) {
    final result = pq_logic.winSpell(config, state.rng, wisdom, level);
    final parts = result.split('|');
    final name = parts[0];
    final rank = parts.length > 1 ? parts[1] : 'I';

    // 스펠북 업데이트
    final skills = [...state.skillBook.skills];
    final index = skills.indexWhere((s) => s.name == name);
    if (index >= 0) {
      skills[index] = skills[index].copyWith(rank: rank);
    } else {
      skills.add(SkillEntry(name: name, rank: rank));
    }

    // 전투 스킬 슬롯에 추가 시도
    var skillSystem = state.skillSystem;
    final combatSkill = SkillData.getSkillBySpellName(name);
    if (combatSkill != null) {
      final addResult = skillSystem.equippedSkills.tryAddSkill(combatSkill);
      if (addResult.success) {
        skillSystem = skillSystem.copyWith(equippedSkills: addResult.slots);
      }
    }

    return state.copyWith(
      rng: state.rng,
      skillBook: state.skillBook.copyWith(skills: skills),
      skillSystem: skillSystem,
    );
  }

  GameState winItem(GameState state) {
    final rng = state.rng;
    final result = pq_logic.winItem(config, rng, state.inventory.items.length);
    final items = [...state.inventory.items];

    if (result.isEmpty) {
      // Duplicate an existing item if possible.
      if (items.isNotEmpty) {
        final pickIndex = rng.nextInt(items.length);
        final picked = items[pickIndex];
        items[pickIndex] = picked.copyWith(count: picked.count + 1);
      }
    } else {
      final existing = items.indexWhere((e) => e.name == result);
      if (existing >= 0) {
        items[existing] = items[existing].copyWith(
          count: items[existing].count + 1,
        );
      } else {
        items.add(InventoryEntry(name: result, count: 1));
      }
    }

    return state.copyWith(
      rng: rng,
      inventory: state.inventory.copyWith(items: items),
    );
  }
}
