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

namespace com.al_arcade.mcq
{
    using shared;

    [RequireComponent(typeof(Rigidbody))]
    public class McqPlayerRunner : MonoBehaviour
    {

        private McqGameManager _manager;

        [Header("Movement")]
        [SerializeField] private float laneSwitchSpeed = 8f;
        [SerializeField] private float laneSwitchDuration = 0.25f;

        [Header("Visual")]
        [SerializeField] private float bobAmplitude = 0.08f;
        [SerializeField] private float bobFrequency = 6f;

        private Rigidbody _rb;
        private float _currentSpeed;
        private bool _isRunning;
        private Vector3 _startPosition;
        private float _bobTimer;
        private float _baseY;
        private Renderer _renderer;
        private Material _material;
        private Animator _animator;

        private int _currentLane = -1;
        private float[] _lanePositions;

        private void Awake()
        {
            _rb = GetComponent<Rigidbody>();
            _rb.isKinematic = true;
            _rb.useGravity = false;
            _startPosition = transform.position;
            _baseY = transform.position.y;
            _renderer = GetComponentInChildren<Renderer>();
            _animator = transform.GetChild(0).GetComponent<Animator>();
            if (_renderer != null) _material = _renderer.material;
            gameObject.tag = "Player";
        }

        public void SetupManager(McqGameManager manager)
        {
            if (manager == null) print("Null manager");
            _manager = manager;
            manager.onAnswerGiven.AddListener(PlayAnimation);
            manager.onGameOver.AddListener(Stop);
        }
        private void PlayAnimation(bool correct)
        {
            _animator.ResetTrigger(correct ? "Wrong" : "Correct");
            _animator.SetTrigger(correct ? "Correct" : "Wrong");
        }

        public void SetLanePositions(float[] positions) => _lanePositions = positions;

        public void RunForward(float speed)
        {
            _currentSpeed = speed;
            _isRunning = true;
        }

        public void Stop()
        {
            _animator.Play("closing");
            _currentSpeed = 0;
            _isRunning = false;
        }

        public void ResetToStart()
        {
            //Stop();
            DOTween.Kill(transform);
            transform.position = _startPosition;
            transform.rotation = Quaternion.identity;
            transform.localScale = Vector3.one;
            _currentLane = -1;

            _animator.Play("opening");
        }

        public IEnumerator MoveToNextLane(float duration)
        {
            Vector3 target = transform.position + Vector3.forward * 2f;
            DOTween.Kill(transform, "moveNext");
            yield return transform.DOMove(target, duration)
                .SetEase(Ease.InOutQuad).SetId("moveNext")
                .WaitForCompletion();
        }

        private void Update()
        {
            if (!_isRunning) return;

            transform.position += Vector3.forward * (_currentSpeed * Time.deltaTime);

            _bobTimer += Time.deltaTime;
            float bobY = _baseY + Mathf.Sin(_bobTimer * bobFrequency) * bobAmplitude;
            transform.position = new Vector3(transform.position.x, bobY, transform.position.z);

            if (_lanePositions != null && _lanePositions.Length > 0)
                HandleLaneInput();
            else
                HandleFreeMovement();
        }

        private void HandleFreeMovement()
        {
            float moveX = 0f;
            if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
                moveX = -laneSwitchSpeed * Time.deltaTime;
            if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
                moveX = laneSwitchSpeed * Time.deltaTime;

            if (moveX != 0)
            {
                Vector3 pos = transform.position;
                pos.x = Mathf.Clamp(pos.x + moveX, -6f, 6f);
                transform.position = pos;
                /*
                float targetTilt = Mathf.Clamp(-moveX * 300f, -15f, 15f);
                transform.rotation = Quaternion.Slerp(transform.rotation,
                    Quaternion.Euler(0, 0, targetTilt), Time.deltaTime * 10f);
                */
            }
            else
            {
                transform.rotation = Quaternion.Slerp(transform.rotation,
                    Quaternion.identity, Time.deltaTime * 8f);
            }
        }

        private void HandleLaneInput()
        {
            if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A))
                if (_currentLane > 0) MoveToLane(--_currentLane);
            if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D))
                if (_currentLane < _lanePositions.Length - 1) MoveToLane(++_currentLane);
        }

        private void MoveToLane(int lane)
        {
            if (_lanePositions == null || lane < 0 || lane >= _lanePositions.Length) return;
            DOTween.Kill(transform, "laneSwitch");
            transform.DOMoveX(_lanePositions[lane], laneSwitchDuration)
                .SetEase(Ease.OutQuad).SetId("laneSwitch");

            var audio = SSAudioManager.Instance;
            if (audio != null) audio.PlayClickBeep();
        }

        public void FlashColor(Color color, float duration = 0.3f)
        {
            if (_material == null) return;
            Color orig = _material.color;
            DOTween.Kill(_material);
            _material.DOColor(color, duration * 0.3f)
                .OnComplete(() => _material.DOColor(orig, duration * 0.7f));
        }

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

            var body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
            body.name = "Body";
            body.transform.SetParent(transform);
            body.transform.localPosition = Vector3.up * 1f;
            body.transform.localScale = new Vector3(0.6f, 1f, 0.6f);
            Destroy(body.GetComponent<Collider>());
            var bodyMat = new Material(shader) { color = SSColorPalette.Accent };
            body.GetComponent<Renderer>().material = bodyMat;
            _renderer = body.GetComponent<Renderer>();
            _material = bodyMat;

            var head = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            head.name = "Head";
            head.transform.SetParent(transform);
            head.transform.localPosition = Vector3.up * 2.2f;
            head.transform.localScale = Vector3.one * 0.5f;
            Destroy(head.GetComponent<Collider>());
            var headMat = new Material(shader) { color = new Color32(255, 220, 170, 255) };
            head.GetComponent<Renderer>().material = headMat;

            for (int i = -1; i <= 1; i += 2)
            {
                var eye = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                eye.name = "Eye";
                eye.transform.SetParent(head.transform);
                eye.transform.localPosition = new Vector3(i * 0.15f, 0.05f, -0.4f);
                eye.transform.localScale = Vector3.one * 0.2f;
                Destroy(eye.GetComponent<Collider>());
                eye.GetComponent<Renderer>().material = new Material(shader) { color = Color.black };
            }

            var col = gameObject.AddComponent<CapsuleCollider>();
            col.center = Vector3.up * 1.2f;
            col.radius = 0.4f;
            col.height = 2.8f;
            col.isTrigger = true;
        }
    }
}
