import { useState, useEffect, useCallback, useRef, lazy, Suspense } from 'react';
import { useNavigate } from 'react-router-dom';
import { Loader2, Sparkles } from 'lucide-react';
// Static components for CSS-first rendering (no framer-motion dependency)
import { QuizQuestionStatic } from '@/components/quiz/QuizQuestionStatic';
import { QuizProgressStatic } from '@/components/quiz/QuizProgressStatic';
import { QuizAnimationWrapper } from '@/components/quiz/QuizAnimationWrapper';
import { QUIZ_QUESTIONS } from '@/data/quiz-questions';
import { useQuizTracking } from '@/hooks/use-quiz-tracking';
import { useQuizPreload } from '@/hooks/use-quiz-preload';
import { useShouldReduceAnimations } from '@/hooks/use-reduced-motion';
import { useIsMetaInAppBrowser } from '@/hooks/use-inapp-browser-detection';
import { usePageTracking } from '@/hooks/use-page-tracking';
import { getUTMParams } from '@/lib/gtm';
import { getValuePill, MAX_PILLS_PER_SESSION } from '@/config/quizValuePills';
import { getFeatureShowcaseForStep } from '@/config/quizFeatureShowcases';
import { INTRO_VARIANTS } from '@/config/quizIntroVariants';
import { useQuizHeadlineVariant } from '@/hooks/use-quiz-headline-variant';
import { setGlobalEventContext, trackAnalyticsEvent } from '@/lib/analytics-tracker';
import type { ValuePill } from '@/config/quizValuePills';
import type { FeatureShowcase } from '@/config/quizFeatureShowcases';
import {
  startQuiz,
  answerQuizStep,
  completeQuiz,
  trackPhase3Event,
  requestGuide,
  getQuizSessionId,
  getStoredQuizLeadId,
  storeQuizLeadId,
  getStoredQuizProgress,
  storeQuizProgress,
  clearQuizSession,
  QuizPhase,
} from '@/lib/quiz-api';
import logoWhite from '@/assets/logo-hybrid-full-white.svg';
import SeoHead from '@/components/seo/SeoHead';

// Lazy-loaded components for code splitting (loaded after first question)
const QuizResultPhase2 = lazy(() => import('@/components/quiz/QuizResultPhase2').then(m => ({ default: m.QuizResultPhase2 })));
const QuizAuthority = lazy(() => import('@/components/quiz/QuizAuthority').then(m => ({ default: m.QuizAuthority })));
const QuizCommitment = lazy(() => import('@/components/quiz/QuizCommitment').then(m => ({ default: m.QuizCommitment })));
const QuizObjections = lazy(() => import('@/components/quiz/QuizObjections').then(m => ({ default: m.QuizObjections })));
const QuizFeatureShowcase = lazy(() => import('@/components/quiz/QuizFeatureShowcase').then(m => ({ default: m.QuizFeatureShowcase })));
// QuizLoadingWithCases é eager para evitar tela em branco entre o submit do quiz e a prova social.
import { QuizLoadingWithCases } from '@/components/quiz/QuizLoadingWithCases';
const QuizGuideOptin = lazy(() => import('@/components/quiz/QuizGuideOptin').then(m => ({ default: m.QuizGuideOptin })));

// Lazy load QuizProgress and QuizQuestion (they import framer-motion).
// We start fetching these chunks at module evaluation time (paralelo ao render
// da intro/Q1) — assim o usuário praticamente nunca cai no fallback do Suspense
// na transição Q1→Q2, evitando flash do skeleton.
const quizQuestionImport = import('@/components/quiz/QuizQuestion');
const quizProgressImport = import('@/components/quiz/QuizProgress');
const QuizProgress = lazy(() => quizProgressImport.then(m => ({ default: m.QuizProgress })));
const QuizQuestion = lazy(() => quizQuestionImport.then(m => ({ default: m.QuizQuestion })));

// Loading fallback for lazy components - with reserved height to prevent CLS
const LazyFallback = () => (
  <div className="flex items-center justify-center p-8 min-h-[400px]">
    <Loader2 className="w-6 h-6 animate-spin text-primary" />
  </div>
);

// Showcase fallback: shell estável, sem animação de skeleton (evita piscada percebida).
// Usa as mesmas dimensões/cores do showcase final para que a transição seja imperceptível
// caso o chunk lazy ainda não tenha resolvido.
const ShowcaseFallback = () => (
  <div className="w-full max-w-lg mx-auto flex flex-col items-center gap-5 px-4">
    <div
      className="rounded-[2.5rem] bg-muted/10 border border-white/5"
      style={{ width: 210, height: 434 }}
    />
    <div className="h-6 w-3/4 bg-muted/10 rounded" />
    <div className="h-4 w-2/3 bg-muted/10 rounded" />
    <div className="h-14 w-full bg-muted/10 rounded-2xl" />
  </div>
);

// Minimal loading fallback for quick transitions - placeholder leve para evitar "tela vazia"
const MinimalFallback = () => (
  <div className="w-full max-w-lg mx-auto space-y-8 animate-pulse">
    <div className="h-8 bg-muted/30 rounded-lg w-3/4 mx-auto" />
    <div className="space-y-3">
      <div className="h-16 bg-muted/20 rounded-xl" />
      <div className="h-16 bg-muted/20 rounded-xl" />
      <div className="h-16 bg-muted/20 rounded-xl" />
    </div>
  </div>
);

interface ProjectionDay {
  day: number;
  label: string;
  description?: string;
}

interface QuizState {
  quizLeadId: string | null;
  currentStep: number;
  answers: Record<string, string>;
  isLoading: boolean;
  currentPhase: QuizPhase;
  result: {
    final_profile: string;
    commitment_level: string;
    recommended_focus: string;
    diagnosis_summary: string;
    projection_payload: { days: ProjectionDay[] };
  } | null;
  commitmentChoice: string | null;
  error: string | null;
  // Value Pills state
  currentPill: ValuePill | null;
  showPill: boolean;
  pillsShownCount: number;
  // Feature Showcase state
  currentFeatureShowcase: FeatureShowcase | null;
  showFeatureShowcase: boolean;
}

