using FlappyBird.Bird;
using FlappyBird.Core;
using FlappyBird.Environment;
using FlappyBird.Ground;
using FlappyBird.Pipes;
using FlappyBird.UI;
using UnityEngine;
using Zenject;

namespace FlappyBird.Installers
{
    /// <summary>
    /// Core Zenject installer for the game scene.
    /// Handles binding of all game services, settings, and prefabs.
    /// </summary>
    public class GameInstaller : MonoInstaller
    {
        [Header("Bird")]
        [SerializeField] private BirdSettings birdSettings;
        [SerializeField] private BirdView birdPrefab;

        [Header("Pipes")]
        [SerializeField] private PipeSettings pipeSettings;
        [SerializeField] private GameObject pipePairPrefab;

        [Header("Environment")]
        [SerializeField] private GroundSettings groundSettings;
        [SerializeField] private GameObject groundPrefab;

        [Header("UI & Effects")]
        [SerializeField] private GameUIView gameUIPrefab;
        [SerializeField] private GameObject scorePopupPrefab;

        public override void InstallBindings()
        {
            InstallCore();
            InstallEnvironment();
            InstallBird();
            InstallPipes();
            InstallScoring();
            InstallUI();
        }

        private void InstallCore()
        {
            Container.BindInterfacesTo<GameManager>().AsSingle();
            Container.BindInterfacesTo<DeathManager>().AsSingle();

            // Generic ObjectPoolManager handles all IPoolable types
            Container.BindInterfacesTo<ObjectPoolManager>().AsSingle().NonLazy();
        }

        private void InstallEnvironment()
        {
            Container.BindInstance(groundSettings).AsSingle();

            Container.Bind<GameObject>()
                .WithId("GroundPrefab")
                .FromInstance(groundPrefab)
                .AsCached();

            Container.BindInterfacesTo<GroundSpawner>()
                .AsSingle()
                .NonLazy();
        }

        private void InstallPipes()
        {
            Container.BindInstance(pipeSettings).AsSingle();

            Container.Bind<GameObject>()
                .WithId("PipePrefab")
                .FromInstance(pipePairPrefab)
                .AsCached();

            Container.BindInterfacesTo<PipeSpawner>()
                .AsSingle()
                .NonLazy();
        }

        private void InstallBird()
        {
            Container.BindInstance(birdSettings).AsSingle();

            Container.Bind<BirdView>()
                .FromComponentInNewPrefab(birdPrefab)
                .AsSingle()
                .NonLazy();

            Container.BindInterfacesTo<BirdController>()
                .AsSingle()
                .NonLazy();
        }

        private void InstallScoring()
        {
            Container.BindInterfacesTo<PlayerPrefsStorage>().AsSingle();
            Container.BindInterfacesTo<ScoreManager>().AsSingle().NonLazy();
        }

        private void InstallUI()
        {
            // Binds the +1 popup prefab so GameUIController can resolve it
            Container.Bind<GameObject>()
                .WithId("ScorePopupPrefab")
                .FromInstance(scorePopupPrefab)
                .AsCached();

            Container.Bind<GameUIView>()
                .FromComponentInNewPrefab(gameUIPrefab)
                .AsSingle()
                .NonLazy();

            Container.BindInterfacesTo<GameUIController>()
                .AsSingle()
                .NonLazy();
        }
    }
}