import 'dart:convert';
import 'dart:math';
import 'package:flutter/services.dart';
import '../model/entity.dart';
import '../config/game_config.dart';

import 'item_table.dart';

class EnemyTemplate {
  static const String fallbackImage = 'assets/images/enemies/Orc.png';

  final String name;
  final int baseHp;
  final int baseAtk;
  final int baseDefense;
  final int baseDodge; // New: Base dodge chance
  final String? image;
  final List<String> equipmentIds;
  final int tier;

  const EnemyTemplate({
    required this.name,
    required this.baseHp,
    required this.baseAtk,
    required this.baseDefense,
    this.baseDodge = 1, // Default value
    this.image,
    this.equipmentIds = const [],
    this.tier = 1,
  });

  factory EnemyTemplate.fromJson(
    Map<String, dynamic> json, {
    Set<String>? availableAssets,
  }) {
    final imagePath = json['image'] as String?;

    return EnemyTemplate(
      name: json['name'],
      baseHp: json['baseHp'] ?? 10,
      baseAtk: json['baseAtk'] ?? 1,
      baseDefense: json['baseDefense'] ?? 0,
      baseDodge: json['baseDodge'] ?? 1, // Parse from JSON or default to 1
      image: _resolveImagePath(imagePath, availableAssets),
      equipmentIds: (json['equipment'] as List<dynamic>?)?.cast<String>() ?? [],
      tier: json['tier'] ?? 1,
    );
  }

  static String? _resolveImagePath(String? imagePath, Set<String>? assets) {
    if (imagePath == null || imagePath.isEmpty) return null;
    if (assets == null || assets.contains(imagePath)) return imagePath;
    return fallbackImage;
  }

  Character createCharacter({int stage = 1}) {
    // Stage-based scaling for enemy stats is removed to simplify balancing.
    // Enemy stats are now fixed as defined in the EnemyTemplate.

    final character = Character(
      name: name,
      maxHp: baseHp,
      atk: baseAtk,
      baseDefense: baseDefense,
      baseDodge: baseDodge, // Pass baseDodge to Character constructor
      armor: 0,
      image: image,
    );

    // Equip items
    for (final itemId in equipmentIds) {
      final itemTemplate = ItemTable.get(itemId);
      if (itemTemplate != null) {
        // Items no longer scale by stage, pass no stage parameter
        final item = itemTemplate.createItem();
        character.addToInventory(item);
        character.equip(item);
      }
    }

    return character;
  }
}

class EnemyTable {
  static List<EnemyTemplate> normalEnemies = [];
  static List<EnemyTemplate> eliteEnemies = [];
  static final Random _random = Random();

  static Future<void> load() async {
    final String jsonString = await rootBundle.loadString(
      'assets/data/enemies.json',
    );
    final Map<String, dynamic> data = jsonDecode(jsonString);
    final availableAssets = await _loadAvailableAssets();

    normalEnemies = (data['normal'] as List)
        .map((e) => EnemyTemplate.fromJson(e, availableAssets: availableAssets))
        .toList();
    eliteEnemies = (data['elite'] as List)
        .map((e) => EnemyTemplate.fromJson(e, availableAssets: availableAssets))
        .toList();
  }

  static Future<Set<String>?> _loadAvailableAssets() async {
    try {
      final manifest = await AssetManifest.loadFromAssetBundle(rootBundle);
      return manifest.listAssets().toSet();
    } catch (_) {
      return null;
    }
  }

  /// Returns a random enemy suitable for the current stage.
  static EnemyTemplate getRandomEnemy({
    required int stage,
    bool isElite = false,
  }) {
    int targetTier = 1;
    if (stage > GameConfig.tier2StageMax) {
      targetTier = 3;
    } else if (stage > GameConfig.tier1StageMax) {
      targetTier = 2;
    }

    List<EnemyTemplate> pool = isElite ? eliteEnemies : normalEnemies;

    // Filter by tier
    var tierPool = pool.where((e) => e.tier == targetTier).toList();

    // Fallback: If no enemies found for this tier, use lower tiers (or any)
    if (tierPool.isEmpty) {
      tierPool = pool.where((e) => e.tier <= targetTier).toList();
    }
    if (tierPool.isEmpty) {
      tierPool = pool; // Absolute fallback
    }

    if (tierPool.isEmpty) {
      // Should not happen if JSON is correct
      return const EnemyTemplate(
        name: "Fallback Enemy",
        baseHp: 10,
        baseAtk: 1,
        baseDefense: 0,
      );
    }

    return tierPool[_random.nextInt(tierPool.length)];
  }
}
