using System;
using System.Collections.Generic;
using UnityEngine;

// ============================================================================
// PlayerWeaponInventory
// ----------------------------------------------------------------------------
// 플레이어가 보유한 무기 목록 + 현재 장착 무기 관리.
// 씬 전환 시에도 데이터를 유지하기 위해 DontDestroyOnLoad 싱글톤으로 동작.
// PlayerController가 OnWeaponChanged 이벤트를 구독해서 애니메이션/공격 콤보 교체.
//
// 사용법:
//   - 어디서든 PlayerWeaponInventory.Instance 또는 EnsureInstance()로 접근.
//   - 인스턴스가 없으면 EnsureInstance()가 새 GameObject로 자동 생성 → 첫 씬에
//     수동 배치하지 않아도 됨.
//   - Player 프리팹에는 이 컴포넌트를 더 이상 붙이지 않는다 (중복 시엔 자동 폐기되긴 하지만,
//     프리팹과 같은 GameObject가 영속화되는 부작용을 피하려면 제거 권장).
//
// 슬롯 매핑 (외부 코드의 EquipSlot 인덱스):
//   -1 → 맨손 (CurrentWeapon == null)
//    0 → 첫 번째로 픽업한 무기
//    1 → 두 번째로 픽업한 무기
//   ...
//
// 입력 키 매핑 (PlayerController에서 처리):
//   Key 1 → EquipUnarmed()
//   Key 2 → EquipSlot(0)
//   Key 3 → EquipSlot(1)
// ============================================================================
public class PlayerWeaponInventory : MonoBehaviour
{
    // ─── 싱글톤 ──────────────────────────────────────────────────────────
    public static PlayerWeaponInventory Instance { get; private set; }

    // 어디서든 호출하면 인스턴스를 보장한다. 없으면 새 GameObject로 생성.
    // (PlayerController.Awake에서 호출해 첫 진입을 보장하는 용도)
    public static PlayerWeaponInventory EnsureInstance()
    {
        if (Instance != null) return Instance;
        GameObject go = new GameObject(nameof(PlayerWeaponInventory));
        return go.AddComponent<PlayerWeaponInventory>();
        // AddComponent가 Awake를 동기 호출 → Instance 세팅 + DontDestroyOnLoad 적용 완료 후 반환.
    }

    private readonly List<WeaponData> _weapons = new();
    private int _currentIndex = -1;  // -1 = 맨손

    private void Awake()
    {
        // 중복 생성 방지 — 이미 Instance가 있으면 이 컴포넌트만 폐기.
        // (GameObject 전체를 지우지 않는 이유: Player 프리팹 등에 잘못 붙어 있어도 Player가 사라지면 안 되니까.)
        if (Instance != null && Instance != this)
        {
            Destroy(this);
            return;
        }
        Instance = this;
    }

    private void OnDestroy()
    {
        // 앱 종료 등으로 영속 인스턴스가 파괴될 때 정적 참조 정리.
        if (Instance == this) Instance = null;
    }

    // 무기 교체 시 발화. null이면 맨손.
    public event Action<WeaponData> OnWeaponChanged;

    // 인벤토리 상태(목록 추가·장착 변경)가 바뀔 때마다 발화. UI 갱신용.
    public event Action OnInventoryChanged;

    public WeaponData CurrentWeapon =>
        _currentIndex >= 0 && _currentIndex < _weapons.Count
            ? _weapons[_currentIndex]
            : null;
    public bool IsArmed => CurrentWeapon != null;
    public int Count => _weapons.Count;

    // UI 등 외부에서 읽기 전용으로 목록/장착 인덱스 조회 (UI는 데이터를 소유하지 않는다).
    public IReadOnlyList<WeaponData> Weapons => _weapons;
    public int CurrentIndex => _currentIndex;

    // 무기 추가. 이미 보유 중이면 false 반환 (중복 픽업 방지).
    // 첫 픽업 시 자동 장착할지는 호출자가 OnWeaponChanged를 보고 결정.
    public bool Pickup(WeaponData weapon)
    {
        if (weapon == null) return false;
        if (_weapons.Contains(weapon)) return false;

        _weapons.Add(weapon);

        // 첫 픽업이면 자동으로 장착해주면 사용자 편의 ↑.
        if (_weapons.Count == 1 && _currentIndex == -1)
        {
            _currentIndex = 0;
            OnWeaponChanged?.Invoke(_weapons[0]);
        }

        OnInventoryChanged?.Invoke();
        return true;
    }

    // 맨손 상태로 전환.
    public void EquipUnarmed()
    {
        if (_currentIndex == -1) return;
        _currentIndex = -1;
        OnWeaponChanged?.Invoke(null);
        OnInventoryChanged?.Invoke();
    }

    // 슬롯 번호로 직접 장착. 슬롯이 비어있으면 무시.
    public void EquipSlot(int slotIndex)
    {
        if (slotIndex < 0 || slotIndex >= _weapons.Count) return;
        if (_currentIndex == slotIndex) return;
        _currentIndex = slotIndex;
        OnWeaponChanged?.Invoke(_weapons[slotIndex]);
        OnInventoryChanged?.Invoke();
    }

    public void ClearWeaponInven()
    {
        _weapons.Clear();
        OnInventoryChanged?.Invoke();
    }

    // 디버그용: 슬롯에 해당 무기가 있는지 확인.
    public bool HasWeaponInSlot(int slotIndex)
    {
        return slotIndex >= 0 && slotIndex < _weapons.Count && _weapons[slotIndex] != null;
    }
}
