using EventsAppQuest.Application.Services;
using EventsAppQuest.Core;
using UnityEngine;

namespace EventsAppQuest.Presentation
{
    /// <summary>
    /// Ponte opcional para input XR real: tenta ler input de controlador via UnityEngine.XR (reflexão) e despacha comandos.
    /// Mapeamento: trigger → ConfirmSelection, secondary → ToggleNavigationMode, eixo Y → NextStep/PreviousStep.
    /// Se a leitura XR não estiver disponível, mantém fallback; status reflecte disponibilidade real.
    /// </summary>
    public class QuestXRInputBridge : IQuestXRInputBridge
    {
        private IQuestPresentationInputDispatcher _dispatcher;
        private QuestPresentationInputCommandType? _lastXRAction;
        private QuestXRInputMode _activeMode = QuestXRInputMode.None;

        private bool _hasRealXRInputAvailable;
        private bool _lastTrigger;
        private bool _lastSecondary;
        private float _lastAxisY;
        private const float AxisThreshold = 0.5f;

        public QuestXRInputStatus GetStatus()
        {
            var status = new QuestXRInputStatus
            {
                IsXRInputEnabled = true,
                ActiveXRInputMode = _activeMode,
                LastXRAction = _lastXRAction,
                IsBridgeInFallbackOnly = !_hasRealXRInputAvailable
            };

            if (_hasRealXRInputAvailable)
            {
                status.IsXRInputAvailable = true;
                if (_activeMode == QuestXRInputMode.None)
                    status.ActiveXRInputMode = QuestXRInputMode.XRControllerPrimary;
                status.Notes = "XR controlador activo";
            }
            else
            {
                status.IsXRInputAvailable = false;
                status.ActiveXRInputMode = QuestXRInputMode.RuntimeFallback;
                status.Notes = QuestXRInputReader.IsAvailable ? "Sem dispositivos XR" : "XR input real não disponível (fallback activo)";
            }

            return status;
        }

        public void SetDispatcher(IQuestPresentationInputDispatcher dispatcher)
        {
            _dispatcher = dispatcher;
        }

        public bool SubmitXRCommand(QuestPresentationInputCommand command)
        {
            if (command == null || _dispatcher == null)
                return false;

            _lastXRAction = command.CommandType;
            if (command.Source == QuestPresentationInputSourceType.KeyboardFallback ||
                command.Source == QuestPresentationInputSourceType.EditorTest ||
                command.Source == QuestPresentationInputSourceType.SimulatedHeadset)
            {
                command.Source = SourceFromMode(_activeMode);
            }

            _dispatcher.SetCurrentSource(command.Source);
            return _dispatcher.Dispatch(command);
        }

        public void ProcessFrame()
        {
            if (_dispatcher == null) return;

            bool gotInput = QuestXRInputReader.TryReadControllerInput(out bool trigger, out bool secondary, out float axisY);

            if (!gotInput)
            {
                _hasRealXRInputAvailable = false;
                _lastTrigger = false;
                _lastSecondary = false;
                _lastAxisY = 0f;
                return;
            }

            _hasRealXRInputAvailable = true;
            if (_activeMode == QuestXRInputMode.None || _activeMode == QuestXRInputMode.RuntimeFallback)
                _activeMode = QuestXRInputMode.XRControllerPrimary;

            bool triggerDown = trigger && !_lastTrigger;
            bool secondaryDown = secondary && !_lastSecondary;
            bool nextStep = axisY > AxisThreshold && _lastAxisY <= AxisThreshold;
            bool prevStep = axisY < -AxisThreshold && _lastAxisY >= -AxisThreshold;

            if (triggerDown)
                DispatchCommand(QuestPresentationInputCommandType.ConfirmSelection);
            else if (secondaryDown)
                DispatchCommand(QuestPresentationInputCommandType.ToggleNavigationMode);
            else if (nextStep)
                DispatchCommand(QuestPresentationInputCommandType.NextStep);
            else if (prevStep)
                DispatchCommand(QuestPresentationInputCommandType.PreviousStep);

            _lastTrigger = trigger;
            _lastSecondary = secondary;
            _lastAxisY = axisY;
        }

        private void DispatchCommand(QuestPresentationInputCommandType type)
        {
            if (_dispatcher == null) return;
            var cmd = QuestPresentationInputCommand.Create(type, SourceFromMode(_activeMode), null);
            _lastXRAction = type;
            _dispatcher.SetCurrentSource(cmd.Source);
            _dispatcher.Dispatch(cmd);
        }

        public void SetActiveMode(QuestXRInputMode mode)
        {
            _activeMode = mode;
        }

        public static QuestPresentationInputCommandType SuggestedCommandForTrigger => QuestPresentationInputCommandType.ConfirmSelection;

        private static QuestPresentationInputSourceType SourceFromMode(QuestXRInputMode mode)
        {
            switch (mode)
            {
                case QuestXRInputMode.XRControllerPrimary:
                case QuestXRInputMode.XRControllerSecondary:
                    return QuestPresentationInputSourceType.FutureController;
                case QuestXRInputMode.FutureHandTracking:
                    return QuestPresentationInputSourceType.FutureHandTracking;
                case QuestXRInputMode.FutureGaze:
                    return QuestPresentationInputSourceType.FutureGaze;
                default:
                    return QuestPresentationInputSourceType.SimulatedHeadset;
            }
        }
    }
}
