using System.IO;
using eagle;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;

namespace eagle0.Tests {
    [TestFixture]
    public class WeatherEffectMaterialTests {
        private const string BlizzardEffectPrefabPath =
                "Assets/Eagle/Effects/BlizzardEffect.prefab";
        private const string FloodEffectPrefabPath = "Assets/Eagle/Effects/FloodEffect.prefab";
        private const string ProvinceParticleMaterialPath =
                "Assets/Eagle/Effects/ProvinceParticleMaterial.mat";
        private const string ProvinceParticleShaderName = "Eagle/ProvinceParticle";

        [Test]
        public void BlizzardEffectUsesSerializedProvinceParticleMaterial() {
            var effect = LoadPrefabComponent<BlizzardEffect>(BlizzardEffectPrefabPath);
            AssertUsesProvinceParticleMaterial(effect.particleMaterial);
        }

        [Test]
        public void FloodEffectUsesSerializedProvinceParticleMaterial() {
            var effect = LoadPrefabComponent<FloodEffect>(FloodEffectPrefabPath);
            AssertUsesProvinceParticleMaterial(effect.particleMaterial);
        }

        [Test]
        public void WeatherEffectRuntimeCodeDoesNotFindProjectShadersByName() {
            AssertShaderFindIsNotUsed("Assets/Eagle/BlizzardEffect.cs");
            AssertShaderFindIsNotUsed("Assets/Eagle/FloodEffect.cs");
        }

        private static T LoadPrefabComponent<T>(string prefabPath)
                where T : Component {
            var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
            Assert.NotNull(prefab, $"{prefabPath} must exist.");

            var component = prefab.GetComponent<T>();
            Assert.NotNull(component, $"{prefabPath} must include {typeof(T).Name}.");
            return component;
        }

        private static void AssertUsesProvinceParticleMaterial(Material material) {
            var expectedMaterial =
                    AssetDatabase.LoadAssetAtPath<Material>(ProvinceParticleMaterialPath);
            Assert.NotNull(expectedMaterial, $"{ProvinceParticleMaterialPath} must exist.");
            Assert.AreSame(
                    expectedMaterial,
                    material,
                    "Weather effects should serialize the shared province particle material.");
            Assert.NotNull(material.shader, "Province particle material must have a shader.");
            Assert.AreEqual(
                    ProvinceParticleShaderName,
                    material.shader.name,
                    "Weather effects should use the project-owned URP province particle shader.");
        }

        private static void AssertShaderFindIsNotUsed(string scriptPath) {
            StringAssert.DoesNotContain(
                    "Shader.Find",
                    File.ReadAllText(scriptPath),
                    $"{scriptPath} should use serialized particleMaterial instead of shader-name fallback.");
        }
    }
}
