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

namespace com.al_arcade.cs
{
    using LightSide;
    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 GameObject _background;
        private Material _bgMaterial;
        private Canvas _canvas;
        private UniText _uniText; // Assuming the class name is UniText in UniText namespace
        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("ScienceStreet/SciFiTextBackground")
                ?? 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 };
            _bgMaterial.SetFloat("_State", 0f);
            _background.GetComponent<Renderer>().material = _bgMaterial;
            _background.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;

            var canvasObj = new GameObject("WordCanvas");
            canvasObj.transform.SetParent(transform);
            canvasObj.transform.localPosition = new Vector3(0, 0, -0.05f);
            canvasObj.transform.localRotation = Quaternion.identity;

            _canvas = canvasObj.AddComponent<Canvas>();
            _canvas.renderMode = RenderMode.WorldSpace;
            canvasObj.AddComponent<GraphicRaycaster>();

            var rt = canvasObj.GetComponent<RectTransform>();
            float canvasScale = 0.02f;
            rt.localScale = new Vector3(canvasScale, canvasScale, canvasScale);
            rt.sizeDelta = new Vector2(_cardWidth / canvasScale, _cardHeight / canvasScale);

            var textObj = new GameObject("UniText");
            textObj.transform.SetParent(canvasObj.transform);
            textObj.transform.localPosition = Vector3.zero;
            textObj.transform.localRotation = Quaternion.identity;
            textObj.transform.localScale = Vector3.one;

            var textRt = textObj.AddComponent<RectTransform>();
            textRt.anchorMin = Vector2.zero;
            textRt.anchorMax = Vector2.one;
            textRt.sizeDelta = Vector2.zero;

            _uniText = textObj.AddComponent<UniText>();
            _uniText.Text = WordText;
            _uniText.HorizontalAlignment = HorizontalAlignment.Center;
            _uniText.VerticalAlignment = VerticalAlignment.Middle;
            _uniText.FontSize = 20;
            // _uniText.AutoSize = true;


            _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");
            _bgMaterial.SetFloat("_State", 1f); // highlighted on 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");
            _bgMaterial.SetFloat("_State", 0f); // back to neutral
            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;

            // Set shader state: 1 = highlighted (waiting for drop)
            _bgMaterial.SetFloat("_State", 1f);

            _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);

            // Flash shader to wrong state, then back to neutral
            _bgMaterial.SetFloat("_State", 3f);

            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);
                    _bgMaterial.SetFloat("_State", 0f); // back to neutral
                });
        }

        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 (_uniText != null) _uniText.Text = newText;
                WordText = newText;
                DOTween.Kill(_bgMaterial);
                _bgMaterial.color = SSColorPalette.CorrectWord;
                _bgMaterial.SetFloat("_State", 2f); // correct state
            });
            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();
    }
}
