import 'dart:math';
import '../model/entity.dart';
import '../model/status_effect.dart';
import '../enums.dart';
import '../config/game_config.dart';
import '../config/battle_config.dart'; // Import BattleConfig

class CombatResult {
  final bool success;
  final int value;
  final double efficiency;
  final bool isCritical; // Future extension

  CombatResult({
    required this.success,
    required this.value,
    required this.efficiency,
    this.isCritical = false,
  });
}

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

  /// Helper to get efficiency multiplier based on risk and action type.
  static double getEfficiency(ActionType actionType, RiskLevel risk) {
    switch (risk) {
      case RiskLevel.safe:
        return actionType == ActionType.attack
            ? BattleConfig.attackSafeEfficiency
            : BattleConfig.defendSafeEfficiency;
      case RiskLevel.normal:
        return actionType == ActionType.attack
            ? BattleConfig.attackNormalEfficiency
            : BattleConfig.defendNormalEfficiency;
      case RiskLevel.risky:
        return actionType == ActionType.attack
            ? BattleConfig.attackRiskyEfficiency
            : BattleConfig.defendRiskyEfficiency;
    }
  }

  /// Calculates success and efficiency based on Risk Level and Luck.
  static CombatResult calculateActionOutcome({
    required ActionType actionType, // New: Action type (attack or defend)
    required RiskLevel risk,
    required int luck,
    required int baseValue,
    Random? random, // Injectable Random
  }) {
    final effectiveRandom = random ?? _random;
    double efficiency = getEfficiency(actionType, risk);
    
    double baseChance = 0.0;
    switch (risk) {
      case RiskLevel.safe:
        baseChance = BattleConfig.safeBaseChance;
        break;
      case RiskLevel.normal:
        baseChance = BattleConfig.normalBaseChance;
        break;
      case RiskLevel.risky:
        baseChance = BattleConfig.riskyBaseChance;
        break;
    }

    // Apply Luck (1 Luck = +1%)
    double chance = baseChance + (luck / 100.0);
    if (chance > 1.0) chance = 1.0;

    bool success = effectiveRandom.nextDouble() < chance;
    int finalValue = (baseValue * efficiency).toInt();
    if (finalValue < 1 && baseValue > 0) finalValue = 1;

    return CombatResult(
      success: success,
      value: finalValue,
      efficiency: efficiency,
    );
  }

  /// Calculates actual damage to HP after applying armor and vulnerability.
  static int calculateDamageToHp({
    required int incomingDamage,
    required int currentArmor,
    required bool isVulnerable,
  }) {
    int damage = incomingDamage;
    
    // 1. Vulnerability check
    if (isVulnerable) {
      damage = (damage * GameConfig.vulnerableDamageMultiplier).toInt();
    }

    // 2. Armor absorption
    int damageToHp = 0;
    if (currentArmor > 0) {
      if (currentArmor >= damage) {
        // Fully absorbed
        damageToHp = 0;
      } else {
        damageToHp = damage - currentArmor;
      }
    } else {
      damageToHp = damage;
    }

    return damageToHp;
  }
  
  /// Calculates armor remaining after damage absorption.
  static int calculateRemainingArmor({
    required int incomingDamage,
    required int currentArmor,
    required bool isVulnerable,
  }) {
    int damage = incomingDamage;
    if (isVulnerable) {
      damage = (damage * GameConfig.vulnerableDamageMultiplier).toInt();
    }

    if (currentArmor > 0) {
      if (currentArmor >= damage) {
        return currentArmor - damage;
      } else {
        return 0;
      }
    }
    return 0;
  }

  /// Checks if status effects (Bleed, Stun) allow action and returns bleed damage.
  static Map<String, dynamic> processStartTurnEffects(Character character) {
    int totalBleedDamage = 0;
    bool isStunned = false;

    // 1. Bleed Damage
    var bleedEffects = character.statusEffects
        .where((e) => e.type == StatusEffectType.bleed)
        .toList();
    
    if (bleedEffects.isNotEmpty) {
      totalBleedDamage = bleedEffects.fold(0, (sum, e) => sum + e.value);
    }

    // 2. Stun Check
    if (character.hasStatus(StatusEffectType.stun)) {
      isStunned = true;
    }

    return {
      'bleedDamage': totalBleedDamage,
      'isStunned': isStunned,
    };
  }

  /// Tries to apply status effects from attacker's equipment.
  /// Returns a list of applied effects.
  static List<StatusEffect> getAppliedEffects(Character attacker, {Random? random}) {
    final effectiveRandom = random ?? _random;
    List<StatusEffect> appliedEffects = [];
    
    for (var item in attacker.equipment.values) {
      for (var effect in item.effects) {
        if (effectiveRandom.nextInt(100) < effect.probability) {
          appliedEffects.add(
            StatusEffect(
              type: effect.type,
              duration: effect.duration,
              value: effect.value,
            ),
          );
        }
      }
    }
    return appliedEffects;
  }

  /// Calculates if a dodge occurs.
  /// [targetDodge] is the total dodge chance percentage (e.g. 5 = 5%).
  static bool calculateDodge(int targetDodge, {Random? random}) {
    final effectiveRandom = random ?? _random;
    if (targetDodge <= 0) return false;
    return effectiveRandom.nextInt(100) < targetDodge;
  }
}
