import 'package:asciineverdie/src/core/model/equipment_item.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/item_stats.dart';
import 'package:asciineverdie/src/core/util/deterministic_random.dart';

/// 샵 시스템 서비스 (Phase 4)
///
/// 장비 구매, 판매, 자동 장착 등을 담당
class ShopService {
  const ShopService({required this.rng});

  final DeterministicRandom rng;

  // ============================================================================
  // 가격 계산
  // ============================================================================

  /// 장비 구매 가격 계산
  ///
  /// 가격 = 아이템 레벨 * 50 * 희귀도 배율
  int calculateBuyPrice(EquipmentItem item) {
    if (item.isEmpty) return 0;
    return (item.level * 50 * _getRarityPriceMultiplier(item.rarity)).round();
  }

  /// 장비 판매 가격 계산
  ///
  /// 판매 가격 = 구매 가격 * 0.3
  int calculateSellPrice(EquipmentItem item) {
    return (calculateBuyPrice(item) * 0.3).round();
  }

  /// 희귀도별 가격 배율 (Phase 4 문서 기준)
  double _getRarityPriceMultiplier(ItemRarity rarity) {
    return switch (rarity) {
      ItemRarity.common => 1.0,
      ItemRarity.uncommon => 2.0,
      ItemRarity.rare => 5.0,
      ItemRarity.epic => 15.0,
      ItemRarity.legendary => 50.0,
    };
  }

  // ============================================================================
  // 장비 생성
  // ============================================================================

  /// 특정 슬롯의 샵 장비 생성
  ///
  /// [playerLevel] 플레이어 레벨 (장비 레벨 범위 결정)
  /// [slot] 장비 슬롯
  /// [targetRarity] 목표 희귀도 (null이면 랜덤)
  EquipmentItem generateShopItem({
    required int playerLevel,
    required EquipmentSlot slot,
    ItemRarity? targetRarity,
  }) {
    // 아이템 레벨: 플레이어 레벨 기준 ±2
    final minLevel = (playerLevel - 2).clamp(1, 999);
    final maxLevel = playerLevel + 2;
    final itemLevel = minLevel + rng.nextInt(maxLevel - minLevel + 1);

    // 희귀도 결정 (샵 아이템은 Common~Rare만)
    final rarity = targetRarity ?? _rollShopRarity();

    // 아이템 이름 생성
    final name = _generateItemName(slot, rarity, itemLevel);

    // 스탯 생성
    final stats = _generateItemStats(slot, itemLevel, rarity);

    // 무게 계산
    final weight = _calculateWeight(slot, itemLevel);

    return EquipmentItem(
      name: name,
      slot: slot,
      level: itemLevel,
      weight: weight,
      stats: stats,
      rarity: rarity,
    );
  }

  /// 샵 희귀도 롤 (Common 70%, Uncommon 25%, Rare 5%)
  ItemRarity _rollShopRarity() {
    final roll = rng.nextInt(100);
    if (roll < 70) return ItemRarity.common;
    if (roll < 95) return ItemRarity.uncommon;
    return ItemRarity.rare;
  }

  /// 슬롯별 아이템 이름 생성
  String _generateItemName(EquipmentSlot slot, ItemRarity rarity, int level) {
    final prefix = _getRarityPrefix(rarity);
    final baseName = _getSlotBaseName(slot);
    final suffix = level > 10 ? ' +${level ~/ 10}' : '';
    return '$prefix$baseName$suffix'.trim();
  }

  String _getRarityPrefix(ItemRarity rarity) {
    return switch (rarity) {
      ItemRarity.common => '',
      ItemRarity.uncommon => 'Fine ',
      ItemRarity.rare => 'Superior ',
      ItemRarity.epic => 'Epic ',
      ItemRarity.legendary => 'Legendary ',
    };
  }

  String _getSlotBaseName(EquipmentSlot slot) {
    return switch (slot) {
      EquipmentSlot.weapon => 'Keyboard',
      EquipmentSlot.shield => 'Firewall Shield',
      EquipmentSlot.helm => 'Neural Headset',
      EquipmentSlot.hauberk => 'Server Rack Armor',
      EquipmentSlot.brassairts => 'Cable Brassairts',
      EquipmentSlot.vambraces => 'USB Vambraces',
      EquipmentSlot.gauntlets => 'Typing Gauntlets',
      EquipmentSlot.gambeson => 'Padded Gambeson',
      EquipmentSlot.cuisses => 'Circuit Cuisses',
      EquipmentSlot.greaves => 'Copper Greaves',
      EquipmentSlot.sollerets => 'Static Boots',
    };
  }

