import { chat } from '@chat-app/shared';
import type { ConversationSummary, DecryptedMessage } from '@chat-app/shared/chat';
import { Stack, useLocalSearchParams } from 'expo-router';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  ActivityIndicator,
  FlatList,
  KeyboardAvoidingView,
  Platform,
  Pressable,
  StyleSheet,
  Text,
  TextInput,
  View,
} from 'react-native';

import { useAuth } from '../../../lib/authContext';
import { supabase } from '../../../lib/supabase';
import { colors } from '../../../theme/colors';

// Phase 1 conversation detail: fetch + decrypt last 50 messages, render
// them newest-at-bottom, and let the user send a text message. No
// realtime subscription, no attachments, no edit/delete — those are
// later phases. Pull-to-refresh re-fetches.
export default function ConversationDetail() {
  const { id } = useLocalSearchParams<{ id: string }>();
  const { user, device, ownPrivateKey } = useAuth();
  const [conversation, setConversation] = useState<ConversationSummary | null>(null);
  const [messages, setMessages] = useState<DecryptedMessage[] | null>(null);
  const [text, setText] = useState('');
  const [sending, setSending] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const listRef = useRef<FlatList<DecryptedMessage>>(null);

  const load = useCallback(async () => {
    if (!id || !device || !ownPrivateKey) return;
    setError(null);
    try {
      const all = await chat.listConversations(supabase);
      const conv = all.find((c) => c.id === id) ?? null;
      setConversation(conv);

      const ciphers = await chat.fetchConversationMessages(supabase, id, 50);
      const decrypted = await chat.decryptMessages({
        client: supabase,
        messages: ciphers,
        ownDeviceId: device.id,
        ownPrivateKey,
      });
      setMessages(decrypted);
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : 'Nachrichten konnten nicht geladen werden');
    }
  }, [id, device, ownPrivateKey]);

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

  const members = useMemo(() => conversation?.members ?? [], [conversation]);
  const senderName = useCallback(
    (senderId: string) => {
      if (senderId === user?.id) return 'Du';
      const m = members.find((mm) => mm.userId === senderId);
      return m?.profile?.displayName ?? m?.profile?.username ?? 'Unbekannt';
    },
    [members, user],
  );

  const title =
    conversation?.type === 'group'
      ? (conversation.name ?? 'Gruppe')
      : (conversation?.peer?.displayName ?? '…');

  async function handleSend() {
    if (!text.trim() || !user || !device || !ownPrivateKey || !id || sending) return;
    setSending(true);
    setError(null);
    try {
      await chat.sendEncryptedMessage({
        client: supabase,
        conversationId: id,
        plaintext: text.trim(),
        senderUserId: user.id,
        senderDeviceId: device.id,
        senderPrivateKey: ownPrivateKey,
      });
      setText('');
      await load();
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : 'Senden fehlgeschlagen');
    } finally {
      setSending(false);
    }
  }

  return (
    <KeyboardAvoidingView
      style={styles.container}
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      keyboardVerticalOffset={Platform.OS === 'ios' ? 80 : 0}
    >
      <Stack.Screen
        options={{
          title,
          headerStyle: { backgroundColor: colors.bg },
          headerTitleStyle: { color: colors.text },
          headerBackTitle: 'Chats',
        }}
      />

      {messages === null && !error && (
        <View style={styles.loading}>
          <ActivityIndicator color={colors.accent} />
        </View>
      )}

      {error && <Text style={styles.error}>{error}</Text>}

      {messages && (
        <FlatList
          ref={listRef}
          data={messages}
          keyExtractor={(m) => m.id}
          contentContainerStyle={styles.listContent}
          renderItem={({ item }) => (
            <MessageRow
              senderName={senderName(item.senderId)}
              mine={item.senderId === user?.id}
              body={item.plaintext ?? '🔒 [Entschlüsselung fehlgeschlagen]'}
              time={new Date(item.createdAt).toLocaleTimeString('de-DE', {
                hour: '2-digit',
                minute: '2-digit',
              })}
            />
          )}
          onContentSizeChange={() => listRef.current?.scrollToEnd({ animated: false })}
        />
      )}

      <View style={styles.inputRow}>
        <TextInput
          value={text}
          onChangeText={setText}
          placeholder="Nachricht schreiben…"
          placeholderTextColor={colors.textDim}
          style={styles.input}
          multiline
          editable={!sending}
        />
        <Pressable
          style={[styles.sendBtn, (!text.trim() || sending) && styles.sendBtnDisabled]}
          disabled={!text.trim() || sending}
          onPress={handleSend}
        >
          {sending ? (
            <ActivityIndicator color={colors.text} />
          ) : (
            <Text style={styles.sendBtnText}>Senden</Text>
          )}
        </Pressable>
      </View>
    </KeyboardAvoidingView>
  );
}

function MessageRow({
  senderName,
  mine,
  body,
  time,
}: {
  senderName: string;
  mine: boolean;
  body: string;
  time: string;
}) {
  return (
    <View style={[styles.bubbleWrap, mine ? styles.bubbleWrapMine : styles.bubbleWrapOther]}>
      <View style={[styles.bubble, mine ? styles.bubbleMine : styles.bubbleOther]}>
        {!mine && <Text style={styles.sender}>{senderName}</Text>}
        <Text style={styles.body}>{body}</Text>
        <Text style={styles.time}>{time}</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: colors.bg },
  loading: { flex: 1, alignItems: 'center', justifyContent: 'center' },
  error: { color: colors.danger, padding: 12, textAlign: 'center' },
  listContent: { padding: 12, gap: 6 },
  bubbleWrap: { flexDirection: 'row', marginVertical: 2 },
  bubbleWrapMine: { justifyContent: 'flex-end' },
  bubbleWrapOther: { justifyContent: 'flex-start' },
  bubble: { maxWidth: '78%', padding: 10, borderRadius: 14 },
  bubbleMine: { backgroundColor: colors.accent },
  bubbleOther: { backgroundColor: colors.surface, borderColor: colors.border, borderWidth: 1 },
  sender: { color: colors.textMuted, fontSize: 11, fontWeight: '600', marginBottom: 4 },
  body: { color: colors.text, fontSize: 15, lineHeight: 20 },
  time: { color: colors.textDim, fontSize: 10, marginTop: 4, textAlign: 'right' },
  inputRow: {
    flexDirection: 'row',
    alignItems: 'flex-end',
    padding: 8,
    gap: 8,
    borderTopWidth: 1,
    borderTopColor: colors.border,
    backgroundColor: colors.surface,
  },
  input: {
    flex: 1,
    minHeight: 40,
    maxHeight: 120,
    color: colors.text,
    backgroundColor: colors.bg,
    borderColor: colors.border,
    borderWidth: 1,
    borderRadius: 10,
    paddingHorizontal: 12,
    paddingVertical: 10,
    fontSize: 15,
  },
  sendBtn: {
    backgroundColor: colors.accent,
    borderRadius: 10,
    paddingHorizontal: 16,
    height: 40,
    alignItems: 'center',
    justifyContent: 'center',
  },
  sendBtnDisabled: { opacity: 0.5 },
  sendBtnText: { color: colors.text, fontWeight: '600' },
});
