import { useState, useCallback, useEffect } from 'react';
import {
  View,
  Text,
  FlatList,
  TouchableOpacity,
  TextInput,
  ActivityIndicator,
  RefreshControl,
  StyleSheet,
} from 'react-native';
import { useRouter } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { apiFetch } from '../../lib/api';
import { supabase } from '../../lib/supabase';
import { useAuthStore } from '../../stores/auth';
import { AppHeader } from '../../components/AppHeader';
import { UserAvatar } from '../../components/UserAvatar';
import { useColors } from '../../lib/theme';

type DmConversation = {
  partnerId: string;
  partnerName: string;
  partnerAvatar: string | null;
  lastMessage: string;
  lastAttachmentType?: string | null;
  lastMessageAt: string;
  unreadCount: number;
  isOwn: boolean;
};

function formatTime(ts: string, justNowLabel: string): string {
  const diff = Date.now() - new Date(ts).getTime();
  const day = 86_400_000;
  if (diff < 60_000) return justNowLabel;
  if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m`;
  if (diff < day) return `${Math.floor(diff / 3_600_000)}h`;
  if (diff < 7 * day) return new Date(ts).toLocaleDateString('de-DE', { weekday: 'short' });
  if (diff < 30 * day) return `${Math.floor(diff / day)}d`;
  if (diff < 60 * day) return `${Math.floor(diff / (7 * day))}w`;
  if (diff < 365 * day) return `${Math.floor(diff / (30 * day))}mo`;
  return `${Math.floor(diff / (365 * day))}y`;
}

function DmItem({ conv, onPress }: { conv: DmConversation; onPress: () => void }) {
  const { t } = useTranslation();
  const colors = useColors();
  const styles = makeStyles(colors);
  const hasUnread = conv.unreadCount > 0;

  return (
    <TouchableOpacity onPress={onPress} activeOpacity={0.7}>
      <View style={styles.dmRow}>
        <UserAvatar
          userId={conv.partnerId}
          avatar={conv.partnerAvatar}
          nickname={conv.partnerName}
          size="md"
        />
        <View style={styles.dmInfo}>
          <View style={styles.dmHeaderRow}>
            <Text style={styles.dmName} numberOfLines={1}>
              {conv.partnerName}
            </Text>
            <Text style={[styles.dmTime, { color: hasUnread ? colors.brandOrange : colors.textMuted }]}>
              {formatTime(conv.lastMessageAt, t('chat.just_now'))}
            </Text>
          </View>
          <View style={styles.dmBottomRow}>
            <Text
              numberOfLines={1}
              style={[
                styles.dmLast,
                {
                  fontFamily: hasUnread ? 'Nunito_600SemiBold' : 'Nunito_400Regular',
                  color: hasUnread ? colors.text : colors.textMuted,
                },
              ]}
            >
              {conv.isOwn ? `${t('chat.you')} ` : ''}
              {conv.lastMessage ||
                (conv.lastAttachmentType === 'call' ? t('chat.call_audio') :
                 conv.lastAttachmentType === 'audio' ? t('chat.voice_message') :
                 conv.lastAttachmentType === 'image' ? t('chat.photo') :
                 t('chat.media_sent'))}
            </Text>
            {hasUnread && (
              <View style={styles.unreadBadge}>
                <Text style={styles.unreadBadgeText}>
                  {conv.unreadCount > 99 ? '99+' : conv.unreadCount}
                </Text>
              </View>
            )}
          </View>
        </View>
      </View>
    </TouchableOpacity>
  );
}

export default function ChatScreen() {
  const { t } = useTranslation();
  const router = useRouter();
  const colors = useColors();
  const styles = makeStyles(colors);
  const queryClient = useQueryClient();
  const myUserId = useAuthStore((s) => s.user?.id);
  const [search, setSearch] = useState('');
  const [userRefreshing, setUserRefreshing] = useState(false);
  const [debouncedSearch, setDebouncedSearch] = useState('');

  // 300ms debounce für User-Suche
  useEffect(() => {
    const t = setTimeout(() => setDebouncedSearch(search.trim()), 300);
    return () => clearTimeout(t);
  }, [search]);

  const {
    data: convs = [],
    isLoading: loadingDms,
    refetch: refetchDms,
  } = useQuery<DmConversation[]>({
    queryKey: ['dm-conversations'],
    queryFn: () => apiFetch('/api/chat/dm-conversations'),
    staleTime: 30_000,
  });

  // Realtime: bei jeder neuen DM/Anruf (eingehend ODER von mir, auch von einem
  // anderen Gerät) die Konversationsliste neu laden → sie re-sortiert sich live
  // (neueste zuerst). Anrufe sind Rows in direct_messages (attachment_type=call),
  // werden also vom selben Insert-Listener mitgefangen.
  useEffect(() => {
    if (!myUserId) return;
    let channel: ReturnType<typeof supabase.channel> | null = null;
    let cancelled = false;
    let reconnectTimer: ReturnType<typeof setTimeout> | null = null;

    const bump = () => {
      queryClient.invalidateQueries({ queryKey: ['dm-conversations'] });
    };

    async function subscribe() {
      const { data } = await supabase.auth.getSession();
      if (cancelled || !data.session?.access_token) return;
      channel = supabase
        .channel(`dm-list:${myUserId}:${Date.now()}`)
        .on('postgres_changes', {
          event: 'INSERT', schema: 'rebreak', table: 'direct_messages',
          filter: `receiver_id=eq.${myUserId}`,
        }, bump)
        .on('postgres_changes', {
          event: 'INSERT', schema: 'rebreak', table: 'direct_messages',
          filter: `sender_id=eq.${myUserId}`,
        }, bump)
        .subscribe((status: string) => {
          if (status === 'CHANNEL_ERROR' || status === 'TIMED_OUT') {
            if (channel) { supabase.removeChannel(channel); channel = null; }
            if (reconnectTimer) clearTimeout(reconnectTimer);
            reconnectTimer = setTimeout(() => { if (!cancelled) subscribe(); }, 3000);
          }
        });
    }

    subscribe();
    return () => {
      cancelled = true;
      if (reconnectTimer) clearTimeout(reconnectTimer);
      if (channel) supabase.removeChannel(channel);
    };
  }, [myUserId, queryClient]);

  const handleRefresh = useCallback(async () => {
    setUserRefreshing(true);
    try {
      await refetchDms();
    } finally {
      setUserRefreshing(false);
    }
  }, [refetchDms]);

  // Newest-first: der Server liefert nach partner_id sortiert (DISTINCT ON), NICHT
  // nach Aktualität → hier client-seitig nach lastMessageAt absteigend sortieren.
  const sorted = [...convs].sort(
    (a, b) => new Date(b.lastMessageAt).getTime() - new Date(a.lastMessageAt).getTime(),
  );
  const filtered = search.trim()
    ? sorted.filter((c) =>
        c.partnerName.toLowerCase().includes(search.toLowerCase()) ||
        c.lastMessage.toLowerCase().includes(search.toLowerCase()),
      )
    : sorted;

  // Zweite Stufe: User-Suche (nur wenn Suchbegriff ≥ 2 Zeichen)
  const {
    data: userResults = [],
    isFetching: searchingUsers,
  } = useQuery<{ id: string; nickname: string; avatar: string | null }[]>({
    queryKey: ['user-search', debouncedSearch],
    queryFn: () => apiFetch(`/api/users/search?q=${encodeURIComponent(debouncedSearch)}`),
    enabled: debouncedSearch.length >= 2,
    staleTime: 10_000,
  });

  // Bereits gechattet? User-Resultate ohne aktive Conversations zeigen
  const existingPartnerIds = new Set(convs.map((c) => c.partnerId));
  const newUsers = userResults.filter((u) => !existingPartnerIds.has(u.id));

  const openDm = useCallback(
    (userId: string) => {
      router.push(`/dm?userId=${userId}`);
    },
    [router],
  );

  return (
    <View style={styles.container}>
      <AppHeader />

      <View style={styles.headerSection}>
        <View style={styles.searchRow}>
          <Ionicons name="search-outline" size={16} color={colors.textMuted} style={styles.searchIcon} />
          <TextInput
            style={styles.searchInput}
            value={search}
            onChangeText={setSearch}
            placeholder={t('chat.search_placeholder')}
            placeholderTextColor={colors.textMuted}
            returnKeyType="search"
            autoCorrect={false}
            autoCapitalize="none"
          />
          {search.length > 0 && (
            <TouchableOpacity onPress={() => setSearch('')} activeOpacity={0.7} hitSlop={8}>
              <Ionicons name="close-circle" size={16} color={colors.textMuted} />
            </TouchableOpacity>
          )}
        </View>
      </View>

      <FlatList
        data={loadingDms ? [] : filtered}
        keyExtractor={(item) => item.partnerId}
        refreshControl={
          <RefreshControl
            refreshing={userRefreshing}
            onRefresh={handleRefresh}
            tintColor={colors.brandOrange}
          />
        }
        ListEmptyComponent={
          loadingDms ? (
            <View style={styles.emptyBox}>
              <ActivityIndicator color={colors.brandOrange} />
            </View>
          ) : (
            <View style={styles.emptyBox}>
              <Ionicons name="chatbubble-ellipses-outline" size={42} color="#d4d4d4" />
              <Text style={styles.emptyText}>{t('chat.no_chats')}</Text>
            </View>
          )
        }
        renderItem={({ item }) => <DmItem conv={item} onPress={() => openDm(item.partnerId)} />}
        ListFooterComponent={
          debouncedSearch.length >= 2 ? (
            <View style={{ paddingBottom: 100 }}>
              <View style={styles.newConvHeader}>
                <Text style={[styles.newConvLabel, { color: colors.textMuted }]}>
                  {t('chat.new_conversation')}
                </Text>
                {searchingUsers && <ActivityIndicator size="small" color={colors.brandOrange} />}
              </View>
              {newUsers.length === 0 && !searchingUsers ? (
                <View style={styles.emptyBox}>
                  <Text style={styles.emptyText}>{t('chat.no_users_found')}</Text>
                </View>
              ) : (
                newUsers.map((u) => (
                  <TouchableOpacity
                    key={u.id}
                    onPress={() => openDm(u.id)}
                    activeOpacity={0.7}
                  >
                    <View style={styles.dmRow}>
                      <UserAvatar userId={u.id} avatar={u.avatar} nickname={u.nickname} size="md" />
                      <View style={styles.dmInfo}>
                        <Text style={styles.dmName} numberOfLines={1}>{u.nickname}</Text>
                        <Text style={[styles.dmLast, { fontFamily: 'Nunito_400Regular', color: colors.textMuted }]}>
                          {t('chat.start_conversation')}
                        </Text>
                      </View>
                      <Ionicons name="chevron-forward" size={16} color={colors.textMuted} />
                    </View>
                  </TouchableOpacity>
                ))
              )}
            </View>
          ) : (
            <View style={{ paddingBottom: 100 }} />
          )
        }
        contentContainerStyle={{ flexGrow: 1 }}
      />
    </View>
  );
}

function makeStyles(colors: ReturnType<typeof useColors>) {
  return StyleSheet.create({
    container: { flex: 1, backgroundColor: colors.bg },
    headerSection: {
      paddingHorizontal: 16,
      paddingTop: 12,
      paddingBottom: 10,
      backgroundColor: colors.bg,
      borderBottomWidth: StyleSheet.hairlineWidth,
      borderBottomColor: colors.border,
    },
    searchRow: {
      flexDirection: 'row',
      alignItems: 'center',
      backgroundColor: colors.surfaceElevated,
      borderRadius: 999,
      paddingHorizontal: 16,
      paddingVertical: 8,
    },
    searchIcon: { marginRight: 8 },
    searchInput: {
      flex: 1,
      fontSize: 14,
      fontFamily: 'Nunito_500Medium',
      color: colors.text,
      paddingVertical: 0,
    },
    emptyBox: {
      alignItems: 'center',
      justifyContent: 'center',
      paddingVertical: 40,
      paddingHorizontal: 32,
    },
    emptyText: {
      fontSize: 13,
      fontFamily: 'Nunito_600SemiBold',
      color: colors.textMuted,
      marginTop: 12,
    },
    newConvHeader: {
      flexDirection: 'row',
      alignItems: 'center',
      gap: 8,
      paddingHorizontal: 16,
      paddingTop: 20,
      paddingBottom: 8,
      borderTopWidth: StyleSheet.hairlineWidth,
      borderTopColor: colors.border,
    },
    newConvLabel: {
      fontSize: 12,
      fontFamily: 'Nunito_700Bold',
      textTransform: 'uppercase',
      letterSpacing: 0.5,
      flex: 1,
    },
    dmRow: {
      flexDirection: 'row',
      alignItems: 'center',
      gap: 12,
      paddingHorizontal: 16,
      paddingVertical: 12,
      backgroundColor: colors.bg,
      borderBottomWidth: StyleSheet.hairlineWidth,
      borderBottomColor: colors.border,
      minHeight: 68,
    },
    dmInfo: { flex: 1, minWidth: 0 },
    dmHeaderRow: {
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'space-between',
    },
    dmName: {
      fontSize: 15,
      fontFamily: 'Nunito_700Bold',
      color: colors.text,
      flexShrink: 1,
      marginRight: 6,
    },
    dmTime: { fontSize: 11, fontFamily: 'Nunito_500Medium' },
    dmBottomRow: {
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'space-between',
      marginTop: 2,
    },
    dmLast: { fontSize: 12, flex: 1 },
    unreadBadge: {
      minWidth: 20,
      height: 20,
      paddingHorizontal: 6,
      borderRadius: 10,
      backgroundColor: colors.brandOrange,
      alignItems: 'center',
      justifyContent: 'center',
      marginLeft: 8,
    },
    unreadBadgeText: {
      fontSize: 10,
      fontFamily: 'Nunito_700Bold',
      color: '#fff',
    },
  });
}
