using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using System.Collections;

namespace DayNightCycle
{
    public class LightingManagerTestsPlayMode
    {
        private LightingManager lightingManager;
        private LightingPreset lightingPreset;

        private GameObject _testGameObject;
        private Light _testLight;
        private AutomaticLight _testAutomaticLight;

        [UnitySetUp]
        public IEnumerator Setup()
        {
            GameObject lightingManagerGameObject = new GameObject("LightingManager");
            lightingManager = lightingManagerGameObject.AddComponent<LightingManager>();

            lightingPreset = ScriptableObject.CreateInstance<LightingPreset>();

            lightingManager.SetDirectionalLightSun(new GameObject("DirectionalLight").AddComponent<Light>());
            lightingManager.SetLightingPreset(lightingPreset);
            lightingManager.SetAmbientMode(UnityEngine.Rendering.AmbientMode.Flat);
            lightingManager.SetUseFog(false);

            _testGameObject = new GameObject("TestLightObject");
            _testLight = _testGameObject.AddComponent<Light>();
            _testAutomaticLight = _testGameObject.AddComponent<AutomaticLight>();

            // Wait for one frame to ensure everything is set up properly
            yield return null;
        }

        [UnityTearDown]
        public IEnumerator Teardown()
        {
            Object.DestroyImmediate(lightingManager.gameObject);
            Object.DestroyImmediate(lightingManager.GetDirectionalLightSun().gameObject);
            Object.DestroyImmediate(lightingPreset);

            Object.DestroyImmediate(_testGameObject);

            // Wait for one frame to ensure everything is destroyed properly
            yield return null;
        }

        [UnityTest]
        public IEnumerator LightingManager_TimeOfDayUpdates()
        {
            float initialTimeOfDay = lightingManager.GetTimeOfDay();

            // Wait for 0.1 seconds
            yield return new WaitForSeconds(0.1f);

            float updatedTimeOfDay = lightingManager.GetTimeOfDay();

            Assert.Greater(updatedTimeOfDay, initialTimeOfDay);
        }

        private bool _eventTriggered = false;

        private void HourPassedEventHandler(object sender, LightingManager.HourPassedEventArgs e)
        {
            _eventTriggered = true;
        }

        [UnityTest]
        public IEnumerator LightingManager_HourPassedEvent()
        {
            LightingManager.HourPassed += HourPassedEventHandler;

            float initialTimeOfDay = lightingManager.GetTimeOfDay();
            while (!_eventTriggered)
            {
                // Wait for 0.1 seconds
                yield return new WaitForSeconds(0.1f);
            }

            LightingManager.HourPassed -= HourPassedEventHandler;

            Assert.IsTrue(_eventTriggered);
        }

        [UnityTest]
        public IEnumerator LightingManager_CurrentDayIncrements()
        {
            int initialDay = lightingManager.CurrentDay;
            while (lightingManager.CurrentDay == initialDay)
            {
                // Wait for 0.1 seconds
                yield return new WaitForSeconds(0.1f);
            }

            Assert.AreEqual(initialDay + 1, lightingManager.CurrentDay);
        }

        [UnityTest]
        public IEnumerator UpdateLightState_EnablesLightAtNight_DisablesLightAtDay()
        {
            _testAutomaticLight.StartHour = 18;
            _testAutomaticLight.EndHour = 6;

            lightingManager.SetTimeOfDay(20.0f);

            // Wait for 0.1 seconds
            yield return new WaitForSeconds(0.1f);

            Assert.IsTrue(_testLight.enabled);

            lightingManager.SetTimeOfDay(8);

            // Wait for 0.1 seconds
            yield return new WaitForSeconds(0.1f);

            Assert.IsFalse(_testLight.enabled);
        }
    }

}