using System;
using System.Collections.Generic;
using EventsAppQuest.Domain.Enums;
using EventsAppQuest.Domain.Models;

namespace EventsAppQuest.Core
{
    /// <summary>
    /// Estado simples da sessão de apresentação no Quest: proposta, plano MR, dados atuais e índice do passo.
    /// Consumido pela cena Quest para exibir e navegar na apresentação.
    /// </summary>
    public class QuestPresentationSession
    {
        /// <summary>Proposta ativa da qual a apresentação foi montada.</summary>
        public EventProjectProposal Proposal { get; set; }

        /// <summary>Plano de apresentação MR (sequência, hotspots, estados de cena).</summary>
        public ProposalMRPresentationPlan MRPlan { get; set; }

        /// <summary>Passos do roteiro guiado (ordem do plano).</summary>
        public List<ProposalGuidedTourStep> GuidedSteps { get; set; } = new List<ProposalGuidedTourStep>();

        /// <summary>Hotspots visuais da proposta.</summary>
        public List<ProposalVisualHotspot> Hotspots { get; set; } = new List<ProposalVisualHotspot>();

        /// <summary>Estados de cena da proposta.</summary>
        public List<ProposalSceneState> SceneStates { get; set; } = new List<ProposalSceneState>();

        /// <summary>Resumo executivo de decisão (quando a proposta é a recomendada).</summary>
        public ProposalDecisionSummary DecisionSummary { get; set; }

        /// <summary>Resumo da recomendação (quando a proposta é a recomendada).</summary>
        public ProposalRecommendationSummary RecommendationSummary { get; set; }

        /// <summary>Modo de navegação atual (guiado, manual ou foco em hotspot).</summary>
        public QuestPresentationNavigationMode NavigationMode { get; set; } = QuestPresentationNavigationMode.Guided;

        /// <summary>Se true, a apresentação tem dados suficientes e está pronta para exibição.</summary>
        public bool IsPresentationReady { get; set; }

        /// <summary>Status de prontidão do runtime Quest (build, dados, fallback, controles). Preenchido pelo controlador após avaliar.</summary>
        public QuestRuntimeReadinessStatus RuntimeReadiness { get; set; }

        /// <summary>Modo de execução actual (EditorFallback, SimulatedXR, RealXR). Preenchido pelo controlador a partir de IQuestXRRuntimeStatusService.</summary>
        public QuestPresentationRuntimeMode RuntimeMode { get; set; } = QuestPresentationRuntimeMode.EditorFallback;

        /// <summary>Se true, o subsistema XR está activo (headset real).</summary>
        public bool IsXRActive { get; set; }

        /// <summary>Se true, a cena está em fallback (editor ou XR indisponível).</summary>
        public bool IsFallbackActive { get; set; } = true;

        /// <summary>Mensagem breve de inicialização XR (para debug/teste).</summary>
        public string XRInitStatus { get; set; }

        /// <summary>Estado do input XR (disponível, activo, modo, última acção). Preenchido pelo controlador a partir da bridge.</summary>
        public QuestXRInputStatus XRInputStatus { get; set; }

        /// <summary>Último resultado de raycast XR (para HUD/debug). Preenchido quando XR está activo e o raycast é executado.</summary>
        public QuestXRRaycastHitResult LastXRRaycastHit { get; set; }

        /// <summary>Se true, o raycast XR está activo e foi executado no último frame.</summary>
        public bool XRRaycastActive { get; set; }

        /// <summary>Modo de confirmação no alvo (apenas explícita, apenas dwell, ou ambos).</summary>
        public QuestTargetConfirmationMode ConfirmationMode { get; set; } = QuestTargetConfirmationMode.DwellOrExplicit;

        /// <summary>Estado actual de hover/dwell no alvo apontado (preenchido pelo QuestHoverDwellController).</summary>
        public QuestTargetHoverState CurrentHoverState { get; set; }

        /// <summary>Id do último alvo confirmado (por dwell ou explícito) para HUD/debug.</summary>
        public string LastConfirmationTargetId { get; set; }

        /// <summary>Id do alvo detectado bruto (pointer/raycast) para HUD/debug.</summary>
        public string DetectedTargetId { get; set; }

        /// <summary>Id do alvo resolvido final (após stickiness) para HUD e consumo.</summary>
        public string ResolvedTargetId { get; set; }

        /// <summary>Origem do alvo resolvido (FocusFallback, SimulatedPointer, XRRaycast, FutureGaze).</summary>
        public QuestTargetSourceMode ResolvedTargetSourceMode { get; set; }

        /// <summary>Se true, no último frame foi aplicada stickiness (manteve alvo anterior).</summary>
        public bool StickinessAppliedLastFrame { get; set; }

        /// <summary>Modo de aiming actual (FallbackOnly, XRRaycastPreferred, GazeLikePreferred, Hybrid).</summary>
        public QuestAimingMode AimingMode { get; set; } = QuestAimingMode.XRRaycastPreferred;

