using System;
using Sources.Signals;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.UI;
using Zenject;

namespace Sources.Gui
{
    public class ResearchButton : MonoBehaviour
    {
        [SerializeField] private TextMeshProUGUI _descriptionText;
        [SerializeField] private TextMeshProUGUI _progressText;
        [SerializeField] private TextMeshProUGUI _unlockText;
        [SerializeField] private ResearchButton _dependsOn;
        [SerializeField] private Image _backGroundImage;
        [SerializeField] private GameObject _descriptionPanel;
        [SerializeField] private TextMeshProUGUI _extendedDescriptionText;

        [Header("Colors")] [SerializeField] private Color _lockedColor;
        [SerializeField] private Color _availableColor;
        [SerializeField] private Color _researchedColor;

        [Inject] private Player _player;
        [Inject] private SignalBus _signalBus;

        public bool IsMaxedOut => _value.Value >= _maxLevel;
        public Action MaxedOut;

        private int _unlockLevel;
        private int _price;
        private int _maxLevel;
        private bool _isMoseOver;
        private ReactiveProperty<int> _value;

        public void Setup(int unlockLevel, int maxLevel, int price, string title, string description, ReactiveProperty<int> value,
            ResearchButton dependsOn = null)
        {
            GetComponentInChildren<Button>().onClick.AddListener(OnClick);

            _value = value;
            _unlockLevel = unlockLevel;
            _descriptionText.text = title;
            _maxLevel = maxLevel;
            _price = price;
            _dependsOn = dependsOn;
            _extendedDescriptionText.text = description;
            
            _descriptionPanel.SetActive(false);
            
            SetProgress(0);

            _signalBus.Subscribe<LevelUpSignal>(UpdateLockState);

            if (_dependsOn != null)
            {
                _dependsOn.MaxedOut += UpdateLockState;
            }

            UpdateLockState();
        }

        private void Update()
        {
            if (_isMoseOver)
            {
                _descriptionPanel.transform.position = Input.mousePosition;
            }
        }

        private void OnClick()
        {
            if (_player.SkillPoints < _price || _value.Value >= _maxLevel || _player.CurrentLevel < _unlockLevel)
                return;

            if (_dependsOn != null && !_dependsOn.IsMaxedOut)
                return;

            _value.Value++;
            _player.SkillPoints -= _price;

            if (_value.Value >= _maxLevel)
                MaxedOut?.Invoke();

            SetProgress(_value.Value);
            UpdateLockState();
        }

        private void UpdateLockState()
        {
            if (_dependsOn != null && !_dependsOn.IsMaxedOut)
            {
                _backGroundImage.color = _lockedColor;
                _unlockText.gameObject.SetActive(true);
                _unlockText.text = $"Locked";
            }
            else if (_player.CurrentLevel < _unlockLevel)
            {
                _backGroundImage.color = _lockedColor;
                _unlockText.gameObject.SetActive(true);
                _unlockText.text = $"Req. level {_unlockLevel}";
            }
            else if (_value.Value <= 0)
            {
                _backGroundImage.color = _availableColor;
                _unlockText.gameObject.SetActive(false);
            }
            else
            {
                _backGroundImage.color = _researchedColor;
                _unlockText.gameObject.SetActive(false);
            }
        }

        private void SetProgress(int current)
        {
            _progressText.text = $"{current} / {_maxLevel}";
        }

        public void OnMouseEnter()
        {
            _descriptionPanel.SetActive(true);
            _isMoseOver = true;
        }
    
        public void OnMouseExit()
        {
            _descriptionPanel.SetActive(false);
            _isMoseOver = false;
        }
    }
}