using System;
using UnityEngine;
using Zenject;

namespace FlappyBird.Core
{
    public class DeathManager : IDeathManager, IInitializable, ITickable, IDisposable
    {
        private const float ShakeDuration = 0.2f;
        private const float ShakeMagnitude = 0.18f;

        private readonly IGameManager _gameManager;

        private Transform _cameraTransform;
        private Vector3 _cameraBaseLocalPosition;
        private float _shakeTimeRemaining;

        [Inject]
        public DeathManager(IGameManager gameManager)
        {
            _gameManager = gameManager;
        }

        public bool IsDead { get; private set; }

        public event Action OnDied;

        public void Initialize()
        {
            _gameManager.OnGameStateChanged += HandleGameStateChanged;
            CacheMainCamera();
            IsDead = false;
        }

        public void Dispose()
        {
            _gameManager.OnGameStateChanged -= HandleGameStateChanged;
            ResetCameraPosition();
        }

        public void Tick()
        {
            if (_shakeTimeRemaining <= 0f)
            {
                return;
            }

            if (!CacheMainCamera())
            {
                _shakeTimeRemaining = 0f;
                return;
            }

            _shakeTimeRemaining -= Time.deltaTime;
            if (_shakeTimeRemaining <= 0f)
            {
                ResetCameraPosition();
                return;
            }

            float strength = ShakeMagnitude * (_shakeTimeRemaining / ShakeDuration);
            Vector2 offset = UnityEngine.Random.insideUnitCircle * strength;
            _cameraTransform.localPosition = _cameraBaseLocalPosition + new Vector3(offset.x, offset.y, 0f);
        }

        public void Die()
        {
            if (IsDead || _gameManager.CurrentState != GameState.Playing)
            {
                return;
            }

            IsDead = true;
            StartCameraShake();
            OnDied?.Invoke();
            _gameManager.GameOver();
        }

        private void HandleGameStateChanged(GameState state)
        {
            if (state == GameState.Menu)
            {
                IsDead = false;
                _shakeTimeRemaining = 0f;
                ResetCameraPosition();
            }
        }

        private void StartCameraShake()
        {
            if (!CacheMainCamera())
            {
                return;
            }

            _shakeTimeRemaining = ShakeDuration;
        }

        private bool CacheMainCamera()
        {
            if (_cameraTransform != null)
            {
                return true;
            }

            Camera mainCamera = Camera.main;
            if (mainCamera == null)
            {
                return false;
            }

            _cameraTransform = mainCamera.transform;
            _cameraBaseLocalPosition = _cameraTransform.localPosition;
            return true;
        }

        private void ResetCameraPosition()
        {
            if (_cameraTransform == null)
            {
                return;
            }

            _cameraTransform.localPosition = _cameraBaseLocalPosition;
        }
    }
}
