import { useMemo, useState } from 'react';
import { useRouter } from 'expo-router';
import { useTranslation } from 'react-i18next';
import { Alert } from 'react-native';
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';
import { OnboardingLayout } from '@/components/onboarding/OnboardingLayout';
import { NameInputStep } from '@/components/onboarding/NameInputStep';
import { SelectionStep } from '@/components/onboarding/SelectionStep';
import { ReminderStep } from '@/components/onboarding/ReminderStep';
import { buildUserProfileFromQuestionnaire, mapOnboardingSelectionsToQuestionnaireAnswers } from '@/src/features/userProfileScoring';
import { ensureDailyWidgetRecoUpToDate, syncWidgetConfig, syncWidgetUserProfileFromScoring } from '@/src/modules/dailyWidgetReco';
import { toBackendLocaleFromLanguageTag } from '@/src/i18n/locale';
import { fetchRecoFeed } from '@/src/services/recoApi';
import { getExpoPushTokenOrThrow, registerPushToken, setPushPreferences } from '@/src/services/pushApi';
import {
  recordRecoFeedServed,
  setOnboardingCompleted,
  setUserProfile,
  setDailyReminderSettings,
  setUserProfileScoring,
  setRecoFeedCache,
  setPushPromptState,
} from '@/src/storage/appStorage';

type Step =
  | { id: 'name'; type: 'name' }
  | { id: 'status' | 'emotion' | 'influence' | 'support'; type: 'selection'; optionIds: string[] }
  | { id: 'reminder'; type: 'reminder' };

const STEPS: Step[] = [
  { id: 'name', type: 'name' },
  { id: 'status', type: 'selection', optionIds: ['pregnant', 'has_kids', 'no_fill'] },
  { id: 'emotion', type: 'selection', optionIds: ['happy', 'calm', 'okay', 'tired', 'stressed', 'low'] },
  { id: 'influence', type: 'selection', optionIds: ['family', 'work', 'relationship', 'friends', 'health'] },
  { id: 'support', type: 'selection', optionIds: ['emotional', 'parenting', 'self_worth', 'anxiety', 'balance'] },
  { id: 'reminder', type: 'reminder' },
];

