using UnityEngine;
using IStalk.Core;
using IStalk.Data;

namespace IStalk.Shared
{
    public class AudioManager : MonoBehaviour
    {
        public static AudioManager Instance { get; private set; }

        [Header("Music")]
        [SerializeField] private AudioSource _musicSource;
        [SerializeField] private AudioClip _graceMusic;
        [SerializeField] private AudioClip _huntMusic;
        [SerializeField] private AudioClip _overtimeMusic;
        [SerializeField] private AudioClip _winMusic;
        [SerializeField] private AudioClip _loseMusic;

        [Header("Settings")]
        [SerializeField] private float _musicFadeDuration = 1.5f;
        [SerializeField] private float _musicVolume = 0.4f;

        [Header("SFX Pool")]
        [SerializeField] private int _poolSize = 16;

        private AudioSource[] _sfxPool;
        private int _nextPoolIndex;
        private float _fadeTarget;
        private float _fadeSpeed;
        private AudioClip _pendingClip;

        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
                return;
            }
            Instance = this;
            DontDestroyOnLoad(gameObject);
            InitializePool();
        }

        private void Start()
        {
            if (GameManager.Instance != null)
                GameManager.Instance.OnStateChanged += HandleMatchStateChanged;
        }

        private void InitializePool()
        {
            _sfxPool = new AudioSource[_poolSize];
            for (int i = 0; i < _poolSize; i++)
            {
                var go = new GameObject($"SFX_{i}");
                go.transform.SetParent(transform);
                _sfxPool[i] = go.AddComponent<AudioSource>();
                _sfxPool[i].playOnAwake = false;
                _sfxPool[i].spatialBlend = 1f;
            }
        }

        public void PlaySfx(AudioClip clip, Vector3 position, float volume = 1f)
        {
            if (clip == null) return;

            var source = _sfxPool[_nextPoolIndex];
            _nextPoolIndex = (_nextPoolIndex + 1) % _poolSize;

            source.transform.position = position;
            source.clip = clip;
            source.volume = volume;
            source.Play();
        }

        public void PlaySfx2D(AudioClip clip, float volume = 1f)
        {
            if (clip == null) return;

            var source = _sfxPool[_nextPoolIndex];
            _nextPoolIndex = (_nextPoolIndex + 1) % _poolSize;

            source.spatialBlend = 0f;
            source.clip = clip;
            source.volume = volume;
            source.Play();
            source.spatialBlend = 1f;
        }

        private void HandleMatchStateChanged(MatchState state)
        {
            AudioClip clip = state switch
            {
                MatchState.GracePeriod => _graceMusic,
                MatchState.Hunt => _huntMusic,
                MatchState.Overtime => _overtimeMusic,
                MatchState.RunnersWin => _winMusic,
                MatchState.EyeWins => _loseMusic,
                _ => null
            };

            if (clip != null)
                CrossfadeMusic(clip);
        }

        private void CrossfadeMusic(AudioClip newClip)
        {
            _pendingClip = newClip;
            _fadeTarget = 0f;
            _fadeSpeed = _musicVolume / _musicFadeDuration;
        }

        private void Update()
        {
            if (_musicSource == null) return;

            if (_pendingClip != null)
            {
                _musicSource.volume = Mathf.MoveTowards(_musicSource.volume, _fadeTarget, _fadeSpeed * Time.deltaTime);

                if (Mathf.Approximately(_musicSource.volume, 0f))
                {
                    _musicSource.clip = _pendingClip;
                    _musicSource.Play();
                    _pendingClip = null;
                    _fadeTarget = _musicVolume;
                }
            }
            else if (_fadeTarget > 0 && _musicSource.volume < _musicVolume)
            {
                _musicSource.volume = Mathf.MoveTowards(_musicSource.volume, _fadeTarget, _fadeSpeed * Time.deltaTime);
            }
        }

        private void OnDestroy()
        {
            if (GameManager.Instance != null)
                GameManager.Instance.OnStateChanged -= HandleMatchStateChanged;
        }
    }
}
