import 'package:asciineverdie/src/core/model/class_traits.dart';
import 'package:asciineverdie/src/core/model/combat_stats.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/race_traits.dart';

/// 스탯 계산기 (stat calculator)
///
/// 기본 스탯에 종족/클래스 보정을 적용하여 최종 스탯 계산
class StatCalculator {
  const StatCalculator();

  /// 기본 스탯에 종족/클래스 보정 적용
  ///
  /// [baseStats] 기본 캐릭터 스탯
  /// [race] 종족 특성
  /// [klass] 클래스 특성
  Stats applyModifiers({
    required Stats baseStats,
    required RaceTraits race,
    required ClassTraits klass,
  }) {
    // 종족 보정 적용
    var str = baseStats.str + race.getModifier(StatType.str);
    var con = baseStats.con + race.getModifier(StatType.con);
    var dex = baseStats.dex + race.getModifier(StatType.dex);
    var intel =
        baseStats.intelligence + race.getModifier(StatType.intelligence);
    var wis = baseStats.wis + race.getModifier(StatType.wis);
    var cha = baseStats.cha + race.getModifier(StatType.cha);

    // 클래스 보정 적용
    str += klass.getModifier(StatType.str);
    con += klass.getModifier(StatType.con);
    dex += klass.getModifier(StatType.dex);
    intel += klass.getModifier(StatType.intelligence);
    wis += klass.getModifier(StatType.wis);
    cha += klass.getModifier(StatType.cha);

    // HP/MP에 종족 패시브 적용
    var hpMax = baseStats.hpMax;
    var mpMax = baseStats.mpMax;

    // 종족 HP 보너스 (Heap Troll: +20%)
    final raceHpBonus = race.getPassiveValue(PassiveType.hpBonus);
    if (raceHpBonus > 0) {
      hpMax = (hpMax * (1 + raceHpBonus)).round();
    }

    // 종족 MP 보너스 (Pointer Fairy: +20%)
    final raceMpBonus = race.getPassiveValue(PassiveType.mpBonus);
    if (raceMpBonus > 0) {
      mpMax = (mpMax * (1 + raceMpBonus)).round();
    }

    // 클래스 HP 보너스 (Garbage Collector: +30%)
    final classHpBonus = klass.getPassiveValue(ClassPassiveType.hpBonus);
    if (classHpBonus > 0) {
      hpMax = (hpMax * (1 + classHpBonus)).round();
    }

    return baseStats.copyWith(
      str: str,
      con: con,
      dex: dex,
      intelligence: intel,
      wis: wis,
      cha: cha,
      hpMax: hpMax,
      mpMax: mpMax,
    );
  }

  /// CombatStats에 종족/클래스 패시브 효과 적용
  ///
  /// [combatStats] 기본 전투 스탯
  /// [race] 종족 특성
  /// [klass] 클래스 특성
  CombatStats applyPassives({
    required CombatStats combatStats,
    required RaceTraits race,
    required ClassTraits klass,
  }) {
    var atk = combatStats.atk;
    var def = combatStats.def;
    var magAtk = combatStats.magAtk;
    var criRate = combatStats.criRate;
    var evasion = combatStats.evasion;

    // 종족 패시브 적용

    // 마법 데미지 보너스 (Null Elf: +15%)
    final raceMagicBonus = race.getPassiveValue(PassiveType.magicDamageBonus);
    if (raceMagicBonus > 0) {
      magAtk = (magAtk * (1 + raceMagicBonus)).round();
    }

    // 방어력 보너스 (Buffer Dwarf: +10%)
    final raceDefenseBonus = race.getPassiveValue(PassiveType.defenseBonus);
    if (raceDefenseBonus > 0) {
      def = (def * (1 + raceDefenseBonus)).round();
    }

    // 크리티컬 보너스 (Stack Goblin: +5%)
    final raceCritBonus = race.getPassiveValue(PassiveType.criticalBonus);
    if (raceCritBonus > 0) {
      criRate = (criRate + raceCritBonus).clamp(0.0, 0.8);
    }

    // 클래스 패시브 적용

    // 물리 공격력 보너스 (Bug Hunter: +20%)
    final classPhysicalBonus = klass.getPassiveValue(
      ClassPassiveType.physicalDamageBonus,
    );
    if (classPhysicalBonus > 0) {
      atk = (atk * (1 + classPhysicalBonus)).round();
    }

    // 방어력 보너스 (Debugger Paladin: +15%)
    final classDefenseBonus = klass.getPassiveValue(
      ClassPassiveType.defenseBonus,
    );
    if (classDefenseBonus > 0) {
      def = (def * (1 + classDefenseBonus)).round();
    }

    // 마법 데미지 보너스 (Compiler Mage: +25%)
    final classMagicBonus = klass.getPassiveValue(
      ClassPassiveType.magicDamageBonus,
    );
    if (classMagicBonus > 0) {
      magAtk = (magAtk * (1 + classMagicBonus)).round();
    }

    // 회피율 보너스 (Refactor Monk: +15%)
    final classEvasionBonus = klass.getPassiveValue(
      ClassPassiveType.evasionBonus,
    );
    if (classEvasionBonus > 0) {
      evasion = (evasion + classEvasionBonus).clamp(0.0, 0.6);
    }

    // 크리티컬 보너스 (Pointer Assassin: +20%)
    final classCritBonus = klass.getPassiveValue(
      ClassPassiveType.criticalBonus,
    );
    if (classCritBonus > 0) {
      criRate = (criRate + classCritBonus).clamp(0.0, 0.8);
    }

    return combatStats.copyWith(
      atk: atk,
      def: def,
      magAtk: magAtk,
      criRate: criRate,
      evasion: evasion,
    );
  }

  /// 경험치 배율 계산
  ///
  /// 종족 경험치 배율 반환 (Byte Human: 1.10)
  double calculateExpMultiplier(RaceTraits race) {
    return race.expMultiplier;
  }

  /// 전투 후 HP 회복량 계산 (Garbage Collector 패시브)
  ///
  /// [klass] 클래스 특성
  /// [maxHp] 최대 HP
  /// Returns: 회복할 HP 양
  int calculatePostCombatHeal({
    required ClassTraits klass,
    required int maxHp,
  }) {
    final healRate = klass.getPassiveValue(ClassPassiveType.postCombatHeal);
    if (healRate <= 0) return 0;
    return (maxHp * healRate).round();
  }

  /// 첫 공격 배율 계산 (Pointer Assassin 패시브)
  ///
  /// [klass] 클래스 특성
  /// Returns: 첫 공격 배율 (기본 1.0)
  double calculateFirstStrikeMultiplier(ClassTraits klass) {
    final bonus = klass.getPassiveValue(ClassPassiveType.firstStrikeBonus);
    return bonus > 0 ? bonus : 1.0;
  }

  /// 연속 공격 가능 여부 (Refactor Monk 패시브)
  bool hasMultiAttack(ClassTraits klass) {
    return klass.hasPassive(ClassPassiveType.multiAttack);
  }

  /// 회복력 배율 계산 (Debugger Paladin 패시브)
  double calculateHealingMultiplier(ClassTraits klass) {
    final bonus = klass.getPassiveValue(ClassPassiveType.healingBonus);
    return 1.0 + bonus;
  }
}