  /// 슬롯과 레벨에 따른 스탯 생성
  ItemStats _generateItemStats(
    EquipmentSlot slot,
    int level,
    ItemRarity rarity,
  ) {
    final multiplier = rarity.multiplier;
    final baseValue = (level * multiplier).round();

    return switch (slot) {
      EquipmentSlot.weapon => ItemStats(
        atk: baseValue * 2,
        criRate: 0.01 * (level ~/ 5),
        parryRate: 0.005 * level,
      ),
      EquipmentSlot.shield => ItemStats(
        def: baseValue,
        blockRate: 0.02 * (level ~/ 3).clamp(1, 10),
      ),
      EquipmentSlot.helm => ItemStats(
        def: baseValue ~/ 2,
        magDef: baseValue ~/ 2,
        intBonus: level ~/ 10,
      ),
      EquipmentSlot.hauberk => ItemStats(def: baseValue, hpBonus: level * 2),
      EquipmentSlot.brassairts => ItemStats(
        def: baseValue ~/ 2,
        strBonus: level ~/ 15,
      ),
      EquipmentSlot.vambraces => ItemStats(
        def: baseValue ~/ 2,
        dexBonus: level ~/ 15,
      ),
      EquipmentSlot.gauntlets => ItemStats(
        atk: baseValue ~/ 2,
        def: baseValue ~/ 4,
      ),
      EquipmentSlot.gambeson => ItemStats(
        def: baseValue ~/ 2,
        conBonus: level ~/ 15,
      ),
      EquipmentSlot.cuisses => ItemStats(
        def: baseValue ~/ 2,
        evasion: 0.005 * level,
      ),
      EquipmentSlot.greaves => ItemStats(
        def: baseValue ~/ 2,
        evasion: 0.003 * level,
      ),
      EquipmentSlot.sollerets => ItemStats(
        def: baseValue ~/ 3,
        evasion: 0.002 * level,
        dexBonus: level ~/ 20,
      ),
    };
  }

  /// 무게 계산
  int _calculateWeight(EquipmentSlot slot, int level) {
    final baseWeight = switch (slot) {
      EquipmentSlot.weapon => 5,
      EquipmentSlot.shield => 8,
      EquipmentSlot.helm => 4,
      EquipmentSlot.hauberk => 15,
      EquipmentSlot.brassairts => 3,
      EquipmentSlot.vambraces => 3,
      EquipmentSlot.gauntlets => 2,
      EquipmentSlot.gambeson => 6,
      EquipmentSlot.cuisses => 5,
      EquipmentSlot.greaves => 4,
      EquipmentSlot.sollerets => 3,
    };
    return baseWeight + (level ~/ 10);
  }

  // ============================================================================
  // 자동 구매
  // ============================================================================

  /// 빈 슬롯에 대해 자동으로 장비 구매
  ///
  /// Returns: 구매 결과
  AutoBuyResult autoBuyForEmptySlots({
    required int playerLevel,
    required int currentGold,
    required Equipment currentEquipment,
  }) {
    var remainingGold = currentGold;
    final purchasedItems = <EquipmentItem>[];
    var updatedEquipment = currentEquipment;

    // 각 슬롯 순회하며 빈 슬롯에 구매
    for (var i = 0; i < Equipment.slotCount; i++) {
      final currentItem = currentEquipment.getItemByIndex(i);
      if (currentItem.isNotEmpty) continue;

      final slot = EquipmentSlot.values[i];

      // 구매 가능한 아이템 생성 시도
      final shopItem = generateShopItem(
        playerLevel: playerLevel,
        slot: slot,
        targetRarity: ItemRarity.common, // 부활 시 Common만 구매
      );

      final price = calculateBuyPrice(shopItem);
      if (price <= remainingGold) {
        remainingGold -= price;
        purchasedItems.add(shopItem);
        updatedEquipment = updatedEquipment.setItemByIndex(i, shopItem);
      }
    }

    return AutoBuyResult(
      purchasedItems: purchasedItems,
      totalCost: currentGold - remainingGold,
      remainingGold: remainingGold,
      updatedEquipment: updatedEquipment,
    );
  }

  /// 특정 슬롯에 장비 구매
  ///
  /// Returns: 구매 성공 시 결과, 실패 시 null
  PurchaseResult? buyItem({
    required int playerLevel,
    required int currentGold,
    required EquipmentSlot slot,
    ItemRarity? preferredRarity,
  }) {
    final item = generateShopItem(
      playerLevel: playerLevel,
      slot: slot,
      targetRarity: preferredRarity,
    );

    final price = calculateBuyPrice(item);
    if (price > currentGold) return null;

    return PurchaseResult(
      item: item,
      price: price,
      remainingGold: currentGold - price,
    );
  }

  /// 장비 판매
  SellResult sellItem(EquipmentItem item, int currentGold) {
    final price = calculateSellPrice(item);
    return SellResult(item: item, price: price, newGold: currentGold + price);
  }
}

/// 자동 구매 결과
class AutoBuyResult {
  const AutoBuyResult({
    required this.purchasedItems,
    required this.totalCost,
    required this.remainingGold,
    required this.updatedEquipment,
  });

  /// 구매한 아이템 목록
  final List<EquipmentItem> purchasedItems;

  /// 총 비용
  final int totalCost;

  /// 남은 골드
  final int remainingGold;

  /// 업데이트된 장비
  final Equipment updatedEquipment;

  /// 구매한 아이템 개수
  int get purchasedCount => purchasedItems.length;
}

/// 단일 구매 결과
class PurchaseResult {
  const PurchaseResult({
    required this.item,
    required this.price,
    required this.remainingGold,
  });

  final EquipmentItem item;
  final int price;
  final int remainingGold;
}

/// 판매 결과
class SellResult {
  const SellResult({
    required this.item,
    required this.price,
    required this.newGold,
  });

  final EquipmentItem item;
  final int price;
  final int newGold;
}
