import { Stack, useFocusEffect, useRouter } from 'expo-router';
import { useCallback, useState } from 'react';
import { ActivityIndicator, Pressable, ScrollView, StyleSheet, View } from 'react-native';

import { ThemedText } from '@/components/themed-text';
import { ThemedView } from '@/components/themed-view';
import { MaxContentWidth, Spacing } from '@/constants/theme';
import { useTheme } from '@/hooks/use-theme';
import { getRepo, type Flashcard } from '@/lib/db';
import { downloadText } from '@/lib/download';
import { review } from '@/lib/learn';
import { useCourses } from '@/stores/coursesStore';

const ACCENT = '#3c87f7';

// Course scope for the due queue: 'all' = no filter, null = Unsorted, string = course id.
type Scope = 'all' | string | null;

const GRADES: { label: string; grade: 0 | 1 | 2 | 3 }[] = [
  { label: 'Again', grade: 0 },
  { label: 'Hard', grade: 1 },
  { label: 'Good', grade: 2 },
  { label: 'Easy', grade: 3 },
];

export default function StudyScreen() {
  const theme = useTheme();
  const router = useRouter();

  const courses = useCourses((s) => s.items);
  const refreshCourses = useCourses((s) => s.refresh);

  const [scope, setScope] = useState<Scope>('all');
  const [queue, setQueue] = useState<Flashcard[] | null>(null);
  const [index, setIndex] = useState(0);
  const [revealed, setRevealed] = useState(false);

  const load = useCallback(async (s: Scope) => {
    setQueue(null);
    setIndex(0);
    setRevealed(false);
    const cards = await getRepo().listDueFlashcards(
      s === 'all' ? {} : { courseId: s },
    );
    setQueue(cards);
  }, []);

  // Reload the due queue and courses every time the screen gains focus.
  useFocusEffect(
    useCallback(() => {
      void refreshCourses();
      void load(scope);
    }, [refreshCourses, load, scope]),
  );

  const pickScope = (s: Scope) => {
    setScope(s);
    void load(s);
  };

  const total = queue?.length ?? 0;
  const card = queue && index < total ? queue[index] : undefined;

  const grade = async (g: 0 | 1 | 2 | 3) => {
    if (!card) return;
    await getRepo().updateFlashcardSrs(card.id, review(card.srs, g, Date.now()));
    setRevealed(false);
    setIndex((i) => i + 1);
  };

  const exportAnki = async () => {
    const all = await getRepo().listFlashcards();
    const rows = all.map((c) => `${csvField(c.front)},${csvField(c.back)}`);
    const csv = ['front,back', ...rows].join('\r\n');
    downloadText('wisp-flashcards.csv', 'text/csv', csv);
  };

  const courseName = (cid?: string | null) =>
    cid ? courses.find((c) => c.id === cid)?.name ?? 'Course' : 'Unsorted';

  return (
    <ThemedView style={styles.fill}>
      <Stack.Screen
        options={{
          title: 'Study',
          headerRight: () => (
            <Pressable onPress={() => void exportAnki()} hitSlop={8}>
              <ThemedText type="link" themeColor="textSecondary">Export Anki (.csv)</ThemedText>
            </Pressable>
          ),
        }}
      />
      <ScrollView contentContainerStyle={styles.content}>
        <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.filterBar}>
          <FilterChip label="All" active={scope === 'all'} onPress={() => pickScope('all')} />
          <FilterChip label="Unsorted" active={scope === null} onPress={() => pickScope(null)} />
          {courses.map((c) => (
            <FilterChip key={c.id} label={c.name} active={scope === c.id} onPress={() => pickScope(c.id)} />
          ))}
        </ScrollView>

        {queue === null ? (
          <ActivityIndicator style={styles.pad} />
        ) : card === undefined ? (
          <ThemedText type="small" themeColor="textSecondary" style={styles.pad}>
            {total === 0
              ? 'No cards due — generate some from a lecture.'
              : 'All done — no more cards due right now.'}
          </ThemedText>
        ) : (
          <>
            <ThemedText type="small" themeColor="textSecondary">
              {index + 1} of {total}
            </ThemedText>

            <ThemedView type="backgroundElement" style={styles.card}>
              <ThemedText type="small" themeColor="textSecondary">{courseName(card.courseId)}</ThemedText>
              <ThemedText type="subtitle" style={styles.front}>{card.front}</ThemedText>

              {revealed ? (
                <>
                  <View style={[styles.divider, { backgroundColor: theme.backgroundSelected }]} />
                  <ThemedText type="default">{card.back}</ThemedText>
                  {card.start !== undefined && (
                    <Pressable
                      onPress={() =>
                        router.push({
                          pathname: '/transcript/[id]',
                          params: { id: card.transcriptId, t: String(Math.floor(card.start ?? 0)) },
                        })
                      }
                      hitSlop={6}>
                      <ThemedText type="linkPrimary">Jump to lecture</ThemedText>
                    </Pressable>
                  )}
                </>
              ) : (
                <Pressable
                  onPress={() => setRevealed(true)}
                  style={({ pressed }) => [styles.showBtn, { backgroundColor: ACCENT, opacity: pressed ? 0.85 : 1 }]}>
                  <ThemedText style={styles.showBtnText}>Show answer</ThemedText>
                </Pressable>
              )}
            </ThemedView>

            {revealed && (
              <View style={styles.gradeRow}>
                {GRADES.map((g) => (
                  <Pressable
                    key={g.grade}
                    onPress={() => void grade(g.grade)}
                    style={({ pressed }) => [
                      styles.gradeBtn,
                      { backgroundColor: theme.backgroundElement, opacity: pressed ? 0.7 : 1 },
                    ]}>
                    <ThemedText type="smallBold">{g.label}</ThemedText>
                  </Pressable>
                ))}
              </View>
            )}
          </>
        )}
      </ScrollView>
    </ThemedView>
  );
}

