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

import { PreCaptureSheet, type PreCaptureResult } from '@/components/PreCaptureSheet';
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 type { TranscriptMeta } from '@/lib/db';
import { formatClock } from '@/lib/format';
import { MODELS } from '@/lib/models/catalog';
import { pickAudio, type PickedAudio } from '@/lib/pickAudio';
import { useCourses } from '@/stores/coursesStore';
import { useTranscribe } from '@/stores/transcribeStore';
import { useTranscripts, type CourseFilter } from '@/stores/transcriptsStore';

export default function LibraryScreen() {
  const theme = useTheme();
  const router = useRouter();
  const { items, loading, query, setQuery, refresh, remove, courseFilter, setCourseFilter } =
    useTranscripts();
  const courses = useCourses((s) => s.items);
  const refreshCourses = useCourses((s) => s.refresh);
  const job = useTranscribe();
  const [picked, setPicked] = useState<PickedAudio | null>(null);

  useFocusEffect(
    useCallback(() => {
      void refresh();
      void refreshCourses();
    }, [refresh, refreshCourses]),
  );

  const busy = job.status === 'loading' || job.status === 'transcribing';

  const onNew = useCallback(async () => {
    if (busy) return;
    const p = await pickAudio();
    if (p) setPicked(p); // opens the pre-capture sheet
  }, [busy]);

  const onStart = useCallback(
    async (r: PreCaptureResult) => {
      const p = picked;
      setPicked(null);
      if (!p) return;
      const id = await useTranscribe.getState().start(p, r);
      if (id) router.push({ pathname: '/transcript/[id]', params: { id } });
    },
    [picked, router],
  );

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

  return (
    <ThemedView style={styles.fill}>
      <ScrollView contentContainerStyle={styles.content}>
        <View style={styles.headerRow}>
          <View style={styles.flex}>
            <ThemedText type="subtitle">Wisp</ThemedText>
            <ThemedText type="small" themeColor="textSecondary">
              Private transcription — runs on your device, nothing uploaded.
            </ThemedText>
          </View>
          <View style={styles.headerLinks}>
            <Link href="/courses" asChild>
              <Pressable hitSlop={8}>
                <ThemedText type="link" themeColor="textSecondary">Courses</ThemedText>
              </Pressable>
            </Link>
            <Link href="/settings" asChild>
              <Pressable hitSlop={8}>
                <ThemedText type="link" themeColor="textSecondary">⚙ Settings</ThemedText>
              </Pressable>
            </Link>
          </View>
        </View>

        <Pressable
          onPress={onNew}
          disabled={busy}
          style={({ pressed }) => [
            styles.newButton,
            { backgroundColor: '#3c87f7', opacity: busy ? 0.5 : pressed ? 0.85 : 1 },
          ]}>
          <ThemedText style={styles.newButtonText}>＋ New transcription</ThemedText>
        </Pressable>

        {busy && <ActiveJob />}
        {job.status === 'error' && (
          <ThemedView type="backgroundElement" style={styles.card}>
            <ThemedText type="smallBold">Transcription failed</ThemedText>
            <ThemedText type="small" themeColor="textSecondary">{job.error}</ThemedText>
          </ThemedView>
        )}

        <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.filterBar}>
          <FilterChip label="All" active={courseFilter === 'all'} onPress={() => void setCourseFilter('all')} />
          <FilterChip label="Unsorted" active={courseFilter === null} onPress={() => void setCourseFilter(null)} />
          {courses.map((c) => (
            <FilterChip key={c.id} label={c.name} active={courseFilter === c.id} onPress={() => void setCourseFilter(c.id)} />
          ))}
        </ScrollView>

        <TextInput
          value={query}
          onChangeText={(t) => void setQuery(t)}
          placeholder="Search transcripts…"
          placeholderTextColor={theme.textSecondary}
          style={[styles.search, { color: theme.text, backgroundColor: theme.backgroundElement }]}
        />

        {loading && items.length === 0 ? (
          <ActivityIndicator style={styles.pad} />
        ) : items.length === 0 ? (
          <ThemedText type="small" themeColor="textSecondary" style={styles.pad}>
            {query ? 'No matches.' : 'No transcripts here yet. Pick an audio or video file to begin.'}
          </ThemedText>
        ) : (
          items.map((t) => (
            <TranscriptRow
              key={t.id}
              item={t}
              courseName={courseName(t.courseId)}
              onOpen={() => router.push({ pathname: '/transcript/[id]', params: { id: t.id } })}
              onDelete={() => void remove(t.id)}
            />
          ))
        )}
      </ScrollView>

      <PreCaptureSheet
        visible={picked !== null}
        defaultTitle={picked?.name ?? 'Recording'}
        onStart={(r) => void onStart(r)}
        onCancel={() => setPicked(null)}
      />
    </ThemedView>
  );
}

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