export default function QuizFunnelV2() {
  const navigate = useNavigate();
  const shouldReduceAnimations = useShouldReduceAnimations();
  const isInAppBrowser = useIsMetaInAppBrowser();
  const { preloadForStep, preloadInitial, preloadAllCritical, ensureShowcaseReady } = useQuizPreload();
  
  // Force lighter animations in in-app browsers (Instagram/Facebook WebViews)
  const useLightAnimations = shouldReduceAnimations || isInAppBrowser;

  // A/B/C split sticky por device — define qual headline o usuário vê
  const headlineVariant = useQuizHeadlineVariant();
  const introVariant = INTRO_VARIANTS[headlineVariant];

  // Injeta a variante em TODOS os eventos analytics da sessão
  useEffect(() => {
    setGlobalEventContext({ headline_variant: headlineVariant });
  }, [headlineVariant]);

  // Dispara um único evento quando a tela de intro é exibida
  const introViewedRef = useRef(false);
  useEffect(() => {
    if (introViewedRef.current) return;
    introViewedRef.current = true;
    trackAnalyticsEvent({
      eventType: 'page_view',
      eventName: 'quiz_intro_viewed',
      eventData: { headline_variant: headlineVariant },
    });
  }, [headlineVariant]);

  // Tracking de page view para analytics correto
  usePageTracking();
  
  const { 
    trackQuizStarted, 
    trackQuizAnsweredStep, 
    trackQuizCompleted, 
    trackQuizAbandoned,
    trackQuizAuthorityViewed,
    trackQuizCommitmentViewed,
    trackQuizCommitmentSelected,
    trackQuizObjectionsViewed,
    trackQuizPrepayWallCompleted,
    trackQuizValuePillShown,
    trackQuizValuePillDismissed,
    trackQuizGuideOptinViewed,
    trackQuizGuideOptinCompleted,
    trackQuizGuideOptinSkipped,
  } = useQuizTracking();

  // Ref para tracking de tempo da pill
  const pillShownAtRef = useRef<number>(0);
  // Ref para tracking de tempo na tela guide-optin
  const guideOptinShownAtRef = useRef<number>(0);
  // Ref para tracking se a barra de progresso já foi mostrada (evita reiniciar animação)
  const progressBarShownRef = useRef<boolean>(false);
  // Ref para guardar resposta quando quizLeadId ainda não existe (Optimistic UI)
  const pendingAnswerRef = useRef<{ stepKey: string; value: string } | null>(null);
  // Ref para armazenar a Promise do save da última resposta (evita race condition com showcase)
  const lastAnswerSaveRef = useRef<Promise<void> | null>(null);

  // Verificar se há parâmetro de reset na URL - executar antes de inicialização
  const shouldReset = (() => {
    const urlParams = new URLSearchParams(window.location.search);
    if (urlParams.get('reset') === '1') {
      clearQuizSession();
      // Remover APENAS o parâmetro `reset` — preserva variant, UTMs etc.
      urlParams.delete('reset');
      const remaining = urlParams.toString();
      const newUrl = window.location.pathname + (remaining ? `?${remaining}` : '');
      window.history.replaceState({}, '', newUrl);
      return true;
    }
    return false;
  })();

  // Track if motion components are ready (after first interaction)
  const [motionReady, setMotionReady] = useState(false);

  const [state, setState] = useState<QuizState>(() => ({
    quizLeadId: null,
    currentStep: 1, // Start at step 1 immediately for CSS-first rendering
    answers: {},
    isLoading: false, // Not loading - render first question immediately
    currentPhase: 'intro',
    result: null,
    commitmentChoice: null,
    error: null,
    // Value Pills
    currentPill: null,
    showPill: false,
    pillsShownCount: 0,
    // Feature Showcase
    currentFeatureShowcase: null,
    showFeatureShowcase: false,
  }));

  // Track if quiz has been initialized in the background
  const quizInitialized = useRef(false);

  // Inicializar quiz - sempre começa do zero ao carregar a página
  useEffect(() => {
    async function initQuiz() {
      try {
        // SEMPRE limpar sessão anterior e começar do zero
        // Isso garante que recarregar a página ou sair no meio reinicia o quiz
        clearQuizSession();

        // Criar novo quiz
        const sessionId = getQuizSessionId();
        const utmParams = getUTMParams();
        
        const quizLeadId = await startQuiz({
          session_id: sessionId,
          utm_source: utmParams.utm_source,
          utm_medium: utmParams.utm_medium,
          utm_campaign: utmParams.utm_campaign,
          utm_content: utmParams.utm_content,
          utm_term: utmParams.utm_term,
          utm_id: utmParams.utm_id,
          gclid: utmParams.gclid,
          fbclid: utmParams.fbclid,
        });

        storeQuizLeadId(quizLeadId);
        // NÃO disparar `quiz_started` aqui — ele agora dispara apenas no clique
        // do botão "Iniciar" (handleStartQuiz), para representar fielmente
        // a conversão Intro → Iniciou.

        // Preload inicial das imagens do primeiro showcase
        preloadInitial();

        // CRITICAL FIX: Apenas setar quizLeadId, NÃO resetar currentStep
        // Isso evita a race condition onde o usuário já avançou para step 2
        // mas o initQuiz() forçava voltar para step 1
        setState(prev => {
          // Se usuário já interagiu (step > 1 ou tem respostas), manter estado atual
          const userAlreadyInteracted = prev.currentStep > 1 || Object.keys(prev.answers).length > 0;
          
          return {
            ...prev,
            quizLeadId,
            isLoading: false,
            // Manter currentStep e currentPhase se usuário já interagiu
            ...(userAlreadyInteracted ? {} : { currentStep: 1, currentPhase: 'intro' as QuizPhase }),
          };
        });

        // Salvar progresso inicial APENAS se usuário ainda não interagiu
        // Evita sobrescrever progresso do usuário que clicou rápido
        setState(prev => {
          if (prev.currentStep === 1 && Object.keys(prev.answers).length === 0) {
            storeQuizProgress(1, {}, 'intro');
          }
          return prev; // Não altera estado, apenas side-effect condicional
        });
      } catch (error) {
        console.error('Error initializing quiz:', error);
        setState(prev => ({
          ...prev,
          isLoading: false,
          error: 'Erro ao iniciar o quiz. Tente novamente.',
        }));
      }
    }

    initQuiz();
  }, []);

  // Bloquear botão voltar do navegador
  useEffect(() => {
    // Preserva a query string original (?variant=, UTMs, etc.) ao bloquear o "voltar".
    const currentUrl = window.location.pathname + window.location.search;
    const handlePopState = (e: PopStateEvent) => {
      e.preventDefault();
      window.history.pushState(null, '', currentUrl);
    };

    window.history.pushState(null, '', currentUrl);
    window.addEventListener('popstate', handlePopState);

    return () => {
      window.removeEventListener('popstate', handlePopState);
    };
  }, []);

  // Tracking de abandono ao sair da página
  useEffect(() => {
    const handleBeforeUnload = () => {
      if (state.currentPhase === 'questions' && state.currentStep > 0 && state.currentStep <= QUIZ_QUESTIONS.length) {
        const currentQuestion = QUIZ_QUESTIONS[state.currentStep - 1];
        if (currentQuestion) {
          trackQuizAbandoned(currentQuestion.step_key, state.currentStep);
        }
      }
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => window.removeEventListener('beforeunload', handleBeforeUnload);
  }, [state.currentStep, state.currentPhase, trackQuizAbandoned]);

  // Marcar barra de progresso como já mostrada após primeira renderização
  useEffect(() => {
    if (state.currentStep > 0 && !progressBarShownRef.current) {
      progressBarShownRef.current = true;
    }
  }, [state.currentStep]);

  // Preload chunks JS críticos do funil em TODOS os browsers, em background.
  // Garante que step 2, progress bar e showcase já estejam baixados antes do clique.
  useEffect(() => {
    const ric: (cb: () => void) => void =
      typeof window !== 'undefined' && 'requestIdleCallback' in window
        ? (cb) => (window as any).requestIdleCallback(cb, { timeout: 1500 })
        : (cb) => setTimeout(cb, 200);

    ric(() => {
      // QuizQuestion e QuizProgress já são pré-carregados no topo do módulo
      // (paralelo ao render da intro), então aqui só agendamos o resto.
      import('@/components/quiz/QuizFeatureShowcase').catch(() => {});
      import('@/components/quiz/FeatureCarousel').catch(() => {});
      import('@/components/landing/IPhoneMockup').catch(() => {});
    });

    // Em WebView in-app, fazemos preload agressivo de imagens também
    if (isInAppBrowser) {
      preloadAllCritical();
    }
  }, [isInAppBrowser, preloadAllCritical]);
  // Processa a conclusão do quiz - MOVED BEFORE handleSelectAnswer to avoid hoisting issue
  // Refs para sincronizar fim do loading visual com a resposta da API.
  const completionResultRef = useRef<Awaited<ReturnType<typeof completeQuiz>> | null>(null);
  const completionPromiseRef = useRef<Promise<Awaited<ReturnType<typeof completeQuiz>> | null> | null>(null);
  const completionErrorRef = useRef<unknown>(null);

  const finalizeCompletion = useCallback((result: Awaited<ReturnType<typeof completeQuiz>>) => {
    trackQuizCompleted(result.final_profile, result.commitment_level, state.quizLeadId);
    setState(prev => ({
      ...prev,
      isLoading: false,
      currentPhase: 'result',
      result: {
        final_profile: result.final_profile,
        commitment_level: result.commitment_level,
        recommended_focus: result.recommended_focus || 'organization',
        diagnosis_summary: result.diagnosis_summary || '',
        projection_payload: result.projection_payload || { days: [] },
      },
    }));
    // Preload QuizGuideOptin so it's instant when user clicks CTA
    import('@/components/quiz/QuizGuideOptin').catch(() => {});
  }, [state.quizLeadId, trackQuizCompleted]);

  const handleLoadingCasesComplete = useCallback(async () => {
    // Aguarda a Promise da API (se ainda não terminou) e só então transiciona.
    try {
      const result = completionResultRef.current
        ?? (completionPromiseRef.current ? await completionPromiseRef.current : null);
      if (!result) {
        // Erro já tratado em processQuizCompletion
        return;
      }
      finalizeCompletion(result);
      if (state.currentStep) {
        storeQuizProgress(state.currentStep, state.answers, 'result');
      }
    } catch {
      // erro tratado no catch de processQuizCompletion
    }
  }, [finalizeCompletion, state.answers, state.currentStep]);

  const processQuizCompletion = useCallback(async (answers: Record<string, string>) => {
    if (!state.quizLeadId) return;

    // Reset refs e entra na fase de loading visual.
    completionResultRef.current = null;
    completionErrorRef.current = null;

    setState(prev => ({
      ...prev,
      isLoading: true,
      currentPhase: 'loading-diagnosis',
      error: null,
    }));

    // Dispara a API em paralelo. O QuizLoadingWithCases controla o tempo mínimo
    // de exibição (3 cases × 2.5s) e chama onComplete quando termina.
    const apiCall = (async () => {
      const MAX_RETRIES = 2;
      for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
        try {
          const res = await completeQuiz({ quiz_lead_id: state.quizLeadId!, answers });
          completionResultRef.current = res;
          return res;
        } catch (err) {
          if (attempt === MAX_RETRIES) {
            completionErrorRef.current = err;
            console.error('Error completing quiz:', err);
            setState(prev => ({
              ...prev,
              isLoading: false,
              error: 'Não conseguimos gerar seu diagnóstico. Toque para tentar novamente.',
            }));
            return null;
          }
          await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));
        }
      }
      return null;
    })();

    completionPromiseRef.current = apiCall;
    // Não aguardamos aqui — handleLoadingCasesComplete fará a transição.
  }, [state.quizLeadId]);



  // Retry silencioso para garantir persistência da primeira resposta (crítica para cohort)
  const saveAnswerWithRetry = useCallback(async (
    quizLeadId: string,
    stepKey: string,
    answerValue: string,
    maxRetries = 2
  ) => {
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        await answerQuizStep({
          quiz_lead_id: quizLeadId,
          step_key: stepKey,
          answer_value: answerValue,
        });
        return; // Sucesso, sai do loop
      } catch (error) {
        if (attempt === maxRetries) {
          console.error(`Failed to save answer after ${maxRetries + 1} attempts:`, error);
        } else {
          // Backoff exponencial: 500ms, 1000ms
          await new Promise(resolve => setTimeout(resolve, 500 * (attempt + 1)));
        }
      }
    }
  }, []);

  // Processar resposta pendente quando quizLeadId chegar
  // Isso acontece quando o usuário clicou na primeira pergunta antes do initQuiz() terminar
  useEffect(() => {
    if (state.quizLeadId && pendingAnswerRef.current) {
      const { stepKey, value } = pendingAnswerRef.current;
      pendingAnswerRef.current = null;
      
      // Salvar no backend em background com retry (garante persistência do cohort)
      saveAnswerWithRetry(state.quizLeadId, stepKey, value);
    }
  }, [state.quizLeadId, saveAnswerWithRetry]);

  // Handler de seleção de resposta - OPTIMISTIC UI para TODAS as perguntas
  // Step 1: Permite clique mesmo sem quizLeadId (salva em pendingAnswerRef)
  // Steps 2+: Avança imediatamente, salva em background com retry silencioso
  const handleSelectAnswer = useCallback(async (value: string) => {
    // Bloquear apenas se loading, mostrando pill ou showcase
    if (state.isLoading || state.showPill || state.showFeatureShowcase) return;

    const currentQuestion = QUIZ_QUESTIONS[state.currentStep - 1];
    if (!currentQuestion) return;

    const isFirstQuestion = state.currentStep === 1;
    const isLastQuestion = state.currentStep === QUIZ_QUESTIONS.length;

    // === CASO ESPECIAL: Primeira pergunta SEM quizLeadId ===
    // Isso acontece quando o usuário clica antes do initQuiz() terminar
    // Solução: Guardar resposta em pendingAnswerRef e avançar UI imediatamente
    if (isFirstQuestion && !state.quizLeadId) {
      // Guardar resposta para processar quando quizLeadId chegar
      pendingAnswerRef.current = { stepKey: currentQuestion.step_key, value };
      
      // OPTIMISTIC UI: Avança imediatamente (sem esperar backend)
      const newAnswers = { [currentQuestion.step_key]: value };
      
      // Verificar se há Value Pill para esta resposta
      const pill = getValuePill(currentQuestion.step_key, value);
      const shouldShowPill = pill && state.pillsShownCount < MAX_PILLS_PER_SESSION;
      
      // Verificar se há Feature Showcase para este step
      const featureShowcase = getFeatureShowcaseForStep(currentQuestion.step_key);

      if (shouldShowPill && pill) {
        pillShownAtRef.current = Date.now();
        trackQuizValuePillShown(currentQuestion.step_key, value, pill.feature);
        
        setState(prev => ({
          ...prev,
          answers: newAnswers,
          currentPill: pill,
          showPill: true,
          pillsShownCount: prev.pillsShownCount + 1,
          currentFeatureShowcase: featureShowcase,
        }));
      } else if (featureShowcase) {
        // Pré-aquecer chunks + imagem principal antes de trocar a tela.
        await ensureShowcaseReady(currentQuestion.step_key);
        setState(prev => ({
          ...prev,
          answers: newAnswers,
          currentFeatureShowcase: featureShowcase,
          showFeatureShowcase: true,
        }));
      } else {
        // Avançar para step 2 imediatamente
        setState(prev => ({
          ...prev,
          answers: newAnswers,
          currentStep: 2,
        }));
        storeQuizProgress(2, newAnswers, 'questions');
      }

      // Tracking local (não depende do backend)
      trackQuizAnsweredStep(currentQuestion.step_key, value, 1, 'pending');
      preloadForStep(currentQuestion.step_key);
      return;
    }

    // === FLUXO NORMAL: quizLeadId já existe ===
    if (!state.quizLeadId) return;

    // OPTIMISTIC UI: Avança imediatamente, salva em background
    const newAnswers = { ...state.answers, [currentQuestion.step_key]: value };
    
    // Verificar se há Value Pill para esta resposta
    const pill = getValuePill(currentQuestion.step_key, value);
    const shouldShowPill = pill && state.pillsShownCount < MAX_PILLS_PER_SESSION && !isLastQuestion;
    
    // Verificar se há Feature Showcase para este step (APÓS a pill)
    const featureShowcase = getFeatureShowcaseForStep(currentQuestion.step_key);

    if (shouldShowPill && pill) {
      // Mostrar pill antes de avançar - instantâneo
      pillShownAtRef.current = Date.now();
      trackQuizValuePillShown(currentQuestion.step_key, value, pill.feature);
      
      setState(prev => ({
        ...prev,
        answers: newAnswers,
        currentPill: pill,
        showPill: true,
        pillsShownCount: prev.pillsShownCount + 1,
        // Guarda o showcase para mostrar depois da pill
        currentFeatureShowcase: featureShowcase,
      }));
    } else if (featureShowcase && !isLastQuestion) {
      // Mostrar Feature Showcase diretamente (sem pill antes).
      // Aguarda chunk + imagem principal por um tempo curto para evitar piscada.
      await ensureShowcaseReady(currentQuestion.step_key);
      setState(prev => ({
        ...prev,
        answers: newAnswers,
        currentFeatureShowcase: featureShowcase,
        showFeatureShowcase: true,
      }));
    } else if (!isLastQuestion) {
      // Avançar para próxima pergunta IMEDIATAMENTE
      const nextStep = state.currentStep + 1;
      
      setState(prev => ({
        ...prev,
        answers: newAnswers,
        currentStep: nextStep,
      }));

      // Salvar progresso (fire and forget para não bloquear UI)
      storeQuizProgress(nextStep, newAnswers, 'questions');
    } else {
      // Última pergunta - verificar se há showcase final antes do resultado
      if (featureShowcase) {
        // Salvar a Promise do save para aguardar antes do /complete
        lastAnswerSaveRef.current = saveAnswerWithRetry(state.quizLeadId, currentQuestion.step_key, value);
        await ensureShowcaseReady(currentQuestion.step_key);
        setState(prev => ({
          ...prev,
          answers: newAnswers,
          currentFeatureShowcase: featureShowcase,
          showFeatureShowcase: true,
        }));
      } else {
        // Ir direto para resultado
        setState(prev => ({ ...prev, answers: newAnswers, isLoading: true }));
      }
    }

    // Tracking em background (não bloqueia UI)
    trackQuizAnsweredStep(currentQuestion.step_key, value, state.currentStep, state.quizLeadId);
    
    // Preload das imagens do próximo showcase (em background)
    preloadForStep(currentQuestion.step_key);

    // Salvar resposta no backend em background (fire-and-forget)
    if (isFirstQuestion) {
      // Primeira pergunta: usar retry silencioso para garantir persistência do cohort
      saveAnswerWithRetry(state.quizLeadId, currentQuestion.step_key, value);
    } else if (isLastQuestion && !featureShowcase) {
      // Última pergunta sem showcase: aguarda save + processa resultado
      try {
        await answerQuizStep({
          quiz_lead_id: state.quizLeadId,
          step_key: currentQuestion.step_key,
          answer_value: value,
        });
        await processQuizCompletion(newAnswers);
      } catch (error) {
        console.error('Error saving final answer:', error);
        setState(prev => ({
          ...prev,
          isLoading: false,
          error: 'Erro ao salvar resposta. Tente novamente.',
        }));
      }
    } else if (!featureShowcase || !isLastQuestion) {
      // Perguntas 2-11 (e última sem showcase): fire-and-forget simples
      answerQuizStep({
        quiz_lead_id: state.quizLeadId,
        step_key: currentQuestion.step_key,
        answer_value: value,
      }).catch(err => console.error('Error saving answer (silent):', err));
    }
    // Nota: última pergunta COM showcase já salva via lastAnswerSaveRef acima
  }, [state.quizLeadId, state.currentStep, state.answers, state.isLoading, state.showPill, state.showFeatureShowcase, state.pillsShownCount, trackQuizAnsweredStep, trackQuizValuePillShown, preloadForStep, processQuizCompletion, saveAnswerWithRetry, ensureShowcaseReady]);

  // Handler para quando a pill é completada (auto-dismiss ou clique)
  const handlePillComplete = useCallback(async () => {
    const currentQuestion = QUIZ_QUESTIONS[state.currentStep - 1];
    if (currentQuestion && pillShownAtRef.current > 0) {
      const timeViewed = Date.now() - pillShownAtRef.current;
      trackQuizValuePillDismissed(currentQuestion.step_key, timeViewed);
    }

    // Verificar se há Feature Showcase para mostrar após a pill
    if (state.currentFeatureShowcase && currentQuestion) {
      // Pré-aquecer o showcase antes de trocar a tela
      await ensureShowcaseReady(currentQuestion.step_key);
      setState(prev => ({
        ...prev,
        currentPill: null,
        showPill: false,
        showFeatureShowcase: true,
      }));
    } else {
      // Avançar para próxima pergunta
      const nextStep = state.currentStep + 1;

      setState(prev => ({
        ...prev,
        currentStep: nextStep,
        currentPill: null,
        showPill: false,
      }));

      // Salvar progresso
      storeQuizProgress(nextStep, state.answers, 'questions');
    }
  }, [state.currentStep, state.answers, state.currentFeatureShowcase, trackQuizValuePillDismissed, ensureShowcaseReady]);

  // Handler para quando o Feature Showcase é completado
  const handleFeatureShowcaseComplete = useCallback(async () => {
    const isLastQuestion = state.currentStep === QUIZ_QUESTIONS.length;
    
    if (isLastQuestion) {
      // Última pergunta - aguardar save da resposta antes de processar resultado
      setState(prev => ({
        ...prev,
        currentFeatureShowcase: null,
        showFeatureShowcase: false,
        isLoading: true,
      }));
      
      // CRITICAL: Aguardar persistência da última resposta antes de chamar /complete
      if (lastAnswerSaveRef.current) {
        try {
          await lastAnswerSaveRef.current;
        } catch (err) {
          console.error('Error awaiting last answer save:', err);
        }
        lastAnswerSaveRef.current = null;
      }
      
      await processQuizCompletion(state.answers);
    } else {
      // Avançar para próxima pergunta
      const nextStep = state.currentStep + 1;
      
      setState(prev => ({
        ...prev,
        currentStep: nextStep,
        currentFeatureShowcase: null,
        showFeatureShowcase: false,
      }));

      // Salvar progresso
      storeQuizProgress(nextStep, state.answers, 'questions');
    }
  }, [state.currentStep, state.answers, processQuizCompletion]);

  // Handler para avançar da tela de resultado para guide-optin
  const handleResultContinue = useCallback(async () => {
    if (!state.quizLeadId) return;
    
    // Scroll to top on phase change
    window.scrollTo({ top: 0, behavior: 'instant' });
    
    // Track guide optin viewed + start timer
    guideOptinShownAtRef.current = Date.now();
    trackQuizGuideOptinViewed(state.quizLeadId);
    
    setState(prev => ({ ...prev, currentPhase: 'guide-optin' }));
    storeQuizProgress(state.currentStep, state.answers, 'guide-optin');

    // Preload QuizAuthority (próxima tela) — chunk JS + imagens — para
    // garantir transição instantânea quando o usuário clica em receber
    // o guia ou continuar sem guia.
    import('@/components/quiz/QuizAuthority').catch(() => {});
    Promise.all([
      import('@/assets/transformacao-antes-1.jpg'),
      import('@/assets/transformacao-depois-1.jpg'),
      import('@/assets/transformacao-antes-2.jpg'),
      import('@/assets/transformacao-depois-2.jpg'),
      import('@/assets/avatar-nutricionista.png'),
      import('@/assets/avatar-personal.jpg'),
    ]).then((mods) => {
      mods.forEach((m) => {
        const img = new Image();
        img.decoding = 'async';
        img.src = (m as { default: string }).default;
      });
    }).catch(() => {});
  }, [state.quizLeadId, state.currentStep, state.answers, trackQuizGuideOptinViewed]);


  // Handler para quando o usuário solicita o guia
  const handleGuideRequest = useCallback(async (phone: string, name: string) => {
    if (!state.quizLeadId) return;
    
    // Track opt-in completed with time on screen
    const timeOnScreen = Date.now() - guideOptinShownAtRef.current;
    trackQuizGuideOptinCompleted(state.quizLeadId, timeOnScreen);
    
    // Advance user IMMEDIATELY — zero wait time
    handleGuideOptinContinue();
    
    // Fire-and-forget: AI call + PDF generation + webhook entirely in background
    const quizLeadId = state.quizLeadId;
    const resultProfile = state.result?.final_profile;
    const resultFocus = state.result?.recommended_focus;
    
    // Fire-and-forget: server handles PDF generation + webhook entirely
    requestGuide(quizLeadId, phone, name).catch(err => {
      console.error('Background guide generation error:', err);
    });
  }, [state.quizLeadId]);

  // Handler para pular ou continuar após guide-optin
  const handleGuideOptinContinue = useCallback(async () => {
    if (!state.quizLeadId) return;
    
    // Track skip with time on screen
    const timeOnScreen = Date.now() - guideOptinShownAtRef.current;
    trackQuizGuideOptinSkipped(state.quizLeadId, timeOnScreen);
    
    // Scroll to top on phase change
    window.scrollTo({ top: 0, behavior: 'instant' });
    
    setState(prev => ({ ...prev, currentPhase: 'authority', isLoading: false }));
    storeQuizProgress(state.currentStep, state.answers, 'authority');
    
    // Tracking
    trackQuizAuthorityViewed(state.quizLeadId);
    
    // Registrar no backend
    try {
      await trackPhase3Event({
        quiz_lead_id: state.quizLeadId,
        event_type: 'authority_viewed',
      });
    } catch (error) {
      console.error('Error tracking authority viewed:', error);
    }
  }, [state.quizLeadId, state.currentStep, state.answers, trackQuizAuthorityViewed, trackQuizGuideOptinSkipped]);

  // Handler para avançar da autoridade para compromisso
  const handleAuthorityContinue = useCallback(async () => {
    if (!state.quizLeadId) return;
    
    // Scroll to top on phase change
    window.scrollTo({ top: 0, behavior: 'instant' });
    
    setState(prev => ({ ...prev, currentPhase: 'commitment' }));
    storeQuizProgress(state.currentStep, state.answers, 'commitment');
    
    // Tracking
    trackQuizCommitmentViewed(state.quizLeadId);
  }, [state.quizLeadId, state.currentStep, state.answers, trackQuizCommitmentViewed]);

  // Handler para seleção de compromisso
  const handleCommitmentSelect = useCallback(async (choice: 'start_now' | 'see_plans' | 'still_unsure') => {
    if (!state.quizLeadId || !state.result) return;
    
    setState(prev => ({ ...prev, isLoading: true, commitmentChoice: choice }));
    
    // Tracking
    trackQuizCommitmentSelected(choice, state.quizLeadId);
    
    try {
      const response = await trackPhase3Event({
        quiz_lead_id: state.quizLeadId,
        event_type: 'commitment_selected',
        commitment_choice: choice,
      });
      
      const nextPhase = response.next_step === 'objections' ? 'objections' : 'paywall';
      
      if (nextPhase === 'objections') {
        // Tracking de objeções
        trackQuizObjectionsViewed(state.quizLeadId);
        
        // Scroll to top on phase change
        window.scrollTo({ top: 0, behavior: 'instant' });
        
        setState(prev => ({ 
          ...prev, 
          isLoading: false, 
          currentPhase: 'objections',
        }));
        
        storeQuizProgress(state.currentStep, state.answers, 'objections', choice);
      } else {
        // Ir direto para paywall
        setState(prev => ({ ...prev, isLoading: false }));
        await handlePrepayWallComplete(choice);
      }
    } catch (error) {
      console.error('Error tracking commitment:', error);
      setState(prev => ({ ...prev, isLoading: false }));
    }
  }, [state.quizLeadId, state.result, state.currentStep, state.answers, trackQuizCommitmentSelected, trackQuizObjectionsViewed]);

  // Handler para marcar prepaywall como completo e redirecionar
  const handlePrepayWallComplete = useCallback(async (choice?: string) => {
    if (!state.quizLeadId || !state.result) return;
    
    setState(prev => ({ ...prev, isLoading: true }));
    
    try {
      await trackPhase3Event({
        quiz_lead_id: state.quizLeadId,
        event_type: 'prepaywall_completed',
      });
      
      trackQuizPrepayWallCompleted(
        state.quizLeadId, 
        state.result.final_profile, 
        state.result.recommended_focus
      );
      
      // Limpar sessão do quiz
      clearQuizSession();
      
      // Redirecionar para paywall com parâmetros
      const params = new URLSearchParams({
        quiz_lead_id: state.quizLeadId,
        profile: state.result.final_profile,
        focus: state.result.recommended_focus,
        commitment: state.result.commitment_level,
        choice: choice || state.commitmentChoice || 'see_plans',
      });
      
      navigate(`/paywall?${params.toString()}`);
    } catch (error) {
      console.error('Error completing prepaywall:', error);
      setState(prev => ({ ...prev, isLoading: false }));
      // Mesmo com erro, tentar redirecionar
      navigate('/paywall');
    }
  }, [state.quizLeadId, state.result, state.commitmentChoice, navigate, trackQuizPrepayWallCompleted]);

  // Handler para completar fase de objeções e ir para paywall
  const handleObjectionsContinue = useCallback(async () => {
    await handlePrepayWallComplete();
  }, [handlePrepayWallComplete]);

  // Handler para iniciar o quiz a partir da tela intro
  const startTrackedRef = useRef(false);
  const handleStartQuiz = useCallback(() => {
    // Dispara `quiz_started` APENAS no clique do botão (uma vez por sessão).
    // Se o quizLeadId ainda não foi criado (corrida com initQuiz), envia sem ele —
    // o backend já tem o registro via session_id.
    if (!startTrackedRef.current) {
      startTrackedRef.current = true;
      trackQuizStarted(state.quizLeadId || '');
    }
    setState(prev => ({ ...prev, currentPhase: 'questions' }));
    storeQuizProgress(1, {}, 'questions');
  }, [trackQuizStarted, state.quizLeadId]);

  // Retry em caso de erro
  const handleRetry = useCallback(() => {
    clearQuizSession();
    window.location.reload();
  }, []);

  // Renderização condicional
  const currentQuestion = state.currentPhase === 'questions' && state.currentStep > 0 && state.currentStep <= QUIZ_QUESTIONS.length 
    ? QUIZ_QUESTIONS[state.currentStep - 1] 
    : null;

  return (
    <>
      <SeoHead title="Quiz — Monte seu plano híbrido | Hybrid Fit" description="Responda o quiz e receba um plano híbrido personalizado de treino e dieta em minutos." path="/quiz-funnelv2" />
    <div className="min-h-screen bg-background flex flex-col relative overflow-hidden">
      {/* Aurora background effect */}
      <div className="quiz-aurora-bg" />

      {/* Header - Glass effect */}
      <header className="quiz-glass-header w-full px-4 py-4 md:py-5 flex items-center justify-center relative z-10">
        <img 
          src={logoWhite} 
          alt="Hybrid Fit" 
          width={120}
          height={32}
          className="h-8 md:h-9 w-auto opacity-90"
          decoding="async"
        />
      </header>

      {/* Main Content */}
      {/* Main Content */}
      <main className="flex-1 flex flex-col items-center justify-center px-4 py-8 md:py-12 relative z-10">
        {/* Loading inicial */}
        {state.isLoading && state.currentStep === 0 && (
          <div className="flex flex-col items-center gap-4">
            <Loader2 className="w-8 h-8 animate-spin text-primary" />
            <p className="text-muted-foreground">Preparando seu quiz...</p>
          </div>
        )}

        {/* Error state */}
        {state.error && (
          <div className="text-center space-y-4">
            <p className="text-destructive">{state.error}</p>
            {/* Se o erro ocorreu durante o diagnóstico, tentar reprocessar sem perder estado */}
            {state.currentPhase === 'loading-diagnosis' ? (
              <button 
                onClick={() => processQuizCompletion(state.answers)}
                className="px-6 py-2.5 rounded-xl bg-primary text-primary-foreground font-semibold text-sm shadow-lg hover:bg-primary/90 transition-all"
              >
                Tentar novamente
              </button>
            ) : (
              <button 
                onClick={handleRetry}
                className="text-primary hover:underline"
              >
                Tentar novamente
              </button>
            )}
          </div>
        )}

        {/* Tela de introdução - antes das perguntas */}
        {!state.error && state.currentPhase === 'intro' && (
          <div className="w-full max-w-lg space-y-8 text-center quiz-animate-fade-in">
            {/* Badge de confiança */}
            <div className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-primary/10 border border-primary/20 text-xs md:text-sm text-primary font-medium">
              <Sparkles className="w-3.5 h-3.5" />
              <span>Diagnóstico gratuito • 2 min</span>
            </div>
            
            <h1 className="text-2xl md:text-4xl font-bold text-foreground leading-tight tracking-tight">
              {introVariant.headlineBefore}
              <span className="text-gradient">{introVariant.headlineGradient}</span>
              {introVariant.headlineAfter}
            </h1>
            <p className="text-sm md:text-base text-muted-foreground leading-relaxed max-w-md mx-auto">
              {introVariant.subtitle}
            </p>

            <button
              onClick={handleStartQuiz}
              className="w-full max-w-xs mx-auto flex items-center justify-center gap-2 px-8 py-4 rounded-xl bg-primary text-primary-foreground font-semibold text-base md:text-lg shadow-[0_0_24px_-4px_hsl(var(--primary)/0.5)] hover:shadow-[0_0_32px_-4px_hsl(var(--primary)/0.6)] transition-all duration-300 hover:scale-[1.02] active:scale-[0.98]"
            >
              {introVariant.ctaText}
            </button>

            {/* Social proof */}
            <p className="text-xs md:text-sm text-muted-foreground/70 flex items-center justify-center gap-1.5">
              <span className="text-primary/80">✓</span>
              +12.000 diagnósticos realizados
            </p>
          </div>
        )}

        {/* Quiz em andamento - Perguntas */}
        {!state.error && state.currentPhase === 'questions' && currentQuestion && !state.showFeatureShowcase && (
          <div className="w-full max-w-lg space-y-8">
            {/*
              * Single Suspense tree for ALL questions (incluindo a Q1).
              * O fallback usa os componentes Static — visualmente idênticos
              * ao conteúdo final — então mesmo se o chunk lazy não estiver
              * pronto o usuário NÃO vê o skeleton genérico (zero flash).
              * Os chunks são pré-carregados no topo do módulo, então na
              * prática o Suspense praticamente nunca dispara após Q1.
              */}
            <Suspense
              fallback={
                <>
                  <QuizProgressStatic
                    currentStep={state.currentStep}
                    totalSteps={QUIZ_QUESTIONS.length}
                  />
                  <QuizQuestionStatic
                    question={currentQuestion.question}
                    options={currentQuestion.options}
                    selectedValue={state.answers[currentQuestion.step_key] || null}
                    onSelect={handleSelectAnswer}
                    isLoading={state.isLoading}
                  />
                </>
              }
            >
              <QuizProgress
                currentStep={state.currentStep}
                totalSteps={QUIZ_QUESTIONS.length}
                skipInitialAnimation={progressBarShownRef.current}
              />

              <QuizAnimationWrapper
                animationKey={state.currentStep}
                type="slide"
                skipAnimation={useLightAnimations}
                useCSS={isInAppBrowser}
              >
                <QuizQuestion
                  question={currentQuestion.question}
                  options={currentQuestion.options}
                  selectedValue={state.answers[currentQuestion.step_key] || null}
                  onSelect={handleSelectAnswer}
                  isLoading={state.isLoading}
                  valuePill={state.currentPill}
                  showPill={state.showPill}
                  onPillComplete={handlePillComplete}
                />
              </QuizAnimationWrapper>
            </Suspense>

            {/* Loading indicator - only shows on last question */}
            {state.isLoading && state.currentStep === QUIZ_QUESTIONS.length && (
              <div className="flex justify-center quiz-animate-fade-in">
                <div className="flex items-center gap-2 text-muted-foreground">
                  <Loader2 className="w-4 h-4 animate-spin text-primary" />
                  <span className="text-sm">Analisando suas respostas...</span>
                </div>
              </div>
            )}
          </div>
        )}

        {/* Feature Showcase - Mini Landing Page - Reserved height to prevent CLS */}
        {!state.error && state.currentPhase === 'questions' && state.showFeatureShowcase && state.currentFeatureShowcase && (
          <div className="w-full max-w-lg space-y-6 min-h-[600px]">
            {/* Progress bar + label contextual */}
            <div className="space-y-1.5">
              <Suspense fallback={<MinimalFallback />}>
                <QuizProgress 
                  currentStep={state.currentStep} 
                  totalSteps={QUIZ_QUESTIONS.length}
                  skipInitialAnimation
                />
              </Suspense>
              <p className="text-xs text-muted-foreground/60 text-center flex items-center justify-center gap-1.5 quiz-animate-fade-in" style={{ animationDelay: '0.3s' }}>
                <Sparkles className="w-3 h-3" />
                <span>Conhecendo o app...</span>
              </p>
            </div>
            
            <QuizAnimationWrapper
              animationKey={`showcase-${state.currentFeatureShowcase.id}`}
              type="scale"
              skipAnimation={useLightAnimations}
              useCSS={isInAppBrowser}
              className="w-full"
            >
              <Suspense fallback={<ShowcaseFallback />}>
                <QuizFeatureShowcase
                  feature={state.currentFeatureShowcase}
                  onContinue={handleFeatureShowcaseComplete}
                  useLightAnimations={useLightAnimations}
                />
              </Suspense>
            </QuizAnimationWrapper>
          </div>
        )}

        {/* Loading com Cases de Sucesso */}
        {!state.error && state.currentPhase === 'loading-diagnosis' && (
          <QuizLoadingWithCases onComplete={handleLoadingCasesComplete} />
        )}

        {/* Fase 2: Resultado com diagnóstico */}
        {!state.error && state.currentPhase === 'result' && state.result && (
          <QuizAnimationWrapper
            animationKey="result"
            type="slideUp"
            skipAnimation={useLightAnimations}
            useCSS={isInAppBrowser}
          >
            <Suspense fallback={<LazyFallback />}>
              <QuizResultPhase2
                diagnosisSummary={state.result.diagnosis_summary}
                recommendedFocus={state.result.recommended_focus}
                projectionPayload={state.result.projection_payload}
                onCTAClick={handleResultContinue}
              />
            </Suspense>
          </QuizAnimationWrapper>
        )}

        {/* Guia Gratuito - Opt-in */}
        {!state.error && state.currentPhase === 'guide-optin' && (
          <QuizAnimationWrapper
            animationKey="guide-optin"
            type="slideUp"
            skipAnimation={useLightAnimations}
            useCSS={isInAppBrowser}
          >
            <Suspense fallback={<LazyFallback />}>
              <QuizGuideOptin
                onRequestGuide={handleGuideRequest}
                onSkip={handleGuideOptinContinue}
                isLoading={state.isLoading}
              />
            </Suspense>
          </QuizAnimationWrapper>
        )}

        {/* Fase 3: Autoridade */}
        {!state.error && state.currentPhase === 'authority' && (
          <QuizAnimationWrapper
            animationKey="authority"
            type="scale"
            skipAnimation={useLightAnimations}
            useCSS={isInAppBrowser}
          >
            <Suspense fallback={<LazyFallback />}>
              <QuizAuthority
                onContinue={handleAuthorityContinue}
                isLoading={state.isLoading}
              />
            </Suspense>
          </QuizAnimationWrapper>
        )}

        {/* Fase 3: Compromisso */}
        {!state.error && state.currentPhase === 'commitment' && (
          <QuizAnimationWrapper
            animationKey="commitment"
            type="scale"
            skipAnimation={useLightAnimations}
            useCSS={isInAppBrowser}
          >
            <Suspense fallback={<LazyFallback />}>
              <QuizCommitment
                onSelect={handleCommitmentSelect}
                isLoading={state.isLoading}
              />
            </Suspense>
          </QuizAnimationWrapper>
        )}

        {/* Fase 3: Objeções */}
        {!state.error && state.currentPhase === 'objections' && (
          <QuizAnimationWrapper
            animationKey="objections"
            type="scale"
            skipAnimation={useLightAnimations}
            useCSS={isInAppBrowser}
          >
            <Suspense fallback={<LazyFallback />}>
              <QuizObjections
                onContinue={handleObjectionsContinue}
                isLoading={state.isLoading}
              />
            </Suspense>
          </QuizAnimationWrapper>
        )}
      </main>

      {/* Footer discreto */}
      <footer className="w-full px-4 py-4 text-center relative z-10">
        <p className="text-xs text-muted-foreground/40">
          © {new Date().getFullYear()} Hybrid Fit
        </p>
      </footer>
    </div>
    </>
  );
}
