using Minesweeper.Presentation.Views;
using UnityEngine;

namespace Minesweeper.Presentation.Factories
{
    public sealed class MinesweeperScreenBootstrapper
    {
        private const string MainMenuPanelName = "MainMenuPanel";
        private const string BoardGridName = "BoardGrid";
        private const string PausePanelName = "PausePanel";
        private const string ResultPanelName = "ResultPanel";

        public MinesweeperScreenRefs Spawn(
            Transform contentRoot,
            MainMenuView mainMenuPrefab,
            BoardView boardPrefab,
            PauseView pausePrefab,
            ResultView resultPrefab)
        {
            if (contentRoot == null)
            {
                Debug.LogError("Minesweeper screen bootstrap failed: Content root is not assigned.");
                return default;
            }

            if (mainMenuPrefab == null || boardPrefab == null || pausePrefab == null || resultPrefab == null)
            {
                Debug.LogError("Minesweeper screen bootstrap failed: screen prefab references are incomplete.");
                return default;
            }

            ClearContent(contentRoot);

            var mainMenuView = SpawnScreen(mainMenuPrefab, contentRoot, MainMenuPanelName, 0);
            var boardView = SpawnScreen(boardPrefab, contentRoot, BoardGridName, 1);
            var pauseView = SpawnScreen(pausePrefab, contentRoot, PausePanelName, 2);
            var resultView = SpawnScreen(resultPrefab, contentRoot, ResultPanelName, 3);

            if (mainMenuView != null)
            {
                mainMenuView.BindRoot(mainMenuView.gameObject);
            }

            var refs = new MinesweeperScreenRefs(
                mainMenuView,
                boardView,
                pauseView,
                resultView);

            mainMenuView.gameObject.SetActive(false);
            boardView.gameObject.SetActive(false);
            pauseView.gameObject.SetActive(false);
            resultView.gameObject.SetActive(false);

            return refs;
        }

        private static T SpawnScreen<T>(T prefab, Transform parent, string expectedName, int siblingIndex) where T : Component
        {
            var instance = Object.Instantiate(prefab, parent, false);
            instance.gameObject.name = expectedName;
            instance.transform.SetSiblingIndex(siblingIndex);
            Stretch(instance.GetComponent<RectTransform>());
            return instance;
        }

        private static void ClearContent(Transform contentRoot)
        {
            for (var i = contentRoot.childCount - 1; i >= 0; i--)
            {
                var child = contentRoot.GetChild(i);
                child.SetParent(null, false);
                Object.Destroy(child.gameObject);
            }
        }

        private static void Stretch(RectTransform rectTransform)
        {
            if (rectTransform == null)
            {
                return;
            }

            rectTransform.anchorMin = Vector2.zero;
            rectTransform.anchorMax = Vector2.one;
            rectTransform.offsetMin = Vector2.zero;
            rectTransform.offsetMax = Vector2.zero;
        }
    }
}
