using UnityEngine;
using UnityEngine.InputSystem;

namespace OkonaPad.Samples
{
    public class PlayerController : MonoBehaviour
    {
        [Header("Movement Settings")]
        [SerializeField] private float moveForce = 20f;
        [SerializeField] private float maxSpeed = 10f;
        [SerializeField] private float brakeDrag = 5f;

        [Header("Jump Settings")]
        [SerializeField] private float jumpForce = 8f;
        [SerializeField] private LayerMask groundLayer;
        [SerializeField] private float groundCheckDistance = 0.6f;

        [Header("Color Settings")]
        [SerializeField] private float colorChangeInterval = 0.15f;

        [Header("Audio")]
        [SerializeField] private AudioClip jumpSound;
        [SerializeField] private AudioClip beepSound;

        private Rigidbody _rb;
        private PlayerInput _playerInput;
        private AudioSource _audioSource;
        private Renderer _renderer;
        private InputAction _brakeAction;
        private Vector2 _moveInput;
        private bool _isBraking;
        private bool _isGrounded;
        private bool _isChangingColors;
        private float _colorChangeTimer;
        private static bool _isPaused;

        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
        static void ResetStatics()
        {
            _isPaused = false;
        }

        private static readonly Color[] BrightColors =
        {
            new Color(1f, 0.2f, 0.4f),   // Hot Pink
            new Color(0f, 1f, 0.5f),      // Spring Green
            new Color(0.2f, 0.6f, 1f),    // Dodger Blue
            new Color(1f, 0.85f, 0f),     // Gold
            new Color(0.8f, 0.2f, 1f),    // Purple
            new Color(1f, 0.5f, 0f),      // Orange
            new Color(0f, 1f, 1f),        // Cyan
            new Color(1f, 0.4f, 0.7f),    // Pink
            new Color(0.5f, 1f, 0f),      // Lime
            new Color(1f, 0f, 0.5f),      // Rose
        };

        void Awake()
        {
            _playerInput = GetComponent<PlayerInput>();
            if (_playerInput != null)
            {
                _playerInput.onDeviceLost += OnDeviceLost;
                _playerInput.onDeviceRegained += OnDeviceRegained;
                _brakeAction = _playerInput.actions["Brake"];
            }
        }

        void Start()
        {
            _rb = GetComponent<Rigidbody>();
            if (_rb == null)
            {
                Debug.LogError("[PlayerController] Rigidbody component required!");
                return;
            }
            _rb.linearDamping = 0f;

            Time.timeScale = 1f;
            _isPaused = false;

            _renderer = GetComponent<Renderer>();
            if (_renderer != null)
                _renderer.material.color = BrightColors[Random.Range(0, BrightColors.Length)];

            _audioSource = GetComponent<AudioSource>();
            if (_audioSource == null)
                _audioSource = gameObject.AddComponent<AudioSource>();
            _audioSource.playOnAwake = false;
        }

        void OnDestroy()
        {
            if (_playerInput != null)
            {
                _playerInput.onDeviceLost -= OnDeviceLost;
                _playerInput.onDeviceRegained -= OnDeviceRegained;
            }
        }

        void Update()
        {
            // Respawn if fallen off the level
            if (transform.position.y < -5f && _rb != null)
            {
                transform.position = new Vector3(0f, 2f, 0f);
                _rb.linearVelocity = Vector3.zero;
                _rb.angularVelocity = Vector3.zero;
            }

            // Color cycling
            if (_isChangingColors && _renderer != null)
            {
                _colorChangeTimer -= Time.deltaTime;
                if (_colorChangeTimer <= 0f)
                {
                    _renderer.material.color = BrightColors[Random.Range(0, BrightColors.Length)];
                    _colorChangeTimer = colorChangeInterval;
                }
            }
        }

        private void OnDeviceLost(PlayerInput playerInput)
        {
            Debug.Log($"[PlayerController] Device lost - destroying player {gameObject.name}");
            Destroy(gameObject);
        }

        private void OnDeviceRegained(PlayerInput playerInput)
        {
            Debug.Log($"[PlayerController] Device regained for player {gameObject.name}");
        }

        void FixedUpdate()
        {
            if (_rb == null) return;

            _isBraking = _brakeAction != null && _brakeAction.IsPressed();

            // Ground check (fall back to all layers if groundLayer not set)
            int mask = groundLayer == 0 ? ~0 : (int)groundLayer;
            _isGrounded = Physics.SphereCast(transform.position, 0.2f, Vector3.down, out _, groundCheckDistance, mask);

            // Apply force in joystick direction
            Vector3 forceDir = new Vector3(_moveInput.x, 0f, _moveInput.y) * moveForce;
            _rb.AddForce(forceDir, ForceMode.Force);

            // Clamp horizontal speed and apply brake drag
            Vector3 horizontalVel = new Vector3(_rb.linearVelocity.x, 0f, _rb.linearVelocity.z);

            if (_isBraking)
                _rb.AddForce(-horizontalVel * brakeDrag, ForceMode.Force);
            if (horizontalVel.magnitude > maxSpeed)
            {
                horizontalVel = horizontalVel.normalized * maxSpeed;
                _rb.linearVelocity = new Vector3(horizontalVel.x, _rb.linearVelocity.y, horizontalVel.z);
            }
        }

        // Called by PlayerInput component via SendMessage
        public void OnMove(InputValue value)
        {
            _moveInput = value.Get<Vector2>();
            Debug.Log($"[PlayerController] OnMove: {_moveInput}");
        }

        public void OnJump(InputValue value)
        {
            if (value.isPressed && _isGrounded && _rb != null)
            {
                _rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
                if (jumpSound != null)
                    _audioSource.PlayOneShot(jumpSound);
            }
        }

        public void OnChangeColor(InputValue value)
        {
            if (!value.isPressed) return;

            _isChangingColors = !_isChangingColors;
            if (!_isChangingColors && _renderer != null)
            {
                // Settle on a final random color when stopping
                _renderer.material.color = BrightColors[Random.Range(0, BrightColors.Length)];
            }
        }

        public void OnBeep(InputValue value)
        {
            if (value.isPressed && beepSound != null)
                _audioSource.PlayOneShot(beepSound);
        }

        public void OnPause(InputValue value)
        {
            if (!value.isPressed) return;

            _isPaused = !_isPaused;
            Time.timeScale = _isPaused ? 0f : 1f;
            Debug.Log($"[PlayerController] Game {(_isPaused ? "paused" : "resumed")}");
        }
    }
}