        /// <summary>Estado do gaze-like aiming (preenchido pelo QuestGazeLikeController).</summary>
        public QuestGazeLikeState GazeLikeState { get; set; }

        /// <summary>Se true, o alvo actual foi obtido via gaze-like estável (não apenas raycast/simulado).</summary>
        public bool CurrentTargetFromGazeLike { get; set; }

        /// <summary>Estado contextual do hotspot actual (aberto/fechado, título, resumo, mensagem comercial).</summary>
        public QuestHotspotContextState CurrentHotspotContext { get; set; }

        /// <summary>Se true, o painel contextual de um hotspot está aberto.</summary>
        public bool HasHotspotContextOpen => CurrentHotspotContext != null && CurrentHotspotContext.IsContextOpen;

        /// <summary>Estado da comparação entre hotspots (esquerda/direita, mensagens, melhor por critério).</summary>
        public QuestHotspotComparisonState CurrentHotspotComparison { get; set; }

        /// <summary>Se true, o painel de comparação entre hotspots está aberto.</summary>
        public bool HasHotspotComparisonOpen => CurrentHotspotComparison != null && CurrentHotspotComparison.IsComparisonOpen;

        /// <summary>Estado do fechamento imersivo (headline, CTA, conclusões).</summary>
        public QuestClosingExperienceState CurrentClosingState { get; set; }

        /// <summary>Se true, o painel de fechamento imersivo está aberto.</summary>
        public bool HasClosingOpen => CurrentClosingState != null && CurrentClosingState.IsClosingOpen;

        /// <summary>Última acção de fechamento executada (ex.: "PrimaryCTA", "SecondaryCTA") para HUD/debug.</summary>
        public string LastClosingAction { get; set; }

        /// <summary>Resultado comercial consolidado da sessão (após CTA ou acções de follow-up).</summary>
        public QuestCommercialOutcome CurrentCommercialOutcome { get; set; }

        /// <summary>Último CTA confirmado (ex.: "PrimaryCTA", "SecondaryCTA") para estado comercial.</summary>
        public string LastConfirmedCTA { get; set; }

        /// <summary>Estado comercial actual da decisão (ExplorationOnly, Interested, NeedsFollowUp, ReadyToAdvance, ReadyToClose).</summary>
        public QuestCommercialDecisionState LastDecisionState { get; set; }

        /// <summary>Payload exportável actual (gerado pelo QuestSessionExportController); null até primeira geração.</summary>
        public QuestSessionExportPayload CurrentExportPayload { get; set; }

        /// <summary>Data/hora da última geração de payload (UTC); null se nunca gerado.</summary>
        public DateTime? LastExportTimestamp { get; set; }

        /// <summary>Início da sessão (UTC); usado para duração estimada no payload.</summary>
        public DateTime? SessionStartedAtUtc { get; set; }

        /// <summary>Número de aberturas do contexto de hotspot (para estatísticas de exportação).</summary>
        public int HotspotContextOpenCount { get; set; }

        /// <summary>Número de aberturas do painel de comparação (para estatísticas de exportação).</summary>
        public int ComparisonOpenCount { get; set; }

        /// <summary>Número de aberturas do painel de fechamento (para estatísticas de exportação).</summary>
        public int ClosingOpenCount { get; set; }

        /// <summary>Número de confirmações de CTA (para estatísticas de exportação).</summary>
        public int CTAConfirmationCount { get; set; }

        /// <summary>Último snapshot salvo localmente (cópia em memória); null se nunca salvou ou após limpar.</summary>
        public QuestSessionLocalSnapshot CurrentLocalSnapshot { get; set; }

        /// <summary>Data/hora da última restauração (UTC); null se nunca restaurou.</summary>
        public DateTime? LastRestoreTimestamp { get; set; }

        /// <summary>Se existe snapshot em storage para restaurar (preenchido pelo QuestSessionLocalPersistenceController antes de Refresh).</summary>
        public bool RestorableSnapshotAvailable { get; set; }

        /// <summary>Relatório final/handoff comercial actual; null se ainda não gerado.</summary>
        public QuestSessionHandoffReport CurrentHandoffReport { get; set; }

        /// <summary>Data/hora da última geração de relatório (UTC); null se nunca gerado.</summary>
        public DateTime? LastHandoffGeneratedAt { get; set; }

        /// <summary>Se true, já foi gerado pelo menos um relatório de handoff nesta sessão.</summary>
        public bool HasGeneratedHandoffReport { get; set; }

        /// <summary>Resumo compartilhável actual da sessão; null se ainda não gerado.</summary>
        public QuestSessionShareableSummary CurrentShareableSummary { get; set; }

