using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Davanci.Nexus.Editor
{
    // The Nexus splash is mandatory in every game: it ships with DavanciNexus at
    // Assets/DavanciNexus/Scenes/NexusSplash.unity and is kept at build index 0 (enabled),
    // with the game's own first scene moved to index 1, which the splash loads when it ends.
    // Enforced whenever the editor loads or the Build Settings scene list changes, and any build
    // whose scene 0 is something else fails.
    [InitializeOnLoad]
    public static class NexusSplashSceneInstaller
    {
        public const string SplashScenePath = "Assets/DavanciNexus/Scenes/NexusSplash.unity";

        static NexusSplashSceneInstaller()
        {
            // Right away so batch-mode builds (-executeMethod) already read the fixed list; again
            // after load in case the scene was still importing.
            EnsureFirstInBuild();
            EditorApplication.delayCall += EnsureFirstInBuild;
            EditorBuildSettings.sceneListChanged += EnsureFirstInBuild;
        }

        public static bool SplashSceneExists => File.Exists(SplashScenePath);

        public static bool IsSplashFirstInBuild()
        {
            var scenes = EditorBuildSettings.scenes;
            return scenes.Length > 0
                   && scenes[0].enabled
                   && scenes[0].path == SplashScenePath;
        }

        // Puts the splash at index 0 (enabled) in front of the existing scenes. Silent and
        // idempotent, so it is safe on every editor load and scene-list change.
        public static void EnsureFirstInBuild()
        {
            if (!SplashSceneExists || IsSplashFirstInBuild()) return;

            var ordered = new List<EditorBuildSettingsScene>
            {
                new EditorBuildSettingsScene(SplashScenePath, true)
            };

            foreach (var scene in EditorBuildSettings.scenes)
            {
                if (scene.path == SplashScenePath) continue;
                ordered.Add(scene);
            }

            EditorBuildSettings.scenes = ordered.ToArray();
            Debug.Log("[Nexus] Splash scene set as build index 0 (required).");
        }
    }

    // Catches builds that bypass Build Settings (e.g. CI scripts with their own scene list).
    class NexusSplashBuildGuard : IProcessSceneWithReport
    {
        public int callbackOrder => 0;

        public void OnProcessScene(Scene scene, BuildReport report)
        {
            if (!BuildPipeline.isBuildingPlayer || scene.buildIndex != 0) return;
            if (scene.path == NexusSplashSceneInstaller.SplashScenePath) return;

            throw new BuildFailedException(
                $"[Nexus] The Davanci Nexus splash must be the first scene in every build, but scene 0 is " +
                $"'{scene.path}'. Put {NexusSplashSceneInstaller.SplashScenePath} first in the scenes you build " +
                "(your game's first scene becomes index 1; the splash loads it).");
        }
    }
}
