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

namespace com.al_arcade.tf
{
    using shared;

    public class TfProductionLine : MonoBehaviour
    {
        private GameObject _product;
        private GameObject[] _rollers;
        private Material _productMat;
        private float _currentZ;
        private int _stepsToWin;

        public void Build(int stepsToWin, float stepDistance, Vector3 cameraPos)
        {
            _stepsToWin = stepsToWin;
            float totalLength = stepsToWin * stepDistance + 10f;
            var shader = GetShader();


            var belt = GameObject.CreatePrimitive(PrimitiveType.Cube);
            belt.name = "Belt";
            belt.transform.SetParent(transform);
            belt.transform.localPosition = new Vector3(0, 0.3f, totalLength / 2f);
            belt.transform.localScale = new Vector3(2.5f, 0.1f, totalLength);
            Destroy(belt.GetComponent<Collider>());
            belt.GetComponent<Renderer>().material =
                new Material(shader) { color = new Color32(55, 55, 65, 255) };


            var beltTop = GameObject.CreatePrimitive(PrimitiveType.Cube);
            beltTop.name = "BeltTop";
            beltTop.transform.SetParent(transform);
            beltTop.transform.localPosition = new Vector3(0, 0.36f, totalLength / 2f);
            beltTop.transform.localScale = new Vector3(2.4f, 0.005f, totalLength);
            Destroy(beltTop.GetComponent<Collider>());
            beltTop.GetComponent<Renderer>().material =
                new Material(shader) { color = new Color32(70, 70, 80, 255) };


            int rc = Mathf.CeilToInt(totalLength / 2f);
            _rollers = new GameObject[rc];
            for (int i = 0; i < rc; i++)
            {
                var r = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                r.name = $"Roller_{i}";
                r.transform.SetParent(transform);
                r.transform.localPosition = new Vector3(0, 0.15f, i * 2f);
                r.transform.localRotation = Quaternion.Euler(0, 0, 90);
                r.transform.localScale = new Vector3(0.1f, 1.3f, 0.1f);
                Destroy(r.GetComponent<Collider>());
                r.GetComponent<Renderer>().material =
                    new Material(shader) { color = new Color32(130, 130, 140, 255) };
                _rollers[i] = r;
            }


            for (int s = -1; s <= 1; s += 2)
            {
                var rail = GameObject.CreatePrimitive(PrimitiveType.Cube);
                rail.name = "Rail";
                rail.transform.SetParent(transform);
                rail.transform.localPosition = new Vector3(s * 1.35f, 0.5f, totalLength / 2f);
                rail.transform.localScale = new Vector3(0.06f, 0.35f, totalLength);
                Destroy(rail.GetComponent<Collider>());
                rail.GetComponent<Renderer>().material =
                    new Material(shader) { color = SSColorPalette.Primary };
            }


            for (float z = 1; z < totalLength; z += 4f)
            {
                for (int s = -1; s <= 1; s += 2)
                {
                    var leg = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    leg.name = "Leg";
                    leg.transform.SetParent(transform);
                    leg.transform.localPosition = new Vector3(s * 1f, 0.1f, z);
                    leg.transform.localScale = new Vector3(0.08f, 0.3f, 0.08f);
                    Destroy(leg.GetComponent<Collider>());
                    leg.GetComponent<Renderer>().material =
                        new Material(shader) { color = new Color32(85, 85, 95, 255) };
                }
            }


            for (int i = 0; i < stepsToWin; i++)
            {
                float mz = (i + 1) * stepDistance;


                var marker = GameObject.CreatePrimitive(PrimitiveType.Cube);
                marker.name = $"Marker_{i}";
                marker.transform.SetParent(transform);
                marker.transform.localPosition = new Vector3(0, 0.37f, mz);
                marker.transform.localScale = new Vector3(2.5f, 0.015f, 0.1f);
                Destroy(marker.GetComponent<Collider>());
                marker.GetComponent<Renderer>().material =
                    new Material(shader)
                    {
                        color = SSColorPalette.WithAlpha(SSColorPalette.Accent, 0.5f)
                    };


                var labelObj = new GameObject("StepLabel");
                labelObj.transform.SetParent(marker.transform);
                labelObj.transform.position =
                    marker.transform.position + new Vector3(1.6f, 0.5f, 0);


                Vector3 away = labelObj.transform.position - cameraPos;
                away.y = 0;
                if (away.sqrMagnitude > 0.01f)
                    labelObj.transform.rotation = Quaternion.LookRotation(away);

                var lbl = labelObj.AddComponent<ArabicTextMeshPro>();
                lbl.arabicText = $"✦ {i + 1}";

                lbl.fontSize = 2f;
                lbl.alignment = TMPro.TextAlignmentOptions.Center;
                lbl.color = SSColorPalette.WithAlpha(SSColorPalette.Accent, 0.7f);
                lbl.rectTransform.sizeDelta = new Vector2(1.5f, 0.6f);
                SSFontManager.Apply(lbl);
            }


            float endZ = stepsToWin * stepDistance + 2f;
            var ez = GameObject.CreatePrimitive(PrimitiveType.Cube);
            ez.name = "EndZone";
            ez.transform.SetParent(transform);
            ez.transform.localPosition = new Vector3(0, 0.37f, endZ);
            ez.transform.localScale = new Vector3(3f, 0.015f, 2f);
            Destroy(ez.GetComponent<Collider>());
            ez.GetComponent<Renderer>().material =
                new Material(shader) { color = SSColorPalette.WithAlpha(SSColorPalette.Success, 0.35f) };


            _product = new GameObject("Product");
            _product.transform.SetParent(transform);
            _product.transform.localPosition = new Vector3(0, 0.7f, 0);

            var box = GameObject.CreatePrimitive(PrimitiveType.Cube);
            box.name = "Box";
            box.transform.SetParent(_product.transform);
            box.transform.localPosition = Vector3.zero;
            box.transform.localScale = new Vector3(1.2f, 1f, 1.2f);
            Destroy(box.GetComponent<Collider>());
            _productMat = new Material(shader) { color = SSColorPalette.Accent };
            box.GetComponent<Renderer>().material = _productMat;


            var stripe = GameObject.CreatePrimitive(PrimitiveType.Cube);
            stripe.name = "Stripe";
            stripe.transform.SetParent(_product.transform);
            stripe.transform.localPosition = new Vector3(0, 0, -0.61f);
            stripe.transform.localScale = new Vector3(1.0f, 0.25f, 0.02f);
            Destroy(stripe.GetComponent<Collider>());
            stripe.GetComponent<Renderer>().material =
                new Material(shader) { color = SSColorPalette.Primary };


            var star = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            star.name = "Star";
            star.transform.SetParent(_product.transform);
            star.transform.localPosition = new Vector3(0, 0.55f, 0);
            star.transform.localScale = Vector3.one * 0.25f;
            Destroy(star.GetComponent<Collider>());
            star.GetComponent<Renderer>().material =
                new Material(shader) { color = Color.white };

            _currentZ = 0;
        }


