// ==============================================
// AudioManager.cs - Audio-Verwaltung
// ==============================================
// Verwaltet Musik, Sound-Effekte und
// Text-to-Speech fuer das Spiel.

using System.Collections.Generic;
using UnityEngine;

namespace BreakpilotDrive
{
    [System.Serializable]
    public class SoundEffect
    {
        public string name;
        public AudioClip clip;
        [Range(0f, 1f)]
        public float volume = 1f;
        [Range(0.5f, 1.5f)]
        public float pitch = 1f;
        public bool loop = false;
    }

    public class AudioManager : MonoBehaviour
    {
        public static AudioManager Instance { get; private set; }

        [Header("Audio Sources")]
        [SerializeField] private AudioSource musicSource;
        [SerializeField] private AudioSource sfxSource;
        [SerializeField] private AudioSource voiceSource;

        [Header("Musik")]
        [SerializeField] private AudioClip menuMusic;
        [SerializeField] private AudioClip gameMusic;

        [Header("Sound-Effekte")]
        [SerializeField] private SoundEffect[] soundEffects;

        [Header("Lautstaerke")]
        [Range(0f, 1f)]
        [SerializeField] private float masterVolume = 1f;
        [Range(0f, 1f)]
        [SerializeField] private float musicVolume = 0.5f;
        [Range(0f, 1f)]
        [SerializeField] private float sfxVolume = 1f;
        [Range(0f, 1f)]
        [SerializeField] private float voiceVolume = 1f;

        // Sound-Dictionary fuer schnellen Zugriff
        private Dictionary<string, SoundEffect> soundDict = new Dictionary<string, SoundEffect>();

        void Awake()
        {
            if (Instance == null)
            {
                Instance = this;
                DontDestroyOnLoad(gameObject);
                InitializeSounds();
                LoadVolumeSettings();
            }
            else
            {
                Destroy(gameObject);
            }
        }

        private void InitializeSounds()
        {
            soundDict.Clear();
            foreach (var sound in soundEffects)
            {
                if (!string.IsNullOrEmpty(sound.name) && sound.clip != null)
                {
                    soundDict[sound.name.ToLower()] = sound;
                }
            }
        }

        // ==============================================
        // Musik
        // ==============================================
        public void PlayMenuMusic()
        {
            PlayMusic(menuMusic);
        }

        public void PlayGameMusic()
        {
            PlayMusic(gameMusic);
        }

        public void PlayMusic(AudioClip clip)
        {
            if (musicSource == null || clip == null) return;

            if (musicSource.clip == clip && musicSource.isPlaying)
                return;

            musicSource.clip = clip;
            musicSource.volume = musicVolume * masterVolume;
            musicSource.loop = true;
            musicSource.Play();
        }

        public void StopMusic()
        {
            if (musicSource != null)
            {
                musicSource.Stop();
            }
        }

        public void PauseMusic()
        {
            if (musicSource != null)
            {
                musicSource.Pause();
            }
        }

        public void ResumeMusic()
        {
            if (musicSource != null)
            {
                musicSource.UnPause();
            }
        }

        // ==============================================
        // Sound-Effekte
        // ==============================================
        public void PlaySound(string soundName)
        {
            if (sfxSource == null) return;

            string key = soundName.ToLower();
            if (soundDict.TryGetValue(key, out SoundEffect sound))
            {
                sfxSource.pitch = sound.pitch;
                sfxSource.PlayOneShot(sound.clip, sound.volume * sfxVolume * masterVolume);
            }
            else
            {
                Debug.LogWarning($"Sound '{soundName}' nicht gefunden!");
            }
        }

        public void PlaySound(AudioClip clip, float volume = 1f)
        {
            if (sfxSource == null || clip == null) return;
            sfxSource.PlayOneShot(clip, volume * sfxVolume * masterVolume);
        }

        // Vordefinierte Sound-Methoden
        public void PlayCoinSound() => PlaySound("coin");
        public void PlayCrashSound() => PlaySound("crash");
        public void PlayCorrectSound() => PlaySound("correct");
        public void PlayWrongSound() => PlaySound("wrong");
        public void PlayButtonSound() => PlaySound("button");

