import { useEffect, useState } from 'react';
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import { AppState, Modal, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';
import { useAuthStore, type AuthState } from '../store/auth-store';
import { useInboxStore } from '../store/inbox-store';
import { useIntakeStore } from '../store/intake-store';
import { useNotesStore } from '../store/notes-store';
import { useWorkspaceStore } from '../store/workspace-store';
import { checkKillSwitch, flushTelemetry, initPlatform } from '../lib/platform';
import { getBroadcastClient } from '../lib/broadcast-client';
import { getSurveyClient } from '../lib/survey-client';
import { flushNoteQueue, getNoteQueueSize } from '../lib/offline-queue';
import type { InAppMessage } from '@bytelyst/broadcast-client';
import type { ActiveSurvey, Question, QuestionAnswer } from '@bytelyst/survey-client';
import { colors } from '../theme';

export default function RootLayout() {
  const [broadcastMessages, setBroadcastMessages] = useState<InAppMessage[]>([]);
  const [activeSurvey, setActiveSurvey] = useState<ActiveSurvey | null>(null);
  const [surveyStarted, setSurveyStarted] = useState(false);
  const [surveyIndex, setSurveyIndex] = useState(0);
  const [surveyAnswers, setSurveyAnswers] = useState<Record<string, QuestionAnswer>>({});
  const [textAnswer, setTextAnswer] = useState('');
  const [queueStatus, setQueueStatus] = useState<{ pending: number; lastFlushed: number }>({
    pending: getNoteQueueSize(),
    lastFlushed: 0,
  });

  const [killSwitchState, setKillSwitchState] = useState<{
    checked: boolean;
    disabled: boolean;
    message: string | null;
  }>({
    checked: false,
    disabled: false,
    message: null,
  });

  const bootstrapAuth = useAuthStore((state: AuthState) => state.bootstrap);
  const hasBootstrapped = useAuthStore((state: AuthState) => state.hasBootstrapped);
  const isAuthenticated = useAuthStore((state: AuthState) => state.isAuthenticated);

  function toSurveyAnswer(question: Question, value: string): QuestionAnswer {
    if (question.type === 'single_choice' || question.type === 'dropdown') {
      return { type: 'single_choice', optionId: value };
    }
    if (question.type === 'multiple_choice') {
      return { type: 'multiple_choice', optionIds: [value] };
    }
    if (question.type === 'ranking') {
      return { type: 'ranking', rankedOptionIds: [value] };
    }
    if (question.type === 'rating' || question.type === 'nps' || question.type === 'scale') {
      return { type: 'rating', value: Number(value) };
    }
    return { type: 'text', value };
  }

  async function flushQueuedNoteMutations(): Promise<void> {
    const pending = getNoteQueueSize();
    if (pending === 0) {
      setQueueStatus({ pending: 0, lastFlushed: 0 });
      return;
    }

    const result = await flushNoteQueue().catch(() => ({ flushed: 0, failed: getNoteQueueSize() }));
    setQueueStatus({
      pending: result.failed,
      lastFlushed: result.flushed,
    });
  }

  async function loadBroadcasts(): Promise<void> {
    try {
      const { messages } = await getBroadcastClient().listMessages();
      setBroadcastMessages(messages.filter((message) => message.status !== 'dismissed'));
    } catch {
    }
  }

  async function loadSurvey(): Promise<void> {
    try {
      const { survey } = await getSurveyClient().getActiveSurvey();
      setActiveSurvey((current) => current ?? survey);
    } catch {
    }
  }

  useEffect(() => {
    void checkKillSwitch()
      .then((state) => {
        setKillSwitchState({
          checked: true,
          disabled: state.disabled,
          message: state.message,
        });
      })
      .catch(() => {
        setKillSwitchState({ checked: true, disabled: false, message: null });
      });
  }, []);

  useEffect(() => {
    void bootstrapAuth();
  }, [bootstrapAuth]);

  useEffect(() => {
    void initPlatform();
  }, []);

  useEffect(() => {
    const sub = AppState.addEventListener('change', (nextState) => {
      if (nextState === 'background' || nextState === 'inactive') {
        flushTelemetry();
      }
    });
    return () => sub.remove();
  }, []);

  useEffect(() => {
    if (!hasBootstrapped || !isAuthenticated) {
      return undefined;
    }

    let cancelled = false;

    void (async () => {
      await Promise.all([
        useNotesStore.getState().hydrate(),
        useWorkspaceStore.getState().hydrate(),
        useInboxStore.getState().hydrate(),
      ]);
      if (cancelled) {
        return;
      }
      void flushQueuedNoteMutations();
      void loadBroadcasts();
      void loadSurvey();
      void useIntakeStore.getState().pollActiveJobs();
    })();

    const broadcastTimer = setInterval(() => {
      void loadBroadcasts();
    }, 5 * 60_000);

    const surveyTimer = setInterval(() => {
      void loadSurvey();
    }, 10 * 60_000);

    const intakeTimer = setInterval(() => {
      void useIntakeStore.getState().pollActiveJobs();
    }, 30_000);

    const appStateSubscription = AppState.addEventListener('change', (nextState) => {
      if (nextState === 'active') {
        void flushQueuedNoteMutations();
      }
    });

    return () => {
      cancelled = true;
      clearInterval(broadcastTimer);
      clearInterval(surveyTimer);
      clearInterval(intakeTimer);
      appStateSubscription.remove();
    };
  }, [hasBootstrapped, isAuthenticated]);

  if (killSwitchState.checked && killSwitchState.disabled) {
    return (
      <View
        style={{
          flex: 1,
          alignItems: 'center',
          justifyContent: 'center',
          paddingHorizontal: 24,
          backgroundColor: colors.bgCanvas,
          gap: 12,
        }}
      >
        <StatusBar style="light" />
        <Text style={{ color: colors.textPrimary, fontSize: 24, fontWeight: '700', textAlign: 'center' }}>
          NoteLett is temporarily unavailable
        </Text>
        <Text style={{ color: colors.textSecondary, fontSize: 15, textAlign: 'center' }}>
          {killSwitchState.message ?? 'Service access is currently paused by the platform team. Please try again later.'}
        </Text>
      </View>
    );
  }

  const currentQuestion = activeSurvey?.questions[surveyIndex];

  async function dismissBroadcast(messageId: string): Promise<void> {
    try {
      await getBroadcastClient().markDismissed(messageId);
    } catch {
    }
    setBroadcastMessages((current) => current.filter((message) => message.id !== messageId));
  }

  async function startSurvey(): Promise<void> {
    if (!activeSurvey) {
      return;
    }
    try {
      await getSurveyClient().startSurvey(activeSurvey.id);
    } catch {
    }
    setSurveyStarted(true);
  }

  async function dismissSurvey(): Promise<void> {
    if (activeSurvey) {
      try {
        await getSurveyClient().dismissSurvey(activeSurvey.id);
      } catch {
      }
    }
    setActiveSurvey(null);
    setSurveyStarted(false);
    setSurveyIndex(0);
    setSurveyAnswers({});
    setTextAnswer('');
  }

  async function submitAnswer(value: string): Promise<void> {
    if (!activeSurvey || !currentQuestion) {
      return;
    }

    const answer = toSurveyAnswer(currentQuestion, value);
    setSurveyAnswers((current) => ({
      ...current,
      [currentQuestion.id]: answer,
    }));

    try {
      await getSurveyClient().submitAnswer(activeSurvey.id, currentQuestion.id, answer);
    } catch {
      return;
    }

    const isLastQuestion = surveyIndex >= activeSurvey.questions.length - 1;
    if (isLastQuestion) {
      try {
        await getSurveyClient().completeSurvey(activeSurvey.id);
      } catch {
      }
      await dismissSurvey();
      return;
    }

    setSurveyIndex((current) => current + 1);
    setTextAnswer('');
  }

  return (
    <View style={styles.root}>
      <StatusBar style="light" />
      {broadcastMessages.length > 0 ? (
        <View style={styles.bannerSection}>
          {broadcastMessages.map((message) => (
            <View key={message.id} style={styles.bannerCard}>
              <View style={styles.bannerContent}>
                <Text style={styles.bannerTitle}>{message.title}</Text>
                {message.body ? <Text style={styles.bannerBody}>{message.body}</Text> : null}
              </View>
              {message.dismissible !== false ? (
                <Pressable onPress={() => void dismissBroadcast(message.id)}>
                  <Text style={styles.bannerDismiss}>×</Text>
                </Pressable>
              ) : null}
            </View>
          ))}
        </View>
      ) : null}

      {queueStatus.pending > 0 || queueStatus.lastFlushed > 0 ? (
        <View style={styles.queueStatusCard}>
          <Text style={styles.queueStatusTitle}>Offline sync</Text>
          <Text style={styles.queueStatusBody}>Pending actions: {queueStatus.pending}</Text>
          <Text style={styles.queueStatusBody}>Flushed on last attempt: {queueStatus.lastFlushed}</Text>
        </View>
      ) : null}

      {activeSurvey && !surveyStarted ? (
        <View style={styles.surveyPrompt}>
          <Text style={styles.surveyPromptText}>{activeSurvey.title}</Text>
          <View style={styles.surveyActions}>
            <Pressable style={styles.primaryButton} onPress={() => void startSurvey()}>
              <Text style={styles.primaryButtonText}>Start</Text>
            </Pressable>
            <Pressable style={styles.secondaryButton} onPress={() => void dismissSurvey()}>
              <Text style={styles.secondaryButtonText}>Dismiss</Text>
            </Pressable>
          </View>
        </View>
      ) : null}

      <View style={styles.stackContainer}>
        <Stack
          screenOptions={{
            headerShown: false,
            animation: 'fade',
          }}
        />
      </View>

      <Modal animationType="slide" transparent visible={Boolean(activeSurvey && surveyStarted && currentQuestion)}>
        <View style={styles.modalBackdrop}>
          <View style={styles.modalCard}>
            <Text style={styles.modalTitle}>{activeSurvey?.title}</Text>
            <Text style={styles.modalQuestion}>{currentQuestion?.text}</Text>
            <Text style={styles.modalMeta}>
              {surveyIndex + 1}/{activeSurvey?.questions.length ?? 1}
            </Text>

            {currentQuestion?.options?.length ? (
              <ScrollView contentContainerStyle={styles.optionsList}>
                {currentQuestion.options.map((option) => (
                  <Pressable
                    key={option.id}
                    style={styles.optionButton}
                    onPress={() => void submitAnswer(option.id)}
                  >
                    <Text style={styles.optionText}>{option.emoji ? `${option.emoji} ` : ''}{option.text}</Text>
                  </Pressable>
                ))}
              </ScrollView>
            ) : currentQuestion && (currentQuestion.type === 'rating' || currentQuestion.type === 'nps' || currentQuestion.type === 'scale') ? (
              <View style={styles.ratingRow}>
                {Array.from(
                  { length: (currentQuestion.maxValue ?? 5) - (currentQuestion.minValue ?? 1) + 1 },
                  (_, index) => (currentQuestion.minValue ?? 1) + index,
                ).map((value) => (
                  <Pressable key={value} style={styles.ratingButton} onPress={() => void submitAnswer(String(value))}>
                    <Text style={styles.ratingText}>{value}</Text>
                  </Pressable>
                ))}
              </View>
            ) : (
              <>
                <TextInput
                  value={textAnswer}
                  onChangeText={setTextAnswer}
                  placeholder="Your answer"
                  placeholderTextColor={colors.textTertiary}
                  style={styles.answerInput}
                  multiline={currentQuestion?.type === 'text_long'}
                />
                <Pressable
                  style={[styles.primaryButton, textAnswer.trim().length === 0 ? styles.disabledButton : null]}
                  disabled={textAnswer.trim().length === 0}
                  onPress={() => void submitAnswer(textAnswer.trim())}
                >
                  <Text style={styles.primaryButtonText}>Next</Text>
                </Pressable>
              </>
            )}

            <Pressable style={styles.secondaryButton} onPress={() => void dismissSurvey()}>
              <Text style={styles.secondaryButtonText}>Close</Text>
            </Pressable>
          </View>
        </View>
      </Modal>
    </View>
  );
}

const styles = StyleSheet.create({
  root: {
    flex: 1,
    backgroundColor: colors.bgCanvas,
  },
  queueStatusCard: {
    marginHorizontal: 12,
    borderRadius: 12,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    backgroundColor: colors.surfaceCard,
    padding: 10,
    gap: 4,
  },
  queueStatusTitle: {
    color: colors.textPrimary,
    fontWeight: '700',
    fontSize: 13,
  },
  queueStatusBody: {
    color: colors.textSecondary,
    fontSize: 12,
  },
  bannerSection: {
    paddingHorizontal: 12,
    paddingTop: 10,
    gap: 8,
  },
  bannerCard: {
    borderRadius: 12,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    backgroundColor: colors.bgElevated,
    padding: 10,
    flexDirection: 'row',
    alignItems: 'flex-start',
    justifyContent: 'space-between',
  },
  bannerContent: {
    flex: 1,
    gap: 4,
    paddingRight: 10,
  },
  bannerTitle: {
    color: colors.textPrimary,
    fontWeight: '700',
    fontSize: 13,
  },
  bannerBody: {
    color: colors.textSecondary,
    fontSize: 12,
  },
  bannerDismiss: {
    color: colors.textSecondary,
    fontSize: 18,
    lineHeight: 18,
  },
  surveyPrompt: {
    margin: 12,
    borderRadius: 12,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    backgroundColor: colors.surfaceCard,
    padding: 12,
    gap: 10,
  },
  surveyPromptText: {
    color: colors.textPrimary,
    fontWeight: '700',
  },
  surveyActions: {
    flexDirection: 'row',
    gap: 8,
  },
  primaryButton: {
    borderRadius: 10,
    backgroundColor: colors.accentPrimary,
    paddingHorizontal: 14,
    paddingVertical: 10,
    alignItems: 'center',
    justifyContent: 'center',
  },
  primaryButtonText: {
    color: colors.textPrimary,
    fontWeight: '700',
  },
  secondaryButton: {
    borderRadius: 10,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    paddingHorizontal: 14,
    paddingVertical: 10,
    alignItems: 'center',
    justifyContent: 'center',
  },
  secondaryButtonText: {
    color: colors.textSecondary,
    fontWeight: '600',
  },
  stackContainer: {
    flex: 1,
  },
  modalBackdrop: {
    flex: 1,
    backgroundColor: colors.overlayBackdrop,
    justifyContent: 'center',
    paddingHorizontal: 16,
  },
  modalCard: {
    borderRadius: 16,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    backgroundColor: colors.bgCanvas,
    padding: 16,
    gap: 12,
    maxHeight: '85%',
  },
  modalTitle: {
    color: colors.textPrimary,
    fontWeight: '700',
    fontSize: 18,
  },
  modalQuestion: {
    color: colors.textPrimary,
    fontSize: 15,
    lineHeight: 21,
  },
  modalMeta: {
    color: colors.textSecondary,
    fontSize: 12,
  },
  optionsList: {
    gap: 8,
  },
  optionButton: {
    borderRadius: 10,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    paddingHorizontal: 12,
    paddingVertical: 10,
  },
  optionText: {
    color: colors.textPrimary,
    fontSize: 14,
  },
  ratingRow: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: 8,
  },
  ratingButton: {
    width: 38,
    height: 38,
    borderRadius: 19,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    alignItems: 'center',
    justifyContent: 'center',
  },
  ratingText: {
    color: colors.textPrimary,
    fontWeight: '600',
  },
  answerInput: {
    borderRadius: 10,
    borderWidth: 1,
    borderColor: colors.borderDefault,
    backgroundColor: colors.bgElevated,
    color: colors.textPrimary,
    padding: 10,
    minHeight: 42,
    textAlignVertical: 'top' as const,
  },
  disabledButton: {
    opacity: 0.5,
  },
});
