'use client';

import { useCallback, useEffect, useState } from 'react';
import { getCurrentSurvey, getMe, getUserPicks, isLoggedIn, submitSurvey, verifyPurchase } from '@/lib/api';
import { BONUS_SURVEY_CREDITS, getPaidProductMetadata } from '@/lib/offer';
import { isVerifiedPurchaseResponse, stripPurchaseReturnParams } from '@/lib/purchase-return';
import { trackConversion, trackEvent } from '@/lib/tracking';
import { applyForecastBalanceResponse, applySurveyRewardResponse, mergeUserPreservingForecastBalance } from '@/lib/user-balance';
import type { SharedPageQueryParams, SignupGateContext } from '@/components/forecast-page-types';

interface UseForecastAccessFlowArgs {
  pathname: string | null;
  queryParams?: SharedPageQueryParams;
}

export default function useForecastAccessFlow({
  pathname,
  queryParams,
}: UseForecastAccessFlowArgs) {
  const [showPaywall, setShowPaywall] = useState(false);
  const [showVerifyPrompt, setShowVerifyPrompt] = useState(false);
  const [showSignupGate, setShowSignupGate] = useState(false);
  const [showForecastsModal, setShowForecastsModal] = useState(false);
  const [user, setUser] = useState<any>(null);
  const [ownedPicks, setOwnedPicks] = useState<Set<string>>(new Set());
  const [showSurvey, setShowSurvey] = useState(false);
  const [purchaseToast, setPurchaseToast] = useState(false);
  const [purchaseToastBalance, setPurchaseToastBalance] = useState<number | null>(null);
  const [surveyData, setSurveyData] = useState<any>(null);
  const [signupGateResumeAction, setSignupGateResumeAction] = useState<(() => void | Promise<void>) | null>(null);
  const [signupGateContext, setSignupGateContext] = useState<SignupGateContext | null>(null);
  const shouldForceSurvey = queryParams?.survey === '1';

  const refreshUser = useCallback(() => {
    getMe().then(setUser).catch((err) => {
      console.error('Failed to refresh user:', err);
    });
  }, []);

  const refreshUserPreservingBalance = useCallback(() => {
    getMe().then((nextUser) => {
      setUser((prev: any) => mergeUserPreservingForecastBalance(prev, nextUser));
    }).catch((err) => {
      console.error('Failed to refresh user balance:', err);
    });
  }, []);

  const updateBalanceFromResponse = useCallback((data: any) => {
    const forecastBalance = data.forecastBalance ?? data.forecast_balance;
    if (forecastBalance !== undefined) {
      setUser((prev: any) => applyForecastBalanceResponse(prev, forecastBalance));
    }
  }, []);

  const getForecastBalanceFromUser = useCallback((nextUser: any): number | null => {
    if (!nextUser) return null;
    if (typeof nextUser._forecast_balance === 'number') return nextUser._forecast_balance;
    return (nextUser.daily_free_forecasts || 0)
      + (nextUser.daily_pass_valid ? nextUser.daily_pass_picks || 0 : 0)
      + (nextUser.signup_bonus_forecasts || 0)
      + (nextUser.survey_bonus_forecasts || 0)
      + (nextUser.single_picks || 0);
  }, []);

  const applySurveyReward = useCallback((result: any) => {
    setUser((prev: any) => applySurveyRewardResponse(prev, result));
  }, []);

  useEffect(() => {
    trackEvent('session_start', { loggedIn: isLoggedIn() });
    if (isLoggedIn()) {
      refreshUser();
      getUserPicks(200).then((data) => {
        if (data.picks?.length > 0) {
          setOwnedPicks(new Set(data.picks.map((pick: any) => pick.eventId)));
        }
      }).catch((err) => {
        console.error('Failed to load owned picks:', err);
      });
    }
    if (!isLoggedIn()) {
      return;
    }

    let surveyDismissed = false;
    try {
      const dismissed = localStorage.getItem('rm_survey_dismissed');
      if (dismissed) {
        const dismissedAt = parseInt(dismissed, 10);
        if (Date.now() - dismissedAt < 7 * 24 * 60 * 60 * 1000) surveyDismissed = true;
      }
    } catch {}

    const surveyTimer = setTimeout(() => {
      getCurrentSurvey()
        .then((data) => {
          if (!data.survey) {
            return;
          }
          if (!shouldForceSurvey && surveyDismissed && data.hasCompletedAnySurvey) {
            return;
          }
          setSurveyData({
            ...data.survey,
            hasCompletedAnySurvey: !!data.hasCompletedAnySurvey,
          });
          setShowSurvey(true);
          if (shouldForceSurvey && typeof window !== 'undefined') {
            window.history.replaceState({}, '', pathname || '/forecasts');
          }
        })
        .catch((err) => {
          console.error('Failed to load survey prompt:', err);
        });
    }, shouldForceSurvey ? 0 : 5000);

    return () => clearTimeout(surveyTimer);
  }, [pathname, refreshUser, shouldForceSurvey]);

  useEffect(() => {
    if (!user?.email_verified) return;
    let pending: string | null = null;
    try {
      pending = localStorage.getItem('rm_pending_survey');
    } catch {
      return;
    }
    if (!pending) return;
    try {
      const { surveyId, answers } = JSON.parse(pending);
      if (!surveyId || !answers) {
        return;
      }
      submitSurvey(surveyId, answers)
        .then((result) => {
          localStorage.removeItem('rm_pending_survey');
          applySurveyReward({
            ...result,
            creditsAwarded: result.creditsAwarded || BONUS_SURVEY_CREDITS,
          });
          setShowSurvey(false);
        })
        .catch(() => {
          localStorage.removeItem('rm_pending_survey');
        });
    } catch {
      localStorage.removeItem('rm_pending_survey');
    }
  }, [applySurveyReward, user?.email_verified]);

  useEffect(() => {
    const purchase = queryParams?.purchase;
    if (!purchase) {
      return;
    }

    const clearPurchaseParams = () => {
      window.history.replaceState({}, '', stripPurchaseReturnParams(window.location.href));
    };

    if (purchase === 'cancelled') {
      trackEvent('checkout_return', { status: 'cancelled' });
      clearPurchaseParams();
      return;
    }

    if (purchase !== 'success') {
      return;
    }

    let cancelled = false;
    const transactionId = queryParams?.transId || queryParams?.session_id || undefined;
    const invoiceNumber = queryParams?.invoiceNumber || undefined;

    trackEvent('checkout_return', {
      status: 'success',
      transactionId: transactionId || null,
      invoiceNumber: invoiceNumber || null,
    });

    verifyPurchase(transactionId, invoiceNumber).then(async (result) => {
      if (cancelled) return;
      if (!isVerifiedPurchaseResponse(result)) {
        trackEvent('checkout_return_verification_failed', {
          transactionId: transactionId || null,
          invoiceNumber: invoiceNumber || null,
        });
        clearPurchaseParams();
        return;
      }

      trackConversion('purchase_complete', {
        transactionId: transactionId || null,
        invoiceNumber: invoiceNumber || null,
        productType: result.productType || null,
        amount: getPaidProductMetadata(result.productType)?.value,
        currency: 'USD',
        content_name: getPaidProductMetadata(result.productType)?.contentName,
      });
      const nextUser = await getMe().catch(() => null);
      if (cancelled) return;
      if (nextUser) {
        setUser(nextUser);
        setPurchaseToastBalance(getForecastBalanceFromUser(nextUser));
      } else {
        setPurchaseToastBalance(null);
        refreshUser();
      }
      setPurchaseToast(true);
      clearPurchaseParams();
    }).catch((err) => {
      console.error('Purchase verification error:', err);
      clearPurchaseParams();
    });

    return () => {
      cancelled = true;
    };
  }, [getForecastBalanceFromUser, queryParams, refreshUser]);

  const closeSignupGate = useCallback(() => {
    setShowSignupGate(false);
    setSignupGateResumeAction(null);
    setSignupGateContext(null);
  }, []);

  const handleSignupGateSignedIn = useCallback(() => {
    const resumeAction = signupGateResumeAction;
    setShowSignupGate(false);
    setSignupGateResumeAction(null);
    setSignupGateContext(null);
    refreshUser();
    if (resumeAction) {
      void resumeAction();
    }
  }, [refreshUser, signupGateResumeAction]);

  const openSignupGate = useCallback((context: string | SignupGateContext, resumeAction?: () => void | Promise<void>) => {
    const nextContext = typeof context === 'string' ? { source: context } : context;
    trackEvent('signup_gate_open', nextContext, { immediate: true });
    setSignupGateContext(nextContext);
    setSignupGateResumeAction(() => resumeAction ?? null);
    setShowSignupGate(true);
  }, []);

  const openForecastsModal = useCallback((source: string) => {
    trackEvent('forecasts_modal_open', { source });
    setShowForecastsModal(true);
  }, []);

  const openPaywall = useCallback((source: string) => {
    trackEvent('paywall_open', { source });
    setShowPaywall(true);
  }, []);

  const markOwnedPick = useCallback((eventId: string) => {
    setOwnedPicks((prev) => new Set([...prev, eventId]));
  }, []);

  const onBuyForecastClick = useCallback((source = 'unknown') => {
    if (!isLoggedIn()) {
      openSignupGate(source);
      return;
    }
    openForecastsModal(source);
  }, [openForecastsModal, openSignupGate]);

  const closePurchaseToast = useCallback(() => {
    setPurchaseToast(false);
    setPurchaseToastBalance(null);
  }, []);

  return {
    user,
    ownedPicks,
    showPaywall,
    showVerifyPrompt,
    showSignupGate,
    showForecastsModal,
    showSurvey,
    purchaseToast,
    purchaseToastBalance,
    surveyData,
    signupGateContext,
    refreshUser,
    refreshUserPreservingBalance,
    updateBalanceFromResponse,
    applySurveyReward,
    markOwnedPick,
    openSignupGate,
    openForecastsModal,
    openPaywall,
    onBuyForecastClick,
    closeSignupGate,
    handleSignupGateSignedIn,
    closePurchaseToast,
    setShowPaywall,
    setShowVerifyPrompt,
    setShowForecastsModal,
    setShowSurvey,
  };
}