        // ==============================================
        // Text-to-Speech (WebGL)
        // ==============================================
        public void Speak(string text)
        {
            if (string.IsNullOrEmpty(text)) return;

            #if UNITY_WEBGL && !UNITY_EDITOR
            SpeakWebGL(text);
            #else
            Debug.Log($"[TTS] {text}");
            #endif
        }

        public void SpeakQuestion(QuizQuestion question)
        {
            if (question == null) return;

            Speak(question.question_text);

            // Optionen vorlesen (mit Verzoegerung)
            for (int i = 0; i < question.options.Length; i++)
            {
                string optionText = $"Option {i + 1}: {question.options[i]}";
                // In WebGL: Verzoegerung ueber JavaScript
                #if UNITY_WEBGL && !UNITY_EDITOR
                SpeakDelayedWebGL(optionText, 1.5f + (i * 1.5f));
                #else
                Debug.Log($"[TTS] {optionText}");
                #endif
            }
        }

        public void SpeakFeedback(bool correct)
        {
            string message = correct ?
                "Richtig! Gut gemacht!" :
                "Nicht ganz. Versuch es nochmal!";
            Speak(message);
        }

        public void StopSpeaking()
        {
            #if UNITY_WEBGL && !UNITY_EDITOR
            StopSpeakingWebGL();
            #endif
        }

        // WebGL JavaScript Interop
        #if UNITY_WEBGL && !UNITY_EDITOR
        [System.Runtime.InteropServices.DllImport("__Internal")]
        private static extern void SpeakWebGL(string text);

        [System.Runtime.InteropServices.DllImport("__Internal")]
        private static extern void SpeakDelayedWebGL(string text, float delaySeconds);

        [System.Runtime.InteropServices.DllImport("__Internal")]
        private static extern void StopSpeakingWebGL();
        #endif

        // ==============================================
        // Lautstaerke-Einstellungen
        // ==============================================
        public void SetMasterVolume(float volume)
        {
            masterVolume = Mathf.Clamp01(volume);
            UpdateAllVolumes();
            SaveVolumeSettings();
        }

        public void SetMusicVolume(float volume)
        {
            musicVolume = Mathf.Clamp01(volume);
            if (musicSource != null)
            {
                musicSource.volume = musicVolume * masterVolume;
            }
            SaveVolumeSettings();
        }

        public void SetSFXVolume(float volume)
        {
            sfxVolume = Mathf.Clamp01(volume);
            SaveVolumeSettings();
        }

        public void SetVoiceVolume(float volume)
        {
            voiceVolume = Mathf.Clamp01(volume);
            if (voiceSource != null)
            {
                voiceSource.volume = voiceVolume * masterVolume;
            }
            SaveVolumeSettings();
        }

        private void UpdateAllVolumes()
        {
            if (musicSource != null)
                musicSource.volume = musicVolume * masterVolume;
            if (voiceSource != null)
                voiceSource.volume = voiceVolume * masterVolume;
        }

        private void SaveVolumeSettings()
        {
            PlayerPrefs.SetFloat("MasterVolume", masterVolume);
            PlayerPrefs.SetFloat("MusicVolume", musicVolume);
            PlayerPrefs.SetFloat("SFXVolume", sfxVolume);
            PlayerPrefs.SetFloat("VoiceVolume", voiceVolume);
            PlayerPrefs.Save();
        }

        private void LoadVolumeSettings()
        {
            masterVolume = PlayerPrefs.GetFloat("MasterVolume", 1f);
            musicVolume = PlayerPrefs.GetFloat("MusicVolume", 0.5f);
            sfxVolume = PlayerPrefs.GetFloat("SFXVolume", 1f);
            voiceVolume = PlayerPrefs.GetFloat("VoiceVolume", 1f);
            UpdateAllVolumes();
        }

        // Properties fuer UI-Sliders
        public float MasterVolume => masterVolume;
        public float MusicVolume => musicVolume;
        public float SFXVolume => sfxVolume;
        public float VoiceVolume => voiceVolume;
    }
}
