using Minesweeper.Commands;
using Minesweeper.Config;
using Minesweeper.Core;
using Minesweeper.ECS;
using Minesweeper.Presentation.Adapters;
using Minesweeper.Presentation.Factories;
using Minesweeper.Presentation.Presenters;
using Minesweeper.Presentation.ReadModels;
using Minesweeper.Presentation.Views;
using UnityEngine;
using VContainer;
using VContainer.Unity;

namespace Minesweeper.Infrastructure
{
    public sealed class MinesweeperLifetimeScope : LifetimeScope
    {
        [SerializeField] private MinesweeperGameConfig gameConfig;
        [SerializeField] private MinesweeperUiConfig uiConfig;
        [SerializeField] private Transform contentRoot;
        [SerializeField] private TopPanelView topPanelView;
        [SerializeField] private MainMenuView mainMenuViewPrefab;
        [SerializeField] private BoardView boardViewPrefab;
        [SerializeField] private PauseView pauseViewPrefab;
        [SerializeField] private ResultView resultViewPrefab;

        protected override void Configure(IContainerBuilder builder)
        {
            builder.RegisterInstance(GetConfig());
            var resolvedUiConfig = GetUiConfig();
            builder.RegisterInstance(resolvedUiConfig);
            builder.Register<PlayerPrefsGameSettingsStorage>(Lifetime.Singleton).As<IGameSettingsStorage>();
            builder.Register<GameSettingsService>(Lifetime.Singleton).As<IGameSettingsService>();
            builder.Register<GameStateService>(Lifetime.Singleton).As<IGameStateService>();
            builder.Register<BoardService>(Lifetime.Singleton).As<IBoardService>();
            builder.Register<GamePauseService>(Lifetime.Singleton).As<IGamePauseService>();
            builder.Register<GameTimerService>(Lifetime.Singleton).As<IGameTimerService>().As<ITickable>();
            builder.Register<BoardEcsSyncService>(Lifetime.Singleton).As<IBoardEcsSyncService>();
            builder.Register<GameReadModel>(Lifetime.Singleton).As<IGameReadModel>();
            builder.Register<GameStateViewAdapter>(Lifetime.Singleton).As<IGameStateViewAdapter>();
            builder.Register<CellViewFactory>(Lifetime.Singleton).As<ICellViewFactory>();

            var screenRefs = SpawnScreens();

            if (topPanelView != null)
            {
                topPanelView.BindConfig(resolvedUiConfig);
                builder.RegisterComponent(topPanelView).As<ITopPanelView>();
            }
            else
            {
                builder.Register<NullTopPanelView>(Lifetime.Singleton).As<ITopPanelView>();
            }

            if (screenRefs.MainMenuView != null)
            {
                builder.RegisterComponent(screenRefs.MainMenuView).As<IMainMenuView>();
            }
            else
            {
                builder.Register<NullMainMenuView>(Lifetime.Singleton).As<IMainMenuView>();
            }

            if (screenRefs.BoardView != null)
            {
                screenRefs.BoardView.BindConfig(resolvedUiConfig);
                builder.RegisterComponent(screenRefs.BoardView).As<IBoardView>();
            }
            else
            {
                builder.Register<NullBoardView>(Lifetime.Singleton).As<IBoardView>();
            }

            if (screenRefs.PauseView != null)
            {
                builder.RegisterComponent(screenRefs.PauseView).As<IPauseView>();
            }
            else
            {
                builder.Register<NullPauseView>(Lifetime.Singleton).As<IPauseView>();
            }

            if (screenRefs.ResultView != null)
            {
                builder.RegisterComponent(screenRefs.ResultView).As<IResultView>();
            }
            else
            {
                builder.Register<NullResultView>(Lifetime.Singleton).As<IResultView>();
            }

            builder.Register<SelectFieldCommandHandler>(Lifetime.Singleton);
            builder.Register<StartGameCommandHandler>(Lifetime.Singleton);
            builder.Register<OpenCellCommandHandler>(Lifetime.Singleton);
            builder.Register<ToggleFlagCommandHandler>(Lifetime.Singleton);
            builder.Register<RestartCommandHandler>(Lifetime.Singleton);
            builder.Register<PauseCommandHandler>(Lifetime.Singleton);
            builder.Register<ResumeCommandHandler>(Lifetime.Singleton);
            builder.Register<GoToMenuCommandHandler>(Lifetime.Singleton);
            builder.Register<GameCommandDispatcher>(Lifetime.Singleton).As<IGameCommandDispatcher>();

            builder.Register<MainMenuPresenter>(Lifetime.Singleton);
            builder.Register<TopPanelPresenter>(Lifetime.Singleton);
            builder.Register<GamePresenter>(Lifetime.Singleton);
            builder.RegisterEntryPoint<MinesweeperEntryPoint>();
        }

        private MinesweeperGameConfig GetConfig()
        {
            if (gameConfig != null)
            {
                return gameConfig;
            }

            return ScriptableObject.CreateInstance<MinesweeperGameConfig>();
        }

        private MinesweeperUiConfig GetUiConfig()
        {
            if (uiConfig != null)
            {
                return uiConfig;
            }

            return ScriptableObject.CreateInstance<MinesweeperUiConfig>();
        }

        private MinesweeperScreenRefs SpawnScreens()
        {
            return new MinesweeperScreenBootstrapper().Spawn(
                contentRoot,
                mainMenuViewPrefab,
                boardViewPrefab,
                pauseViewPrefab,
                resultViewPrefab);
        }
    }
}