export default function OnboardingScreen() {
  const router = useRouter();
  const { t, i18n } = useTranslation();
  const [stepIndex, setStepIndex] = useState(0);
  const [name, setName] = useState('');
  const [selections, setSelections] = useState<Record<string, string[]>>({});
  const [reminderTimes, setReminderTimes] = useState(3);

  const currentStep = STEPS[stepIndex];
  const currentTitle = useMemo(() => t(`onboardingSurvey.steps.${currentStep.id}.title`), [t, currentStep.id]);
  const currentOptions = useMemo(() => {
    if (currentStep.type !== 'selection') return [];
    return currentStep.optionIds.map((optId) => ({
      id: optId,
      label: t(`onboardingSurvey.steps.${currentStep.id}.options.${optId}`),
    }));
  }, [t, currentStep]);

  async function onFinish() {
    // 用户选择每日次数 > 0：在此页直接触发系统通知权限（已移除单独的 push 引导页）。
    const wantsPush = reminderTimes > 0;

    // 将 Onboarding 选择映射为标准问卷枚举（允许跳过）
    const answers = mapOnboardingSelectionsToQuestionnaireAnswers(selections);

    // 生成用户画像（供推荐/Push/Widget 复用）
    const scoringProfile = buildUserProfileFromQuestionnaire(answers);
    await setUserProfileScoring(scoringProfile);

    // 同步到 App Group：供 iOS Widget 拉取与展示
    await syncWidgetConfig();
    await syncWidgetUserProfileFromScoring(scoringProfile);

    // 可选：前台辅助拉取一次“每日推荐”，提升小组件首次展示的成功率与一致性（失败不阻塞）
    await ensureDailyWidgetRecoUpToDate({ reason: 'onboarding_finish', scoringProfile });

    // Onboarding 结束后预拉取一次 Feed 文案（失败不阻塞进入首页）
    try {
      const lang = toBackendLocaleFromLanguageTag(i18n.language);
      const { items, meta } = await fetchRecoFeed({
        k: 30,
        user_profile: {
          profile_version: scoringProfile.profile_version,
          profile_source: scoringProfile.profile_source,
          profile_generated_at: scoringProfile.profile_generated_at,
          profile_confidence: scoringProfile.profile_confidence,
          profile_answered: scoringProfile.profile_answered,
          stage: scoringProfile.stage,
          emotion_score: scoringProfile.emotion_score,
          context: scoringProfile.context,
          need: scoringProfile.need,
        },
      });

      await setRecoFeedCache({
        saved_at: new Date().toISOString(),
        lang,
        items: items.map((x) => ({ content_id: x.content_id, text: x.text })),
        meta: meta as Record<string, unknown>,
      });
      await recordRecoFeedServed(items.map((x) => x.content_id));
    } catch {
      // 网络失败时使用首页本地 mock 兜底
    }

    await setUserProfile({ 
      name, 
      intents: Object.values(selections).flat() 
    });
    await setDailyReminderSettings({
      timesPerDay: reminderTimes,
      // 这里表示“用户意愿”，不代表系统权限一定已 granted
      pushEnabled: wantsPush,
    });
    await setOnboardingCompleted(true);

    // 用户选择 0 次（关闭）或跳过：直接进入首页
    if (!wantsPush) {
      await setPushPromptState('skipped');
      router.replace('/(app)/home');
      return;
    }

    // 用户想要 Push：请求系统权限并尽量完成 token/偏好上报（失败不阻塞进入首页）
    await setPushPromptState('unknown');
    try {
      const { status } = await Notifications.requestPermissionsAsync();
      if (status !== 'granted') {
        await setPushPromptState('skipped');
        return;
      }

      // iOS 模拟器通常无法获取 Expo Push Token（系统限制），此时不要提示“失败”，而是明确告知需要真机测试。
      if (Device.osName === 'iOS' && !Device.isDevice) {
        Alert.alert('提示', '当前为 iOS 模拟器，无法获取推送 Token。请使用真机测试推送功能。');
        await setPushPromptState('unknown');
        return;
      }

      // 1) 获取 Expo Push Token（失败才认为“推送开启失败”）
      const expoPushToken = await getExpoPushTokenOrThrow();
      // 2) 上报 token 到后端（幂等；失败才认为“推送开启失败”）
      await registerPushToken({ pushToken: expoPushToken });

      // 3) 上报推送偏好（幂等）
      // 注意：这一步失败时，后端仍可能已成功接收 token。
      // 为避免出现“后端已接收 token 但前端弹窗提示失败”的错觉，这里改为：偏好同步失败不弹“开启失败”，仅记录并继续。
      try {
        await setPushPreferences({ enabled: wantsPush, timesPerDay: reminderTimes });
      } catch (e) {
        const msg = e instanceof Error ? e.message : String(e);
        console.warn('[PushPreferences] 同步失败（Onboarding，不阻塞）', msg);
      }

      await setPushPromptState('enabled');
    } catch (e) {
      // 失败不阻塞进入首页；但这里给出更明确的文案（常见原因：模拟器/网络/后端异常）
      Alert.alert(t('push.errorTitle'), t('push.errorDesc'));
      await setPushPromptState('unknown');
    } finally {
      router.replace('/(app)/home');
    }
  }

  const onNext = () => {
    if (stepIndex < STEPS.length - 1) {
      setStepIndex(stepIndex + 1);
    } else {
      onFinish();
    }
  };

  const onBack = () => {
    if (stepIndex > 0) {
      setStepIndex(stepIndex - 1);
    }
  };

  const onSkip = async () => {
    // 跳过整个 Onboarding：仍生成一个“全跳过”的最小画像，保证下游可用
    const scoringProfile = buildUserProfileFromQuestionnaire({});
    await setUserProfileScoring(scoringProfile);

    // 同步到 App Group：供 iOS Widget 使用（失败不阻塞）
    await syncWidgetConfig();
    await syncWidgetUserProfileFromScoring(scoringProfile);

    // 标记已完成，避免下次启动再次进入 Onboarding
    await setOnboardingCompleted(true);
    router.replace('/(app)/home');
  };

  // 题目为多选：点击切换选中状态
  const handleToggleSelection = (id: string) => {
    setSelections(prev => {
      const currentIds = prev[currentStep.id] || [];
      const nextIds = currentIds.includes(id)
        ? currentIds.filter(i => i !== id)
        : [...currentIds, id];
      return { ...prev, [currentStep.id]: nextIds };
    });
  };

  const handleSkipStep = () => {
    setSelections((prev) => ({ ...prev, [currentStep.id]: [] }));
    onNext();
  };

  return (
    <OnboardingLayout
      title={currentTitle}
      currentStep={stepIndex}
      totalSteps={STEPS.length - 1}
      onSkip={onSkip}
      onBack={onBack}
      showBackButton={stepIndex > 0}
      userName={name}
    >
      {currentStep.type === 'name' && (
        <NameInputStep
          value={name}
          onChangeText={setName}
          onNext={onNext}
        />
      )}

      {currentStep.type === 'selection' && (
        <SelectionStep
          options={currentOptions}
          selectedIds={selections[currentStep.id] || []}
          onToggle={handleToggleSelection}
          onNext={onNext}
        />
      )}

      {currentStep.type === 'reminder' && (
        <ReminderStep
          value={Math.max(1, reminderTimes)}
          onChange={setReminderTimes}
          onFinish={onFinish}
          onSkip={() => {
            // 跳过每日提醒：视为 0 次（关闭）
            setReminderTimes(0);
            onFinish();
          }}
        />
      )}
    </OnboardingLayout>
  );
}
