using UnityEngine;
using DG.Tweening;

namespace com.al_arcade.cs
{
    using shared;

    public class CsBotController : MonoBehaviour
    {
        private GameObject _body, _head, _leftEye, _rightEye, _mouth;
        private Material _bodyMat, _headMat, _mouthMat;
        private Sequence _idleAnim;
        private Sequence _headTiltAnim;
        private Coroutine _blinkCoroutine;
        private float _baseY;

        public void Build()
        {
            _baseY = transform.position.y;
            var shader = Shader.Find("Universal Render Pipeline/Lit")
                ?? Shader.Find("Standard") ?? Shader.Find("Unlit/Color");


            _body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
            _body.name = "Body";
            _body.transform.SetParent(transform);
            _body.transform.localPosition = new Vector3(0, 1f, 0);
            _body.transform.localScale = new Vector3(1.2f, 1.2f, 1.2f);
            Destroy(_body.GetComponent<Collider>());
            _bodyMat = new Material(shader) { color = SSColorPalette.Primary };
            _body.GetComponent<Renderer>().material = _bodyMat;


            _head = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            _head.name = "Head";
            _head.transform.SetParent(transform);
            _head.transform.localPosition = new Vector3(0, 2.8f, 0);
            _head.transform.localScale = Vector3.one * 1.1f;
            Destroy(_head.GetComponent<Collider>());
            _headMat = new Material(shader) { color = SSColorPalette.Accent };
            _head.GetComponent<Renderer>().material = _headMat;


            var eyeMat = new Material(shader) { color = Color.white };
            var pupilMat = new Material(shader) { color = SSColorPalette.TextDark };

            for (int side = -1; side <= 1; side += 2)
            {
                var eye = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                eye.name = side < 0 ? "LeftEye" : "RightEye";
                eye.transform.SetParent(_head.transform);
                eye.transform.localPosition = new Vector3(side * 0.22f, 0.1f, -0.42f);
                eye.transform.localScale = Vector3.one * 0.22f;
                Destroy(eye.GetComponent<Collider>());
                eye.GetComponent<Renderer>().material = new Material(eyeMat);

                if (side < 0) _leftEye = eye; else _rightEye = eye;

                var pupil = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                pupil.name = "Pupil";
                pupil.transform.SetParent(eye.transform);
                pupil.transform.localPosition = new Vector3(0, 0, -0.35f);
                pupil.transform.localScale = Vector3.one * 0.55f;
                Destroy(pupil.GetComponent<Collider>());
                pupil.GetComponent<Renderer>().material = new Material(pupilMat);
            }


            _mouth = GameObject.CreatePrimitive(PrimitiveType.Cube);
            _mouth.name = "Mouth";
            _mouth.transform.SetParent(_head.transform);
            _mouth.transform.localPosition = new Vector3(0, -0.2f, -0.45f);
            _mouth.transform.localScale = new Vector3(0.25f, 0.06f, 0.05f);
            Destroy(_mouth.GetComponent<Collider>());
            _mouthMat = new Material(shader) { color = SSColorPalette.Danger };
            _mouth.GetComponent<Renderer>().material = _mouthMat;


            for (int side = -1; side <= 1; side += 2)
            {
                var arm = GameObject.CreatePrimitive(PrimitiveType.Capsule);
                arm.name = side < 0 ? "LeftArm" : "RightArm";
                arm.transform.SetParent(_body.transform);
                arm.transform.localPosition = new Vector3(side * 0.55f, 0.1f, 0);
                arm.transform.localScale = new Vector3(0.2f, 0.45f, 0.2f);
                arm.transform.localRotation = Quaternion.Euler(0, 0, side * -15f);
                Destroy(arm.GetComponent<Collider>());
                arm.GetComponent<Renderer>().material =
                    new Material(shader) { color = SSColorPalette.PrimaryDark };
            }


            for (int side = -1; side <= 1; side += 2)
            {
                var foot = GameObject.CreatePrimitive(PrimitiveType.Cube);
                foot.name = "Foot";
                foot.transform.SetParent(transform);
                foot.transform.localPosition = new Vector3(side * 0.3f, 0.1f, -0.1f);
                foot.transform.localScale = new Vector3(0.3f, 0.2f, 0.5f);
                Destroy(foot.GetComponent<Collider>());
                foot.GetComponent<Renderer>().material =
                    new Material(shader) { color = SSColorPalette.PrimaryDark };
            }

            StartIdleAnimation();
        }

        private void StartIdleAnimation()
        {
            KillAllTweens();
            float y = _baseY;

            _idleAnim = DOTween.Sequence();
            _idleAnim.Append(transform.DOMoveY(y + 0.1f, 1.5f).SetEase(Ease.InOutSine));
            _idleAnim.Append(transform.DOMoveY(y, 1.5f).SetEase(Ease.InOutSine));
            _idleAnim.SetLoops(-1, LoopType.Restart);

            if (_head != null)
            {
                _headTiltAnim = DOTween.Sequence();
                _headTiltAnim.Append(_head.transform.DOLocalRotate(new Vector3(0, 5, 3), 2f)
                    .SetEase(Ease.InOutSine));
                _headTiltAnim.Append(_head.transform.DOLocalRotate(new Vector3(0, -5, -3), 2f)
                    .SetEase(Ease.InOutSine));
                _headTiltAnim.SetLoops(-1, LoopType.Restart);
            }

            _blinkCoroutine = StartCoroutine(BlinkLoop());
        }