        public IEnumerator MoveForward(float dist)
        {
            _currentZ += dist;
            SpinRollers(true);
            DOTween.Kill(_product.transform, "prodMove");
            yield return _product.transform
                .DOLocalMoveZ(_currentZ, 0.6f)
                .SetEase(Ease.OutBack).SetId("prodMove")
                .WaitForCompletion();

            _product.transform.DOPunchScale(Vector3.one * 0.12f, 0.3f, 6, 0.3f);
            if (_productMat != null)
            {
                DOTween.Kill(_productMat, "prodColor");
                _productMat.DOColor(SSColorPalette.Success, 0.12f).SetId("prodColor")
                    .OnComplete(() => _productMat.DOColor(SSColorPalette.Accent, 0.3f));
            }
        }

        public IEnumerator MoveBackward(float dist)
        {
            _currentZ = Mathf.Max(0, _currentZ - dist);
            SpinRollers(false);

            DOTween.Kill(_product.transform, "prodMove");
            var seq = DOTween.Sequence().SetId("prodMove");
            seq.Append(_product.transform.DOShakePosition(0.3f, 0.08f, 15));
            seq.Append(_product.transform
                .DOLocalMoveZ(_currentZ, 0.5f).SetEase(Ease.OutQuad));

            if (_productMat != null)
            {
                DOTween.Kill(_productMat, "prodColor");
                _productMat.DOColor(SSColorPalette.Danger, 0.12f).SetId("prodColor")
                    .OnComplete(() => _productMat.DOColor(SSColorPalette.Accent, 0.3f));
            }
            yield return seq.WaitForCompletion();
        }

        public IEnumerator ProductComplete()
        {
            DOTween.Kill(_product.transform);
            var seq = DOTween.Sequence();
            seq.Append(_product.transform
                .DOLocalMoveY(3f, 0.6f).SetEase(Ease.OutQuad));
            seq.Join(_product.transform
                .DOScale(1.5f, 0.4f).SetEase(Ease.OutBack));
            seq.Join(_product.transform
                .DOLocalRotate(new Vector3(0, 360, 0), 0.8f, RotateMode.FastBeyond360)
                .SetEase(Ease.InOutQuad));
            yield return seq.WaitForCompletion();

            var particles = SSParticleManager.Instance;
            if (particles != null)
                particles.PlayStarBurst(_product.transform.position);
        }

        public void ResetLine()
        {
            _currentZ = 0;
            if (_product != null)
            {
                DOTween.Kill(_product.transform);
                _product.transform.localPosition = new Vector3(0, 0.7f, 0);
                _product.transform.localScale = Vector3.one;
                _product.transform.localRotation = Quaternion.identity;
            }
        }

        private void SpinRollers(bool forward)
        {
            if (_rollers == null) return;
            float angle = forward ? 360 : -360;
            foreach (var r in _rollers)
            {
                if (r == null) continue;
                DOTween.Kill(r.transform, "rollerSpin");
                r.transform.DOLocalRotate(
                    r.transform.localEulerAngles + new Vector3(angle, 0, 0),
                    0.5f, RotateMode.FastBeyond360)
                    .SetEase(Ease.OutQuad).SetId("rollerSpin");
            }
        }

        private Shader GetShader() =>
            Shader.Find("Universal Render Pipeline/Lit")
            ?? Shader.Find("Standard") ?? Shader.Find("Unlit/Color");
    }
}