function FilterChip({ label, active, onPress }: { label: string; active: boolean; onPress: () => void }) {
  const theme = useTheme();
  return (
    <Pressable
      onPress={onPress}
      style={[styles.filterChip, { backgroundColor: active ? ACCENT : theme.backgroundElement }]}>
      <ThemedText type="small" style={active ? styles.chipActive : undefined}>{label}</ThemedText>
    </Pressable>
  );
}

/** RFC4180-quote a CSV field: wrap in quotes, double any embedded quotes. */
function csvField(value: string): string {
  return `"${value.replace(/"/g, '""')}"`;
}

const styles = StyleSheet.create({
  fill: { flex: 1 },
  content: {
    padding: Spacing.three,
    gap: Spacing.three,
    maxWidth: MaxContentWidth,
    width: '100%',
    alignSelf: 'center',
  },
  filterBar: { gap: Spacing.two, paddingVertical: Spacing.one, paddingRight: Spacing.three },
  filterChip: { paddingHorizontal: Spacing.three, paddingVertical: Spacing.one, borderRadius: 999 },
  chipActive: { color: '#fff', fontWeight: '700' },
  card: { padding: Spacing.four, borderRadius: Spacing.three, gap: Spacing.three },
  front: { fontSize: 24, lineHeight: 32 },
  divider: { height: StyleSheet.hairlineWidth, marginVertical: Spacing.one },
  showBtn: { paddingVertical: Spacing.three, borderRadius: Spacing.three, alignItems: 'center' },
  showBtnText: { color: '#fff', fontWeight: '700', fontSize: 16 },
  gradeRow: { flexDirection: 'row', gap: Spacing.two },
  gradeBtn: { flex: 1, paddingVertical: Spacing.three, borderRadius: Spacing.two, alignItems: 'center' },
  pad: { paddingVertical: Spacing.four, textAlign: 'center' },
});
