import 'package:flutter/foundation.dart';

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';

/// 플레이어 사망 처리 서비스
///
/// ProgressService에서 분리된 사망 관련 로직 담당:
/// - 장비 손실 계산
/// - 사망 정보 기록
/// - 보스전 레벨링 모드 진입
class DeathHandler {
  const DeathHandler();

  /// 플레이어 사망 처리 (Phase 4)
  ///
  /// 모든 장비 상실 및 사망 정보 기록.
  /// 보스전 사망 시: 장비 보호 + 5분 레벨링 모드 진입.
  GameState processPlayerDeath(
    GameState state, {
    required String killerName,
    required DeathCause cause,
  }) {
    // 사망 직전 전투 이벤트 저장 (최대 10개)
    final lastCombatEvents =
        state.progress.currentCombat?.recentEvents ?? const [];

    // 보스전 사망 여부 확인 (최종 보스 fighting 상태)
    final isBossDeath =
        state.progress.finalBossState == FinalBossState.fighting;

    // 보스전 사망이 아닐 경우에만 장비 손실
    var newEquipment = state.equipment;
    var lostCount = 0;
    String? lostItemName;
    EquipmentSlot? lostItemSlot;
    ItemRarity? lostItemRarity;
    EquipmentItem? lostEquipmentItem; // 광고 부활 시 복구용

    if (!isBossDeath) {
      final lossResult = _calculateEquipmentLoss(state);
      newEquipment = lossResult.equipment;
      lostCount = lossResult.lostCount;
      lostItemName = lossResult.lostItemName;
      lostItemSlot = lossResult.lostItemSlot;
      lostItemRarity = lossResult.lostItemRarity;
      lostEquipmentItem = lossResult.lostItem;
    }

    // 사망 정보 생성 (전투 로그 포함)
    final deathInfo = DeathInfo(
      cause: cause,
      killerName: killerName,
      lostEquipmentCount: lostCount,
      lostItemName: lostItemName,
      lostItemSlot: lostItemSlot,
      lostItemRarity: lostItemRarity,
      lostItem: lostEquipmentItem,
      goldAtDeath: state.inventory.gold,
      levelAtDeath: state.traits.level,
      timestamp: state.skillSystem.elapsedMs,
      lastCombatEvents: lastCombatEvents,
    );

    // 보스전 사망 시 5분 레벨링 모드 진입
    final bossLevelingEndTime = isBossDeath
        ? DateTime.now().millisecondsSinceEpoch +
              (5 * 60 * 1000) // 5분
        : null;

    // 전투 상태 초기화 및 사망 횟수 증가
    final progress = state.progress.copyWith(
      clearCurrentCombat: true,
      deathCount: state.progress.deathCount + 1,
      bossLevelingEndTime: bossLevelingEndTime,
    );

    return state.copyWith(
      equipment: newEquipment,
      progress: progress,
      deathInfo: deathInfo,
    );
  }

  /// 장비 손실 계산
  ({
    Equipment equipment,
    int lostCount,
    String? lostItemName,
    EquipmentSlot? lostItemSlot,
    ItemRarity? lostItemRarity,
    EquipmentItem? lostItem,
  })
  _calculateEquipmentLoss(GameState state) {
    var newEquipment = state.equipment;

    // 레벨 기반 장비 손실 확률 계산
    // Lv 1: 20%, Lv 5: ~56%, Lv 10+: 100%
    // 공식: 20 + (level - 1) * 80 / 9
    final level = state.traits.level;
    final lossChancePercent = level >= 10
        ? 100
        : (20 + ((level - 1) * 80 ~/ 9)).clamp(0, 100);
    final roll = state.rng.nextInt(100); // 0~99
    final shouldLoseEquipment = roll < lossChancePercent;

    debugPrint(
      '[Death] Lv$level lossChance=$lossChancePercent% roll=$roll '
      'shouldLose=$shouldLoseEquipment',
    );

    if (!shouldLoseEquipment) {
      return (
        equipment: newEquipment,
        lostCount: 0,
        lostItemName: null,
        lostItemSlot: null,
        lostItemRarity: null,
        lostItem: null,
      );
    }

    // 무기(슬롯 0)를 제외한 장착된 장비 중 1개를 제물로 삭제
    final equippedNonWeaponSlots = <int>[];
    for (var i = 1; i < Equipment.slotCount; i++) {
      final item = state.equipment.getItemByIndex(i);
      if (item.isNotEmpty) {
        equippedNonWeaponSlots.add(i);
      }
    }

    if (equippedNonWeaponSlots.isEmpty) {
      return (
        equipment: newEquipment,
        lostCount: 0,
        lostItemName: null,
        lostItemSlot: null,
        lostItemRarity: null,
        lostItem: null,
      );
    }

    // 랜덤하게 1개 슬롯 선택
    final sacrificeIndex =
        equippedNonWeaponSlots[state.rng.nextInt(
          equippedNonWeaponSlots.length,
        )];

    // 제물로 바칠 아이템 정보 저장
    final lostItem = state.equipment.getItemByIndex(sacrificeIndex);
    final lostItemSlot = EquipmentSlot.values[sacrificeIndex];

    // 해당 슬롯을 빈 장비로 교체
    newEquipment = newEquipment.setItemByIndex(
      sacrificeIndex,
      EquipmentItem.empty(lostItemSlot),
    );

    debugPrint('[Death] Lost item: ${lostItem.name} (slot: $lostItemSlot)');

    return (
      equipment: newEquipment,
      lostCount: 1,
      lostItemName: lostItem.name,
      lostItemSlot: lostItemSlot,
      lostItemRarity: lostItem.rarity,
      lostItem: lostItem,
    );
  }
}
