using UnityEngine;

public class LocalPlayerController : MonoBehaviour
{
    [Header("Movement")]
    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float rotationSpeed = 720f;

    [Header("Network")]
    [SerializeField] private float sendRate = 0.1f;

    private Animator _animator;
    private Vector3 _lastSentPos;
    private float _lastSentRot;
    private string _lastSentAnim;
    private float _sendTimer;

    private static readonly int AnimIsWalking = Animator.StringToHash("IsWalking");

    private void Awake()
    {
        _animator = GetComponentInChildren<Animator>();
    }

    private void Update()
    {
        Vector3 input = GetInput();
        Move(input);
        UpdateAnimation(input);
        SendPositionToServer();
    }

    private Vector3 GetInput()
    {
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        return new Vector3(h, 0, v).normalized;
    }

    private void Move(Vector3 input)
    {
        if (input.sqrMagnitude < 0.01f) return;

        Vector3 movement = input * (moveSpeed * Time.deltaTime);
        transform.position += movement;

        Quaternion targetRot = Quaternion.LookRotation(input);
        transform.rotation = Quaternion.RotateTowards(
            transform.rotation, targetRot, rotationSpeed * Time.deltaTime);
    }

    private void UpdateAnimation(Vector3 input)
    {
        if (_animator == null) return;
        _animator.SetBool(AnimIsWalking, input.sqrMagnitude > 0.01f);
    }

    private void SendPositionToServer()
    {
        _sendTimer += Time.deltaTime;
        if (_sendTimer < sendRate) return;
        _sendTimer = 0;

        if (!ArcadeNetworkManager.Instance || !ArcadeNetworkManager.Instance.IsConnected) return;

        string currentAnim = _animator != null && _animator.GetBool(AnimIsWalking) ? "walk" : "idle";

        bool posChanged = Vector3.Distance(transform.position, _lastSentPos) > 0.01f;
        bool rotChanged = Mathf.Abs(transform.eulerAngles.y - _lastSentRot) > 1f;
        bool animChanged = currentAnim != _lastSentAnim;

        if (!posChanged && !rotChanged && !animChanged) return;

        ArcadeNetworkManager.Instance.SendMove(transform.position, transform.eulerAngles.y, currentAnim);

        _lastSentPos = transform.position;
        _lastSentRot = transform.eulerAngles.y;
        _lastSentAnim = currentAnim;
    }
}
