import 'package:wolf_3d_dart/src/data_types/sprite_frame_range.dart';
import 'package:wolf_3d_dart/src/entities/entities/enemies/enemy_type.dart';

enum EnemyAnimation { idle, walking, attacking, pain, dying, dead }

/// A mapping container that defines the sprite index ranges for an enemy's life cycle.
///
/// Wolfenstein 3D enemies use specific ranges within the global sprite list
/// to handle state transitions like walking, attacking, or dying.
class EnemyAnimationMap {
  final SpriteFrameRange idle;
  final SpriteFrameRange walking;
  final SpriteFrameRange attacking;
  final SpriteFrameRange pain;
  final SpriteFrameRange dying;
  final SpriteFrameRange dead;

  const EnemyAnimationMap({
    required this.idle,
    required this.walking,
    required this.attacking,
    required this.pain,
    required this.dying,
    required this.dead,
  });

  /// Identifies which [EnemyAnimation] state a specific [spriteIndex] belongs to.
  ///
  /// Returns `null` if the index is outside this enemy's defined animation ranges.
  EnemyAnimation? getAnimation(int spriteIndex) {
    if (idle.contains(spriteIndex)) return EnemyAnimation.idle;
    if (walking.contains(spriteIndex)) return EnemyAnimation.walking;
    if (attacking.contains(spriteIndex)) return EnemyAnimation.attacking;
    if (pain.contains(spriteIndex)) return EnemyAnimation.pain;
    if (dying.contains(spriteIndex)) return EnemyAnimation.dying;
    if (dead.contains(spriteIndex)) return EnemyAnimation.dead;
    return null;
  }

  /// Returns the [SpriteFrameRange] associated with a specific [animation] state.
  SpriteFrameRange getRange(EnemyAnimation animation) {
    return switch (animation) {
      EnemyAnimation.idle => idle,
      EnemyAnimation.walking => walking,
      EnemyAnimation.attacking => attacking,
      EnemyAnimation.pain => pain,
      EnemyAnimation.dying => dying,
      EnemyAnimation.dead => dead,
    };
  }

  /// Checks if any animation range in this map overlaps with any range in [other].
  bool overlapsWith(EnemyAnimationMap other) {
    final myRanges = [idle, walking, attacking, pain, dying, dead];
    final otherRanges = [
      other.idle,
      other.walking,
      other.attacking,
      other.pain,
      other.dying,
      other.dead,
    ];

    for (final myRange in myRanges) {
      for (final otherRange in otherRanges) {
        if (myRange.overlaps(otherRange)) {
          return true;
        }
      }
    }
    return false;
  }

  /// Checks if any animation ranges within this specific enemy overlap with each other.
  ///
  /// Useful for validating that an enemy isn't trying to use the same sprite
  /// for two different states (e.g., walking and attacking).
  bool hasInternalOverlaps() {
    final ranges = [idle, walking, attacking, pain, dying, dead];

    // Compare every unique pair of ranges
    for (int i = 0; i < ranges.length; i++) {
      for (int j = i + 1; j < ranges.length; j++) {
        if (ranges[i].overlaps(ranges[j])) {
          return true;
        }
      }
    }

    return false;
  }

  void validateEnemyAnimations() {
    bool hasErrors = false;

    for (final enemy in EnemyType.values) {
      // 1. Check for internal overlaps (e.g., Guard walking overlaps Guard attacking)
      if (enemy.animations.hasInternalOverlaps()) {
        print(
          '❌ ERROR: ${enemy.name} has overlapping internal animation states!',
        );
        hasErrors = true;
      }

      // 2. Check for external overlaps (e.g., Guard sprites overlap SS sprites)
      for (final otherEnemy in EnemyType.values) {
        if (enemy != otherEnemy && enemy.sharesFramesWith(otherEnemy)) {
          print(
            '❌ ERROR: ${enemy.name} shares sprite frames with ${otherEnemy.name}!',
          );
          hasErrors = true;
        }
      }
    }

    if (!hasErrors) {
      print(
        '✅ All enemy animations validated successfully! No overlaps found.',
      );
    }
  }
}
