import { Stack, useFocusEffect, useRouter } from 'expo-router';
import { useCallback, useEffect, useRef, useState } from 'react';
import { ActivityIndicator, Pressable, ScrollView, StyleSheet, TextInput, 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 { formatClock } from '@/lib/format';
import { searchLectures } from '@/lib/search/search';
import type { SearchHit } from '@/lib/search/types';
import { useCourses } from '@/stores/coursesStore';
import { useEmbedding } from '@/stores/embeddingStore';

const ACCENT = '#3c87f7';

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

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

  const { status, progress, pending, refreshPending, buildIndex } = useEmbedding();

  const [query, setQuery] = useState('');
  const [hits, setHits] = useState<SearchHit[]>([]);
  const [searching, setSearching] = useState(false);
  // Distinguish "haven't searched yet" from "searched, got nothing".
  const [searched, setSearched] = useState(false);

  // Refresh courses + pending count whenever the screen gains focus.
  useFocusEffect(
    useCallback(() => {
      void refreshCourses();
      void refreshPending();
    }, [refreshCourses, refreshPending]),
  );

  // Debounced search on query change. The latest run wins (stale guard via seq).
  const seq = useRef(0);
  useEffect(() => {
    const q = query.trim();
    if (!q) {
      setHits([]);
      setSearched(false);
      setSearching(false);
      return;
    }
    const mySeq = ++seq.current;
    setSearching(true);
    const handle = setTimeout(() => {
      void searchLectures(q)
        .then((res) => {
          if (seq.current !== mySeq) return; // a newer query superseded us
          setHits(res);
          setSearched(true);
        })
        .catch(() => {
          if (seq.current !== mySeq) return;
          setHits([]);
          setSearched(true);
        })
        .finally(() => {
          if (seq.current !== mySeq) return;
          setSearching(false);
        });
    }, 250);
    return () => clearTimeout(handle);
  }, [query]);

  const runNow = useCallback(() => {
    const q = query.trim();
    if (!q) return;
    const mySeq = ++seq.current;
    setSearching(true);
    void searchLectures(q)
      .then((res) => {
        if (seq.current !== mySeq) return;
        setHits(res);
        setSearched(true);
      })
      .catch(() => {
        if (seq.current !== mySeq) return;
        setHits([]);
        setSearched(true);
      })
      .finally(() => {
        if (seq.current !== mySeq) return;
        setSearching(false);
      });
  }, [query]);

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

  const openHit = (hit: SearchHit) =>
    router.push({
      pathname: '/transcript/[id]',
      params: { id: hit.transcriptId, t: String(Math.floor(hit.start)) },
    });

  const indexReady = status === 'ready' && pending === 0;

  return (
    <ThemedView style={styles.fill}>
      <Stack.Screen options={{ title: 'Search' }} />
      <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
        <ThemedText type="small" themeColor="textSecondary">
          Semantic search across your lectures — runs entirely on your device.
        </ThemedText>

        {pending > 0 && (
          <ThemedView type="backgroundElement" style={styles.banner}>
            <ThemedText type="smallBold">
              Build search index ({pending} {pending === 1 ? 'lecture' : 'lectures'} pending)
            </ThemedText>
            {status === 'indexing' ? (
              <>
                <ThemedText type="small" themeColor="textSecondary">
                  Indexing… {Math.round(progress * 100)}%
                </ThemedText>
                <ProgressBar value={progress} />
              </>
            ) : (
              <Pressable
                onPress={() => void buildIndex()}
                style={({ pressed }) => [styles.bannerBtn, { opacity: pressed ? 0.85 : 1 }]}>
                <ThemedText style={styles.bannerBtnText}>Build index</ThemedText>
              </Pressable>
            )}
          </ThemedView>
        )}

        <TextInput
          value={query}
          onChangeText={setQuery}
          onSubmitEditing={runNow}
          returnKeyType="search"
          autoFocus
          placeholder="Search your lectures…"
          placeholderTextColor={theme.textSecondary}
          style={[styles.search, { color: theme.text, backgroundColor: theme.backgroundElement }]}
        />

        {searching ? (
          <ActivityIndicator style={styles.pad} />
        ) : query.trim() === '' ? (
          <ThemedText type="small" themeColor="textSecondary" style={styles.pad}>
            {indexReady
              ? 'Type a question or topic to search across your lectures.'
              : 'Build the index to search.'}
          </ThemedText>
        ) : searched && hits.length === 0 ? (
          <ThemedText type="small" themeColor="textSecondary" style={styles.pad}>
            No matches.
          </ThemedText>
        ) : (
          hits.map((hit) => (
            <ResultRow
              key={`${hit.transcriptId}:${hit.segmentId}`}
              hit={hit}
              courseName={courseName(hit.courseId)}
              onPress={() => openHit(hit)}
            />
          ))
        )}
      </ScrollView>
    </ThemedView>
  );
}

function ResultRow({
  hit,
  courseName,
  onPress,
}: {
  hit: SearchHit;
  courseName: string;
  onPress: () => void;
}) {
  return (
    <Pressable onPress={onPress} style={({ pressed }) => [pressed && styles.pressed]}>
      <ThemedView type="backgroundElement" style={styles.card}>
        <ThemedText type="small" numberOfLines={2}>
          {hit.text}
        </ThemedText>
        <ThemedText type="small" themeColor="textSecondary">
          {courseName} · {formatClock(hit.start)}
        </ThemedText>
      </ThemedView>
    </Pressable>
  );
}

function ProgressBar({ value }: { value: number }) {
  return (
    <View style={styles.track}>
      <View style={[styles.bar, { width: `${Math.max(2, Math.min(100, value * 100))}%` }]} />
    </View>
  );
}

const styles = StyleSheet.create({
  fill: { flex: 1 },
  content: {
    padding: Spacing.three,
    gap: Spacing.three,
    maxWidth: MaxContentWidth,
    width: '100%',
    alignSelf: 'center',
  },
  banner: { padding: Spacing.three, borderRadius: Spacing.three, gap: Spacing.two },
  bannerBtn: {
    backgroundColor: ACCENT,
    paddingVertical: Spacing.two,
    borderRadius: Spacing.two,
    alignItems: 'center',
  },
  bannerBtnText: { color: '#fff', fontWeight: '700' },
  search: {
    borderRadius: Spacing.two,
    paddingHorizontal: Spacing.three,
    paddingVertical: Spacing.two,
    fontSize: 15,
  },
  card: { padding: Spacing.three, borderRadius: Spacing.three, gap: Spacing.two },
  track: { height: 6, borderRadius: 3, backgroundColor: '#88888833', overflow: 'hidden' },
  bar: { height: 6, borderRadius: 3, backgroundColor: ACCENT },
  pad: { paddingVertical: Spacing.four, textAlign: 'center' },
  pressed: { opacity: 0.7 },
});
