using System.Collections.Generic;
using UnityEngine;
using EventsAppQuest.Core;

namespace EventsAppQuest.Presentation
{
    /// <summary>
    /// Despacho central de comandos de input: roteia para navegação, foco, seleção e apontamento.
    /// Mantém log dos últimos comandos para debug/teste. Preparado para futura integração com input real do Quest.
    /// </summary>
    public class QuestPresentationInputDispatcher : MonoBehaviour, IQuestPresentationInputDispatcher
    {
        private const int DefaultLogSize = 5;

        private QuestPresentationNavigationController _navController;
        private QuestPresentationFocusController _focusController;
        private QuestSelectionController _selectionController;
        private QuestPointerPreparationController _pointerPrepController;
        private QuestSimulatedPointerController _simulatedPointerController;
        private System.Func<QuestPresentationSession> _sessionGetter;
        private QuestHotspotStoryController _storyController;

        private QuestPresentationInputSourceType _currentSource = QuestPresentationInputSourceType.KeyboardFallback;
        private readonly List<QuestPresentationInputCommand> _lastCommands = new List<QuestPresentationInputCommand>();

        public QuestPresentationInputSourceType CurrentSource => _currentSource;

        public void Bind(
            QuestPresentationNavigationController navController,
            QuestPresentationFocusController focusController,
            QuestSelectionController selectionController,
            QuestPointerPreparationController pointerPrepController,
            QuestSimulatedPointerController simulatedPointerController)
        {
            _navController = navController;
            _focusController = focusController;
            _selectionController = selectionController;
            _pointerPrepController = pointerPrepController;
            _simulatedPointerController = simulatedPointerController;
        }

        /// <summary>Opcional: quando a narrativa contextual do hotspot está activa, NextStep/PreviousStep navegam no micro-roteiro.</summary>
        public void BindStory(System.Func<QuestPresentationSession> sessionGetter, QuestHotspotStoryController storyController)
        {
            _sessionGetter = sessionGetter;
            _storyController = storyController;
        }

        public void SetCurrentSource(QuestPresentationInputSourceType source)
        {
            _currentSource = source;
        }

        public bool Dispatch(QuestPresentationInputCommand command)
        {
            if (command == null) return false;

            _currentSource = command.Source;
            LogCommand(command);

            switch (command.CommandType)
            {
                case QuestPresentationInputCommandType.NextFocus:
                    _focusController?.NextFocus();
                    return true;
                case QuestPresentationInputCommandType.PreviousFocus:
                    _focusController?.PreviousFocus();
                    return true;
                case QuestPresentationInputCommandType.ActivateFocus:
                    _focusController?.ActivateFocus();
                    return true;
                case QuestPresentationInputCommandType.ExitFocusMode:
                    _focusController?.ExitFocusMode();
                    return true;
                case QuestPresentationInputCommandType.NextSelectable:
                    _selectionController?.ProcessCommand(QuestInteractionCommand.FromType(QuestInteractionCommandType.NextSelectable));
                    return true;
                case QuestPresentationInputCommandType.PreviousSelectable:
                    _selectionController?.ProcessCommand(QuestInteractionCommand.FromType(QuestInteractionCommandType.PreviousSelectable));
                    return true;
                case QuestPresentationInputCommandType.ConfirmSelection:
                    _selectionController?.ProcessCommand(QuestInteractionCommand.FromType(QuestInteractionCommandType.ConfirmSelection));
                    return true;
                case QuestPresentationInputCommandType.CancelSelection:
                    _selectionController?.ProcessCommand(QuestInteractionCommand.FromType(QuestInteractionCommandType.CancelSelection));
                    return true;
                case QuestPresentationInputCommandType.TogglePointerMode:
                    _simulatedPointerController?.CyclePointerMode();
                    return true;
                case QuestPresentationInputCommandType.ConfirmPointedTarget:
                    if (_pointerPrepController != null && _selectionController != null)
                    {
                        var pointed = _pointerPrepController.GetPointedTarget();
                        if (pointed != null)
                        {
                            _selectionController.ConfirmPointedTarget(pointed);
                            return true;
                        }
                    }
                    _selectionController?.ProcessCommand(QuestInteractionCommand.FromType(QuestInteractionCommandType.ConfirmSelection));
                    return true;
                case QuestPresentationInputCommandType.NextStep:
                    if (_sessionGetter != null && _storyController != null)
                    {
                        var sess = _sessionGetter();
                        if (sess?.CurrentHotspotContext != null && sess.CurrentHotspotContext.IsContextOpen && sess.CurrentHotspotContext.IsStoryActive)
                        {
                            _storyController.NextStep();
                            return true;
                        }
                    }
                    _navController?.NextStep();
                    return true;
                case QuestPresentationInputCommandType.PreviousStep:
                    if (_sessionGetter != null && _storyController != null)
                    {
                        var sess = _sessionGetter();
                        if (sess?.CurrentHotspotContext != null && sess.CurrentHotspotContext.IsContextOpen && sess.CurrentHotspotContext.IsStoryActive)
                        {
                            _storyController.PreviousStep();
                            return true;
                        }
                    }
                    _navController?.PreviousStep();
                    return true;
                case QuestPresentationInputCommandType.NextHotspot:
                    _navController?.NextHotspot();
                    return true;
                case QuestPresentationInputCommandType.PreviousHotspot:
                    _navController?.PreviousHotspot();
                    return true;
                case QuestPresentationInputCommandType.NextSceneState:
                    _navController?.NextSceneState();
                    return true;
                case QuestPresentationInputCommandType.PreviousSceneState:
                    _navController?.PreviousSceneState();
                    return true;
                case QuestPresentationInputCommandType.ToggleNavigationMode:
                    _navController?.ToggleNavigationMode();
                    return true;
                case QuestPresentationInputCommandType.RestartPresentation:
                    _navController?.RestartPresentation();
                    return true;
                default:
                    return false;
            }
        }

        public IReadOnlyList<QuestPresentationInputCommand> GetLastCommands(int maxCount = 5)
        {
            var n = Mathf.Min(maxCount, _lastCommands.Count);
            if (n <= 0) return new List<QuestPresentationInputCommand>();
            var list = new List<QuestPresentationInputCommand>(n);
            for (int i = _lastCommands.Count - 1; i >= 0 && list.Count < n; i--)
                list.Add(_lastCommands[i]);
            return list;
        }

        private void LogCommand(QuestPresentationInputCommand command)
        {
            _lastCommands.Add(command);
            while (_lastCommands.Count > DefaultLogSize)
                _lastCommands.RemoveAt(0);
        }
    }
}