function ActiveJob() {
  const { stage, progress, partial, cancel } = useTranscribe();
  const pct = Math.round(progress * 100);
  return (
    <ThemedView type="backgroundElement" style={styles.card}>
      <View style={styles.rowBetween}>
        <ThemedText type="smallBold">
          {stage === 'loading' ? 'Loading model…' : 'Transcribing…'} {pct}%
        </ThemedText>
        <Pressable onPress={cancel} hitSlop={8}>
          <ThemedText type="small" themeColor="textSecondary">Cancel</ThemedText>
        </Pressable>
      </View>
      <ProgressBar value={progress} />
      {partial.length > 0 && (
        <ThemedText type="small" themeColor="textSecondary" numberOfLines={3}>
          {partial.map((s) => s.text).join(' ')}
        </ThemedText>
      )}
    </ThemedView>
  );
}

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

function TranscriptRow({
  item,
  courseName,
  onOpen,
  onDelete,
}: {
  item: TranscriptMeta;
  courseName: string | null;
  onOpen: () => void;
  onDelete: () => void;
}) {
  const date = new Date(item.lectureDate ?? item.createdAt).toLocaleDateString();
  return (
    <Pressable onPress={onOpen} style={({ pressed }) => [pressed && styles.pressed]}>
      <ThemedView type="backgroundElement" style={styles.card}>
        <View style={styles.rowBetween}>
          <ThemedText type="smallBold" numberOfLines={1} style={styles.flex}>
            {item.title}
          </ThemedText>
          <Pressable onPress={onDelete} hitSlop={8}>
            <ThemedText type="small" themeColor="textSecondary">✕</ThemedText>
          </Pressable>
        </View>
        <ThemedText type="small" themeColor="textSecondary">
          {courseName ? `${courseName} · ` : ''}
          {date} · {formatClock(item.durationSec)} · {item.segmentCount} segments
        </ThemedText>
      </ThemedView>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  fill: { flex: 1 },
  content: {
    padding: Spacing.three,
    gap: Spacing.three,
    maxWidth: MaxContentWidth,
    width: '100%',
    alignSelf: 'center',
  },
  flex: { flex: 1 },
  headerRow: { flexDirection: 'row', alignItems: 'flex-start', gap: Spacing.two },
  headerLinks: { flexDirection: 'row', gap: Spacing.three, alignItems: 'center' },
  newButton: { paddingVertical: Spacing.three, borderRadius: Spacing.three, alignItems: 'center' },
  newButtonText: { color: '#fff', fontWeight: '700', fontSize: 16 },
  card: { padding: Spacing.three, borderRadius: Spacing.three, gap: Spacing.two },
  rowBetween: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: Spacing.two },
  filterBar: { gap: Spacing.two, paddingVertical: Spacing.one, paddingRight: Spacing.three },
  filterChip: { paddingHorizontal: Spacing.three, paddingVertical: Spacing.one, borderRadius: 999 },
  chipActive: { color: '#fff', fontWeight: '700' },
  search: { borderRadius: Spacing.two, paddingHorizontal: Spacing.three, paddingVertical: Spacing.two, fontSize: 15 },
  track: { height: 6, borderRadius: 3, backgroundColor: '#88888833', overflow: 'hidden' },
  bar: { height: 6, borderRadius: 3, backgroundColor: '#3c87f7' },
  pad: { paddingVertical: Spacing.four, textAlign: 'center' },
  pressed: { opacity: 0.7 },
});