        /// <summary>Data/hora da última geração de resumo compartilhável (UTC); null se nunca gerado.</summary>
        public DateTime? LastShareableSummaryGeneratedAt { get; set; }

        /// <summary>Se true, já foi gerado pelo menos um resumo compartilhável nesta sessão.</summary>
        public bool HasShareableSummary { get; set; }

        /// <summary>Avaliação de qualidade/diagnóstico actual da sessão; null até ser calculada.</summary>
        public QuestSessionQualityAssessment CurrentQualityAssessment { get; set; }

        /// <summary>Data/hora da última geração de avaliação de qualidade (UTC); null se nunca calculada.</summary>
        public DateTime? LastQualityAssessmentGeneratedAt { get; set; }

        /// <summary>Se true, já foi calculada pelo menos uma avaliação de qualidade nesta sessão.</summary>
        public bool HasQualityAssessment { get; set; }

        /// <summary>Plano de melhorias actual da sessão; null até ser gerado.</summary>
        public QuestSessionImprovementPlan CurrentImprovementPlan { get; set; }

        /// <summary>Data/hora da última geração do plano de melhorias (UTC); null se nunca gerado.</summary>
        public DateTime? LastImprovementPlanGeneratedAt { get; set; }

        /// <summary>Se true, já foi gerado pelo menos um plano de melhorias nesta sessão.</summary>
        public bool HasImprovementPlan { get; set; }

        /// <summary>Preset de apresentação actual aplicado à sessão; null até aplicar um preset.</summary>
        public QuestPresentationPreset CurrentPresentationPreset { get; set; }

        /// <summary>Data/hora da última aplicação de preset (UTC); null se nunca aplicado.</summary>
        public DateTime? LastAppliedPresentationPresetAt { get; set; }

        /// <summary>Se true, há um preset de apresentação aplicado nesta sessão.</summary>
        public bool HasPresentationPreset { get; set; }

        /// <summary>Estado actual do onboarding; null até ser criado pelo controlador.</summary>
        public QuestPresentationOnboardingState CurrentOnboardingState { get; set; }

        /// <summary>Se true, o utilizador já viu o onboarding nesta sessão (ex.: clicou em iniciar).</summary>
        public bool HasSeenOnboarding { get; set; }

        /// <summary>Se true, o painel de onboarding está aberto (conveniência: CurrentOnboardingState?.IsOnboardingOpen).</summary>
        public bool IsOnboardingOpen => CurrentOnboardingState != null && CurrentOnboardingState.IsOnboardingOpen;

        /// <summary>Índice do passo atual no roteiro guiado (0-based).</summary>
        public int CurrentGuidedStepIndex { get; set; }

        /// <summary>Índice do hotspot atualmente em foco (0-based; -1 se nenhum).</summary>
        public int CurrentHotspotIndex { get; set; } = -1;

        /// <summary>Índice do estado de cena atual (0-based; -1 se nenhum).</summary>
        public int CurrentSceneStateIndex { get; set; } = -1;

        /// <summary>Alvo de foco atual (qual painel está em foco para interação).</summary>
        public QuestPresentationFocusTargetType FocusedTargetType { get; set; } = QuestPresentationFocusTargetType.GuidedStepPanel;

        /// <summary>Se true, o modo de interação por foco está ativo (navegação entre painéis e Activate).</summary>
        public bool IsInteractionModeActive { get; set; }

        /// <summary>Passo atual do tour (conveniência).</summary>
        public ProposalGuidedTourStep CurrentStep =>
            (GuidedSteps != null && CurrentGuidedStepIndex >= 0 && CurrentGuidedStepIndex < GuidedSteps.Count)
                ? GuidedSteps[CurrentGuidedStepIndex]
                : null;

        /// <summary>Hotspot atual (conveniência).</summary>
        public ProposalVisualHotspot CurrentHotspot =>
            (Hotspots != null && CurrentHotspotIndex >= 0 && CurrentHotspotIndex < Hotspots.Count)
                ? Hotspots[CurrentHotspotIndex]
                : null;

        /// <summary>Estado de cena atual (conveniência).</summary>
        public ProposalSceneState CurrentSceneState =>
            (SceneStates != null && CurrentSceneStateIndex >= 0 && CurrentSceneStateIndex < SceneStates.Count)
                ? SceneStates[CurrentSceneStateIndex]
                : null;

        /// <summary>Modo recomendado (do plano MR).</summary>
        public MRPresentationTargetMode Mode => MRPlan?.TargetExperienceMode ?? MRPresentationTargetMode.GuidedSalesTour;

        /// <summary>Total de passos para progresso.</summary>
        public int TotalSteps => GuidedSteps?.Count ?? 0;

        /// <summary>Progresso da apresentação (0 a 1).</summary>
        public float Progress =>
            TotalSteps <= 0 ? 0f : (CurrentGuidedStepIndex + 1) / (float)TotalSteps;
    }
}
