import 'package:freezed_annotation/freezed_annotation.dart';

import 'package:asciineverdie/src/core/model/equipment_slot.dart';
import 'package:asciineverdie/src/core/model/item_stats.dart';

part 'equipment_item.freezed.dart';
part 'equipment_item.g.dart';

/// 장비 아이템
///
/// 개별 장비의 이름, 슬롯, 레벨, 스탯 등을 포함하는 클래스.
/// 불변(immutable) 객체로 설계됨.
@freezed
class EquipmentItem with _$EquipmentItem {
  const EquipmentItem._();

  const factory EquipmentItem({
    /// 아이템 이름 (예: "Flaming Sword of Doom")
    required String name,

    /// 장착 슬롯
    // ignore: invalid_annotation_target
    @JsonKey(fromJson: _slotFromJson, toJson: _slotToJson)
    required EquipmentSlot slot,

    /// 아이템 레벨
    required int level,

    /// 무게 (STR 기반 휴대 제한용)
    required int weight,

    /// 아이템 스탯 보정치
    required ItemStats stats,

    /// 희귀도
    // ignore: invalid_annotation_target
    @JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
    required ItemRarity rarity,
  }) = _EquipmentItem;

  factory EquipmentItem.fromJson(Map<String, dynamic> json) =>
      _$EquipmentItemFromJson(json);

  /// 빈 아이템 생성 (특정 슬롯)
  factory EquipmentItem.empty(EquipmentSlot slot) {
    return EquipmentItem(
      name: '',
      slot: slot,
      level: 0,
      weight: 0,
      stats: const ItemStats(),
      rarity: ItemRarity.common,
    );
  }

  /// 기본 무기 (Keyboard)
  factory EquipmentItem.defaultWeapon() {
    return const EquipmentItem(
      name: 'Keyboard',
      slot: EquipmentSlot.weapon,
      level: 1,
      weight: 5,
      stats: ItemStats(atk: 1, attackSpeed: 1000),
      rarity: ItemRarity.common,
    );
  }

  /// 가중치 (자동 장착 비교용)
  ///
  /// 가중치 = 기본값 + (레벨 * 10) + (희귀도 보너스) + (스탯 합계)
  int get itemWeight {
    const baseValue = 10;
    return baseValue + (level * 10) + rarity.weightBonus + stats.totalStatValue;
  }

  /// 빈 아이템 여부
  bool get isEmpty => name.isEmpty;

  /// 유효한 아이템 여부
  bool get isNotEmpty => name.isNotEmpty;

  @override
  String toString() => name.isEmpty ? '(empty)' : name;
}

// JSON 변환 헬퍼 (세이브 파일 호환성 유지)
EquipmentSlot _slotFromJson(String? value) {
  return EquipmentSlot.values.firstWhere(
    (s) => s.name == value,
    orElse: () => EquipmentSlot.weapon,
  );
}

String _slotToJson(EquipmentSlot slot) => slot.name;

ItemRarity _rarityFromJson(String? value) {
  return ItemRarity.values.firstWhere(
    (r) => r.name == value,
    orElse: () => ItemRarity.common,
  );
}

String _rarityToJson(ItemRarity rarity) => rarity.name;