        private void KillAllTweens()
        {
            _idleAnim?.Kill(); _idleAnim = null;
            _headTiltAnim?.Kill(); _headTiltAnim = null;
            if (_blinkCoroutine != null) { StopCoroutine(_blinkCoroutine); _blinkCoroutine = null; }
            DOTween.Kill(transform);
            if (_head != null) DOTween.Kill(_head.transform);
            if (_mouth != null) DOTween.Kill(_mouth.transform);
            if (_headMat != null) DOTween.Kill(_headMat);
            if (_mouthMat != null) DOTween.Kill(_mouthMat);
        }

        private System.Collections.IEnumerator BlinkLoop()
        {
            while (true)
            {
                yield return new WaitForSeconds(Random.Range(2f, 5f));
                if (_leftEye != null)
                {
                    DOTween.Kill(_leftEye.transform, "blink");
                    _leftEye.transform.DOScaleY(0.01f, 0.08f).SetId("blink")
                        .OnComplete(() => _leftEye.transform.DOScaleY(0.22f, 0.08f));
                }
                if (_rightEye != null)
                {
                    DOTween.Kill(_rightEye.transform, "blink");
                    _rightEye.transform.DOScaleY(0.01f, 0.08f).SetId("blink")
                        .OnComplete(() => _rightEye.transform.DOScaleY(0.22f, 0.08f));
                }
            }
        }


        public void PlayHappy()
        {
            if (_mouth != null)
            {
                DOTween.Kill(_mouth.transform, "mouthAnim");
                _mouth.transform.DOScaleX(0.4f, 0.2f).SetEase(Ease.OutBack).SetId("mouthAnim");
                _mouth.transform.DOScaleY(0.12f, 0.2f);
                DOTween.Kill(_mouthMat);
                _mouthMat.DOColor(SSColorPalette.Success, 0.2f);
            }

            DOTween.Kill(transform, "botPunch");
            transform.DOPunchScale(Vector3.one * 0.15f, 0.5f, 6, 0.3f).SetId("botPunch");

            if (_headMat != null)
            {
                DOTween.Kill(_headMat, "headFlash");
                _headMat.DOColor(SSColorPalette.Success, 0.2f).SetId("headFlash")
                    .OnComplete(() => _headMat.DOColor(SSColorPalette.Accent, 0.4f));
            }


            DOTween.Sequence().SetDelay(1f).OnComplete(() =>
            {
                if (_mouth == null) return;
                DOTween.Kill(_mouth.transform, "mouthAnim");
                _mouth.transform.DOScaleX(0.25f, 0.2f).SetId("mouthAnim");
                _mouth.transform.DOScaleY(0.06f, 0.2f);
                if (_mouthMat != null) { DOTween.Kill(_mouthMat); _mouthMat.DOColor(SSColorPalette.Danger, 0.3f); }
            });
        }

        public void PlaySad()
        {
            if (_mouth != null)
            {
                DOTween.Kill(_mouth.transform, "mouthAnim");
                _mouth.transform.DOScaleX(0.15f, 0.15f).SetId("mouthAnim");
            }
            if (_head != null)
            {
                DOTween.Kill(_head.transform, "headShake");
                _head.transform.DOShakeRotation(0.4f, 10f, 10).SetId("headShake");
            }
            if (_headMat != null)
            {
                DOTween.Kill(_headMat, "headFlash");
                _headMat.DOColor(SSColorPalette.Danger, 0.15f).SetId("headFlash")
                    .OnComplete(() => _headMat.DOColor(SSColorPalette.Accent, 0.4f));
            }

            DOTween.Sequence().SetDelay(1f).OnComplete(() =>
            {
                if (_mouth == null) return;
                DOTween.Kill(_mouth.transform, "mouthAnim");
                _mouth.transform.DOScaleX(0.25f, 0.2f).SetId("mouthAnim");
            });
        }

        public void PlayVictoryDance()
        {
            KillAllTweens();
            var seq = DOTween.Sequence();
            seq.Append(transform.DOJump(transform.position + Vector3.up * 0.3f, 0.5f, 3, 1.5f));
            seq.Join(transform.DORotate(new Vector3(0, 360, 0), 1.5f, RotateMode.FastBeyond360));
            seq.OnComplete(() => StartIdleAnimation());
        }

        public void ShowSpeechBubble()
        {
            DOTween.Kill(transform, "botPunch");
            transform.DOPunchScale(Vector3.one * 0.1f, 0.3f, 4, 0.2f).SetId("botPunch");
        }

        public void ResetBot()
        {
            KillAllTweens();
            transform.localScale = Vector3.one;
            transform.localRotation = Quaternion.identity;
            transform.position = new Vector3(transform.position.x, _baseY, transform.position.z);
            StartIdleAnimation();
        }

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