using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.UI;

public class HeartMeter : SingletonMonoBehaviour<HeartMeter>
{
    [SerializeField] private Slider slider;
    [SerializeField] private TextMeshProUGUI heartLevel;
    [SerializeField] private GameObject maxObject;

    private Coroutine coroutine;
    private List<ShopLevelData> shopLevelList = new List<ShopLevelData>();
    private int currentHeartCount;
    private int maxLevel;
    private readonly ReactiveProperty<float> viewHeartCount = new ReactiveProperty<float>();
    private readonly ReactiveProperty<int> shopLevel = new ReactiveProperty<int>();
    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    private float minHeart;
    private float maxHeart;
    
    private void Awake()
    {
        if (CheckInstance()) return;
    }

    private void Start()
    {
        shopLevel.AddTo(this);
        viewHeartCount.AddTo(this);
        compositeDisposable.AddTo(this);
    }

    public void Initialize(int newShopLevel = 0, int newHeartCount = 0)
    {
        compositeDisposable.Clear();
        shopLevelList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopLevelData>(Const.ShopLevelDataSheet);
        shopLevelList = shopLevelList.Where(data => data.shopLevel != Const.SpecialShopLevel).ToList();
        maxLevel = shopLevelList.Last().shopLevel;

        viewHeartCount.SkipLatestValueOnSubscribe().Subscribe(heartCount =>
        {
            if (shopLevel.Value == maxLevel)
            {
                slider.value = 1;
            }
            else
            {
                slider.value = Mathf.InverseLerp(minHeart, maxHeart, heartCount);
            }
        }).AddTo(compositeDisposable);
        SetHeart(newHeartCount);
        SetShopLevel(newShopLevel);
    }
    
    public void SetHeart(int heartCount)
    {
        currentHeartCount = heartCount;
        viewHeartCount.SetValueAndForceNotify(heartCount);
    }

    public void SetShopLevel(int newShopLevel, bool animate = false)
    {
        var level = Mathf.Min(newShopLevel, maxLevel);
        var isMax = level == maxLevel;
        maxObject.SetActive(isMax);
        heartLevel.gameObject.SetActive(!isMax);
        shopLevel.Value = level;
        heartLevel.text = $"{level}";
        minHeart = shopLevelList.FirstOrDefault(data => data.shopLevel == level)?.heart ?? 0;
        maxHeart = shopLevelList.FirstOrDefault(data => data.shopLevel == level + 1)?.heart ?? minHeart;
        if (animate)
        {
            var tmpCount = currentHeartCount - (int)minHeart;
            SetHeart((int)minHeart);
            AddHeart(tmpCount);
        }
        else
        {
            viewHeartCount.SetValueAndForceNotify(currentHeartCount);
        }
    }
    public void AddHeart(int value)
    {
        this.SafeStopCoroutine(coroutine);
        currentHeartCount += value;
        coroutine = this.CallWaitForSeconds(1f, () =>
        {
            SetHeart(currentHeartCount);
        });
        this.CallLerp(1f, f =>
        {
            viewHeartCount.Value = Mathf.Min(currentHeartCount, viewHeartCount.Value + value * f);
        });
    }
}