using UnityEngine;
using DG.Tweening;
using ALArcade.ArabicTMP;

namespace com.al_arcade.cs
{
    using shared;

    [RequireComponent(typeof(BoxCollider))]
    public class CsWordButton : MonoBehaviour
    {
        public string WordText { get; private set; }
        public bool IsWrong { get; private set; }
        public int Index { get; private set; }

        private ArabicTextMeshPro _text;
        private GameObject _background;
        private Material _bgMaterial;
        private BoxCollider _collider;
        private bool _isHighlighted;
        private Sequence _idleAnim;
        private float _cardWidth;
        private float _cardHeight = 0.8f;


        public void Setup(string text, bool isWrong, int index,
            float cardWidth = -1f, float scaleFactor = 1f)
        {
            WordText = text;
            IsWrong = isWrong;
            Index = index;


            if (cardWidth <= 0)
                _cardWidth = text.Length * 0.32f + 0.6f;
            else
                _cardWidth = cardWidth;

            _cardWidth = Mathf.Max(_cardWidth, 0.8f);

            BuildVisuals();
            StartIdleAnimation();
        }

        private void BuildVisuals()
        {
            var shader = Shader.Find("Universal Render Pipeline/Lit")
                ?? Shader.Find("Standard") ?? Shader.Find("Unlit/Color");


            _background = GameObject.CreatePrimitive(PrimitiveType.Cube);
            _background.name = "WordBg";
            _background.transform.SetParent(transform);
            _background.transform.localPosition = Vector3.zero;
            _background.transform.localScale = new Vector3(_cardWidth, _cardHeight, 0.08f);
            Destroy(_background.GetComponent<Collider>());

            _bgMaterial = new Material(shader) { color = SSColorPalette.NeutralWord };
            _background.GetComponent<Renderer>().material = _bgMaterial;


            var textObj = new GameObject("WordText");
            textObj.transform.SetParent(transform);
            textObj.transform.localPosition = new Vector3(0, 0, -0.05f);

            textObj.transform.localRotation = Quaternion.identity;

            _text = textObj.AddComponent<ArabicTextMeshPro>();
            _text.arabicText = WordText;
            _text.fontSize = 4.5f;
            _text.alignment = TMPro.TextAlignmentOptions.Center;
            _text.color = SSColorPalette.TextDark;
            _text.fontStyle = TMPro.FontStyles.Bold;
            _text.enableAutoSizing = true;
            _text.fontSizeMin = 2f;
            _text.fontSizeMax = 5f;
            _text.rectTransform.sizeDelta = new Vector2(_cardWidth - 0.2f, _cardHeight - 0.1f);
            _text.enableWordWrapping = false;
            _text.overflowMode = TMPro.TextOverflowModes.Ellipsis;
            SSFontManager.Apply(_text);


            _collider = GetComponent<BoxCollider>();
            _collider.size = new Vector3(_cardWidth, _cardHeight, 0.2f);


            var shadow = GameObject.CreatePrimitive(PrimitiveType.Cube);
            shadow.name = "Shadow";
            shadow.transform.SetParent(transform);
            shadow.transform.localPosition = new Vector3(0.04f, -0.04f, 0.02f);
            shadow.transform.localScale = new Vector3(_cardWidth, _cardHeight, 0.06f);
            Destroy(shadow.GetComponent<Collider>());
            shadow.GetComponent<Renderer>().material =
                new Material(shader) { color = new Color(0, 0, 0, 0.12f) };
        }

        private void StartIdleAnimation()
        {
            KillTweens();
            float baseY = transform.position.y;
            float offset = Index * 0.15f;
            _idleAnim = DOTween.Sequence();
            _idleAnim.Append(
                transform.DOMoveY(baseY + 0.05f, 1.5f + offset * 0.1f)
                    .SetEase(Ease.InOutSine));
            _idleAnim.Append(
                transform.DOMoveY(baseY, 1.5f + offset * 0.1f)
                    .SetEase(Ease.InOutSine));
            _idleAnim.SetLoops(-1, LoopType.Restart);
            _idleAnim.SetDelay(offset);
        }

