using System;
using Cybe;
using UniRx;
using UnityEngine;
using UnityEngine.VFX;
using Zenject;

namespace Sources.Enemies
{
    public class Cylinder : AggrableEnemy
    {
        [SerializeField] private Rigidbody _rigidbody;
        [SerializeField] private VisualEffect _attackEffect;
        [SerializeField] private CylinderBomb _bomb;
        [SerializeField] private Transform _shootPoint;
        
        [Header("Balance")]
        [SerializeField] private float _attackRadius = 1;
        [SerializeField] private float _moveSpeed = 2;
        [SerializeField] private float _damage = 5f;
        [SerializeField] private float _cooldown = 5f;

        [Inject] private AudioManager _audioManager;
        
        private Vector3 _initialPosition;
        private bool _isAttacking;
        private bool _isCooldown;
        private CompositeDisposable _disposables = new CompositeDisposable();
        
        protected override void OnUpdate()
        {
            base.OnUpdate();

            if (!IsAlive || _isAttacking)
                return;

            if (TryAttack())
                return;
            
            UpdateMoving();
        }
        
        private void Start()
        {
            base.OnStart();

            if (Physics.Raycast(transform.position, Vector3.down, out var hit, 100, LayerMask.GetMask("Ground")))
            {
                _initialPosition = hit.point;
            }
            else
            {
                _initialPosition = transform.position;
            }
        }
        
        private bool TryAttack()
        {
            if (!IsAttackPossible())
                return false;

            if (_isCooldown)
                return true;
            
            _attackEffect.Play();
            _isCooldown = true;

            var bomb = Instantiate(_bomb, _shootPoint.position, Quaternion.identity);
            bomb.RandomShoot(_damage, 10000, 2, transform);

            Observable.Timer(TimeSpan.FromSeconds(_cooldown)).Subscribe(_ => _isCooldown = false);

            return true;
        }

        private bool IsAttackPossible()
        {
            if (!IsAlive || !Target)
                return false;
            
            if (Vector3.Distance(transform.position, Target.transform.position) > _attackRadius)
                return false;

            return true;
        }
        
        private void UpdateMoving()
        {
            var position = transform.position;
            if (!Target && Vector3.Distance(position, _initialPosition) < 0.5f)
                return;

            var targetPoint = Target ? Target.transform.position : _initialPosition;
            var directionToTarget = targetPoint - position;
            directionToTarget = _moveSpeed * Time.deltaTime * directionToTarget.normalized;
            targetPoint = position + directionToTarget;

            _rigidbody.MovePosition(targetPoint);
        }

        public override void TakeDamage(float damage, Transform damageDealer = null, DamageType type = DamageType.Melee)
        {
            if (type == DamageType.Ranged)
            {
                _audioManager.PlayFx(SoundType.Ricochet);
                return;
            }

            base.TakeDamage(damage, damageDealer, type);
        }

        private void OnDestroy()
        {
            _disposables?.Dispose();
        }
    }
}