using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using TMPro;
using UnityEngine.InputSystem;

namespace MaskShop
{
    public class QTESystem : MonoBehaviour
    {
        [Header("UI References")]
        [SerializeField] private GameObject qtePanel;
        [SerializeField] private Slider timingBar;
        [SerializeField] private Image perfectZone;
        [SerializeField] private Image goodZone;
        [SerializeField] private Image barFill;
        [SerializeField] private TextMeshProUGUI instructionText;
        [SerializeField] private TextMeshProUGUI resultText;

        [Header("Reaction Time UI")]
        [SerializeField] private GameObject reactionPrompt;
        [SerializeField] private TextMeshProUGUI reactionText;

        [Header("Configuration")]
        [SerializeField] private QTEConfiguration qteConfig;

        [Header("Debug")]
        [SerializeField] private bool showDebugInfo = true;

        // State
        private bool isQTEActive = false;
        private QTEType currentQTEType;
        private float currentDifficulty;
        private QTEResult currentResult;
        private bool qteCompleted = false;

        // Timing Bar state
        private float barValue = 0f;
        private float barDirection = 1f;
        private float barSpeed;
        private float perfectZoneCenter = 0.5f;
        private float perfectZoneSize;
        private float goodZoneSize;

        // Reaction Time state
        private float reactionStartTime;
        private float reactionWindow;
        private bool waitingForReaction = false;

        public static event System.Action<QTEResult> OnQTECompleted;

        private void Awake() => HideQTEUI();

        public void StartQTE(QTEType type, float difficulty = 1f)
        {
            if (isQTEActive) return;

            currentQTEType = type;
            currentDifficulty = difficulty;
            isQTEActive = true;
            qteCompleted = false;

            if (type == QTEType.TimingBar) StartTimingBarQTE();
            else if (type == QTEType.ReactionTime) StartReactionTimeQTE();
        }

        #region Input System Receiver
        /// <summary>
        /// Vincula este método en el PlayerInput (Events -> Action Name)
        /// </summary>
        public void OnQTEAction(InputAction.CallbackContext context)
        {
            // Solo procesar si el QTE está activo, no ha terminado y es el momento del "press"
            if (!isQTEActive || qteCompleted || !context.performed) return;

            if (currentQTEType == QTEType.TimingBar)
            {
                EvaluateTimingBarResult();
            }
            else if (currentQTEType == QTEType.ReactionTime && waitingForReaction)
            {
                HandleReactionInput();
            }
        }
        #endregion

        #region Timing Bar Logic
        private void StartTimingBarQTE()
        {
            qtePanel.SetActive(true);
            timingBar.gameObject.SetActive(true);
            reactionPrompt.SetActive(false);

            perfectZoneSize = qteConfig.GetAdjustedPerfectZone(currentDifficulty);
            goodZoneSize = qteConfig.GetAdjustedGoodZone(currentDifficulty);
            barSpeed = qteConfig.GetAdjustedSpeed(currentDifficulty);
            perfectZoneCenter = Random.Range(0.2f, 0.8f);

            SetupTimingBarZones();
            barValue = 0f;
            barDirection = 1f;
            instructionText.text = "Press at the right moment!";
            resultText.text = "";

            StartCoroutine(UpdateTimingBar());
        }

        private IEnumerator UpdateTimingBar()
        {
            while (isQTEActive && !qteCompleted)
            {
                barValue += barDirection * barSpeed * Time.deltaTime;
                if (barValue >= 1f) { barValue = 1f; barDirection = -1f; }
                else if (barValue <= 0f) { barValue = 0f; barDirection = 1f; }

                timingBar.value = barValue;
                yield return null;
            }
        }

        private void EvaluateTimingBarResult()
        {
            qteCompleted = true; // Detiene el movimiento visual
            float distanceFromCenter = Mathf.Abs(barValue - perfectZoneCenter);

            if (distanceFromCenter <= perfectZoneSize / 2f)
            {
                currentResult = QTEResult.Perfect;
                barFill.color = qteConfig.PerfectColor;
                resultText.text = "PERFECT!";
            }
            else if (distanceFromCenter <= goodZoneSize / 2f)
            {
                currentResult = QTEResult.Good;
                barFill.color = qteConfig.GoodColor;
                resultText.text = "Good!";
            }
            else
            {
                currentResult = QTEResult.Bad;
                barFill.color = qteConfig.BadColor;
                resultText.text = "Fail...";
            }
            StartCoroutine(EndQTE());
        }
        #endregion

        #region Reaction Time Logic
        private void StartReactionTimeQTE()
        {
            qtePanel.SetActive(true);
            timingBar.gameObject.SetActive(false);
            reactionPrompt.SetActive(false);
            reactionWindow = qteConfig.ReactionTimeWindow / currentDifficulty;
            instructionText.text = "Prepare!";
            resultText.text = "";

            StartCoroutine(ReactionTimeSequence());
        }

        private IEnumerator ReactionTimeSequence()
        {
            yield return new WaitForSeconds(Random.Range(1.5f, 3.5f));

            if (!isQTEActive) yield break;

            reactionPrompt.SetActive(true);
            reactionText.text = "¡NOW!";
            reactionStartTime = Time.time;
            waitingForReaction = true;

            float timer = 0f;
            while (waitingForReaction && timer < reactionWindow)
            {
                timer += Time.deltaTime;
                yield return null;
            }

            if (waitingForReaction) // Si llegó aquí por timeout
            {
                waitingForReaction = false;
                currentResult = QTEResult.Bad;
                resultText.text = "Very slow!";
                barFill.color = qteConfig.BadColor;
                qteCompleted = true;
                StartCoroutine(EndQTE());
            }
        }

        private void HandleReactionInput()
        {
            waitingForReaction = false; // Detiene la espera en la corrutina
            float reactionTime = Time.time - reactionStartTime;
            EvaluateReactionTimeResult(reactionTime);
        }

        private void EvaluateReactionTimeResult(float reactionTime)
        {
            if (reactionTime <= qteConfig.PerfectReactionTime)
            {
                currentResult = QTEResult.Perfect;
                resultText.text = $"PERFECT! ({reactionTime:F2}s)";
                barFill.color = qteConfig.PerfectColor;
            }
            else
            {
                currentResult = QTEResult.Good;
                resultText.text = $"Good! ({reactionTime:F2}s)";
                barFill.color = qteConfig.GoodColor;
            }
            qteCompleted = true;
            StartCoroutine(EndQTE());
        }
        #endregion

        private void SetupTimingBarZones()
        {
            if (perfectZone)
            {
                perfectZone.rectTransform.anchorMin = new Vector2(perfectZoneCenter - perfectZoneSize / 2, 0);
                perfectZone.rectTransform.anchorMax = new Vector2(perfectZoneCenter + perfectZoneSize / 2, 1);
            }
            if (goodZone)
            {
                goodZone.rectTransform.anchorMin = new Vector2(perfectZoneCenter - goodZoneSize / 2, 0);
                goodZone.rectTransform.anchorMax = new Vector2(perfectZoneCenter + goodZoneSize / 2, 1);
            }
        }

        private IEnumerator EndQTE()
        {
            yield return new WaitForSeconds(1.5f);
            OnQTECompleted?.Invoke(currentResult);
            isQTEActive = false;
            HideQTEUI();
        }

        private void HideQTEUI()
        {
            qtePanel.SetActive(false);
            reactionPrompt.SetActive(false);
        }


        // Public getters

        public bool IsQTEActive() => isQTEActive;

        public QTEResult GetCurrentResult() => currentResult;

    }


}