        private void KillTweens()
        {
            _idleAnim?.Kill();
            _idleAnim = null;
            DOTween.Kill(transform);
            if (_bgMaterial != null) DOTween.Kill(_bgMaterial);
        }


        private void LateUpdate()
        {
            if (Camera.main == null) return;
            Vector3 awayFromCam = transform.position - Camera.main.transform.position;
            awayFromCam.y = 0;
            if (awayFromCam.sqrMagnitude > 0.001f)
                transform.rotation = Quaternion.LookRotation(awayFromCam);
        }


        private void OnMouseEnter()
        {
            if (_isHighlighted) return;
            DOTween.Kill(_bgMaterial, "hover");
            _bgMaterial.DOColor(SSColorPalette.WithAlpha(SSColorPalette.Primary, 0.3f), 0.2f)
                .SetId("hover");
            DOTween.Kill(transform, "hoverScale");
            transform.DOScale(Vector3.one * 1.1f, 0.2f).SetEase(Ease.OutQuad)
                .SetId("hoverScale");
        }

        private void OnMouseExit()
        {
            if (_isHighlighted) return;
            DOTween.Kill(_bgMaterial, "hover");
            _bgMaterial.DOColor(SSColorPalette.NeutralWord, 0.2f).SetId("hover");
            DOTween.Kill(transform, "hoverScale");
            transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutQuad).SetId("hoverScale");
        }

        private void OnMouseDown()
        {
            if (CsGameManager.Instance != null)
                CsGameManager.Instance.OnWordClicked(this);
        }


        public void Highlight(bool isWrongWord)
        {
            _isHighlighted = true;
            KillTweens();

            Color targetColor = isWrongWord
                ? SSColorPalette.WrongWord
                : SSColorPalette.CorrectWord;

            _bgMaterial.DOColor(targetColor, 0.3f);
            if (_text != null) _text.color = Color.white;
            transform.DOPunchScale(Vector3.one * 0.2f, 0.4f, 8, 0.3f);


            DOTween.Sequence()
                .Append(_bgMaterial.DOColor(Color.Lerp(targetColor, Color.white, 0.3f), 0.5f))
                .Append(_bgMaterial.DOColor(targetColor, 0.5f))
                .SetLoops(-1, LoopType.Restart);
        }

        public void ShakeWrong()
        {
            DOTween.Kill(transform, "shakeWrong");
            transform.DOShakePosition(0.3f, 0.15f, 15, 90, false, true).SetId("shakeWrong");
            transform.DOShakeRotation(0.3f, 5f, 15);

            Color orig = _bgMaterial.color;
            DOTween.Kill(_bgMaterial, "shakeColor");
            _bgMaterial.DOColor(SSColorPalette.WithAlpha(SSColorPalette.Danger, 0.3f), 0.1f)
                .SetId("shakeColor")
                .OnComplete(() => _bgMaterial.DOColor(orig, 0.3f));
        }

        public void ReplaceText(string newText)
        {
            DOTween.Kill(transform, "replace");
            var seq = DOTween.Sequence().SetId("replace");
            seq.Append(transform.DOScale(Vector3.one * 0.5f, 0.2f).SetEase(Ease.InBack));
            seq.AppendCallback(() =>
            {
                if (_text != null) _text.arabicText = newText;
                WordText = newText;
                DOTween.Kill(_bgMaterial);
                _bgMaterial.color = SSColorPalette.CorrectWord;
                if (_text != null) _text.color = Color.white;
            });
            seq.Append(transform.DOScale(Vector3.one * 1.2f, 0.3f).SetEase(Ease.OutBack));
            seq.Append(transform.DOScale(Vector3.one, 0.15f));
        }

        private void OnDestroy() => KillTweens();
    }
}
