

using UnityEngine;
using System.Collections.Generic;

namespace com.al_arcade.shared
{
    public class SSAudioManager : MonoBehaviour
    {
        public static SSAudioManager Instance { get; private set; }

        [Header("Sound Effects (all optional)")]
        public AudioClip sfxCorrect;
        public AudioClip sfxWrong;
        public AudioClip sfxClick;
        public AudioClip sfxWhoosh;
        public AudioClip sfxPop;
        public AudioClip sfxVictory;
        public AudioClip sfxDefeat;
        public AudioClip sfxTick;
        public AudioClip sfxSlam;
        public AudioClip sfxDing;
        public AudioClip sfxBuzz;
        public AudioClip sfxSwipe;
        public AudioClip sfxExplosion;
        public AudioClip sfxCheer;
        public AudioClip sfxCountdown;

        [Header("Settings")]
        [Range(0f, 1f)] public float masterVolume = 1f;
        public int audioSourcePoolSize = 8;

        private List<AudioSource> _pool = new List<AudioSource>();
        private int _poolIndex = 0;

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

        public static SSAudioManager EnsureInstance()
        {
            if (Instance != null) return Instance;
            var go = new GameObject("[SSAudioManager]");
            Instance = go.AddComponent<SSAudioManager>();
            DontDestroyOnLoad(go);
            Instance.InitPool();
            return Instance;
        }

        private void InitPool()
        {
            if (_pool.Count > 0) return;
            for (int i = 0; i < audioSourcePoolSize; i++)
            {
                var src = gameObject.AddComponent<AudioSource>();
                src.playOnAwake = false;
                _pool.Add(src);
            }
        }

        private AudioSource GetSource()
        {
            if (_pool.Count == 0) InitPool();
            var src = _pool[_poolIndex % _pool.Count];
            _poolIndex++;
            return src;
        }


        public void Play(AudioClip clip, float volumeScale = 1f, float pitch = 1f)
        {
            if (clip == null) return;
            var src = GetSource();
            src.pitch = pitch;
            src.volume = masterVolume * volumeScale;
            src.PlayOneShot(clip);
        }

        public void PlayCorrect(float vol = 1f)    => Play(sfxCorrect, vol);
        public void PlayWrong(float vol = 1f)       => Play(sfxWrong, vol);
        public void PlayClick(float vol = 0.7f)     => Play(sfxClick, vol);
        public void PlayWhoosh(float vol = 0.8f)    => Play(sfxWhoosh, vol);
        public void PlayPop(float vol = 0.8f)       => Play(sfxPop, vol);
        public void PlayVictory(float vol = 1f)     => Play(sfxVictory, vol);
        public void PlayDefeat(float vol = 1f)      => Play(sfxDefeat, vol);
        public void PlayTick(float vol = 0.5f)      => Play(sfxTick, vol);
        public void PlaySlam(float vol = 1f)        => Play(sfxSlam, vol);
        public void PlayDing(float vol = 0.8f)      => Play(sfxDing, vol);
        public void PlayBuzz(float vol = 0.8f)      => Play(sfxBuzz, vol);
        public void PlaySwipe(float vol = 0.7f)     => Play(sfxSwipe, vol);
        public void PlayExplosion(float vol = 1f)   => Play(sfxExplosion, vol);
        public void PlayCheer(float vol = 1f)       => Play(sfxCheer, vol);
        public void PlayCountdown(float vol = 0.8f) => Play(sfxCountdown, vol);


        public void PlayProceduralBeep(float frequency = 440f, float duration = 0.1f,
            float volume = 0.3f)
        {
            int sampleRate = AudioSettings.outputSampleRate;
            int sampleCount = Mathf.CeilToInt(sampleRate * duration);
            var clip = AudioClip.Create("beep", sampleCount, 1, sampleRate, false);
            float[] data = new float[sampleCount];

            for (int i = 0; i < sampleCount; i++)
            {
                float t = (float)i / sampleRate;
                float envelope = 1f - ((float)i / sampleCount);
                data[i] = Mathf.Sin(2f * Mathf.PI * frequency * t) * envelope * volume;
            }

            clip.SetData(data, 0);
            var src = GetSource();
            src.pitch = 1f;
            src.volume = masterVolume;
            src.PlayOneShot(clip);
        }

        public void PlayCorrectBeep()  => PlayProceduralBeep(880f, 0.15f, 0.25f);
        public void PlayWrongBeep()     => PlayProceduralBeep(220f, 0.3f, 0.25f);
        public void PlayClickBeep()     => PlayProceduralBeep(660f, 0.05f, 0.15f);
        public void PlaySuccessJingle()
        {

            PlayProceduralBeep(523f, 0.12f, 0.2f);
            StartCoroutine(DelayedBeep(660f, 0.12f, 0.1f));
            StartCoroutine(DelayedBeep(784f, 0.2f, 0.2f));
        }

        public void PlayFailBuzz()
        {
            PlayProceduralBeep(150f, 0.4f, 0.3f);
        }

        private System.Collections.IEnumerator DelayedBeep(float freq, float dur, float delay)
        {
            yield return new WaitForSeconds(delay);
            PlayProceduralBeep(freq, dur, 0.2f);
        }
    }
}
