import { useState, useEffect, useRef, useCallback } from 'react';
import {
  View,
  Text,
  FlatList,
  Pressable,
  TouchableOpacity,
  Modal,
  TextInput,
  ActivityIndicator,
  Platform,
  Alert,
  StyleSheet,
  ScrollView,
  Keyboard,
  KeyboardAvoidingView,
} from 'react-native';
import { Image } from 'expo-image';
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
import { useRouter, useLocalSearchParams } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import * as ImagePicker from 'expo-image-picker';
// TODO(sdk54): migrate to new expo-file-system class-based API (File/Directory/Paths) — see Task #14
import * as FileSystem from 'expo-file-system/legacy';
import { apiFetch } from '../lib/api';
import { supabase } from '../lib/supabase';
import { ChatBubble, type ChatMsg } from '../components/chat/ChatBubble';
import { ChatInput, type SendPayload } from '../components/chat/ChatInput';
import { useRoomRealtime } from '../hooks/useChatRealtime';
import { useColors } from '../lib/theme';
import { useOnlineUsers } from '../hooks/useOnlineUsers';
import { UserAvatar } from '../components/UserAvatar';

const GROUP_GAP_MS = 5 * 60 * 1000;

type RoomDetail = {
  room: {
    id: string;
    name: string;
    description: string | null;
    isPublic: boolean;
    isDefault: boolean;
    joinMode: 'approval' | 'invite_only' | 'open';
    avatarUrl: string | null;
    inviteCode: string | null;
    memberCount: number;
    createdBy: string;
    myRole: 'owner' | 'admin' | 'member' | null;
    isMember: boolean;
  };
  members: Array<{ userId: string; role: string; nickname: string; avatar: string | null }>;
  messages: Array<any>;
  hasMore: boolean;
};

function decodeBase64(b64: string): Uint8Array {
  const binary = (globalThis as any).atob
    ? (globalThis as any).atob(b64)
    : Buffer.from(b64, 'base64').toString('binary');
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
  return bytes;
}

export default function RoomScreen() {
  const { t } = useTranslation();
  const router = useRouter();
  const insets = useSafeAreaInsets();
  const colors = useColors();
  const styles = makeStyles(colors);
  const queryClient = useQueryClient();
  const flatRef = useRef<FlatList>(null);
  const [myUserId, setMyUserId] = useState<string | undefined>();
  const { isOnline } = useOnlineUsers();

  const { roomId } = useLocalSearchParams<{ roomId: string }>();

  const [keyboardHeight, setKeyboardHeight] = useState(0);
  const [messages, setMessages] = useState<ChatMsg[]>([]);
  const [replyTo, setReplyTo] = useState<{ id: string; nickname: string; content: string } | null>(
    null,
  );
  const [sending, setSending] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [joining, setJoining] = useState(false);
  const [joinStatus, setJoinStatus] = useState<'joined' | 'pending' | null>(null);

  useEffect(() => {
    supabase.auth.getSession().then(({ data }) => setMyUserId(data.session?.user.id));
  }, []);

  useEffect(() => {
    const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
    const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
    const show = Keyboard.addListener(showEvent, (e) => setKeyboardHeight(e.endCoordinates.height));
    const hide = Keyboard.addListener(hideEvent, () => setKeyboardHeight(0));
    return () => {
      show.remove();
      hide.remove();
    };
  }, []);

  const { data, isLoading, refetch } = useQuery<RoomDetail>({
    queryKey: ['chat-room', roomId],
    queryFn: async () => {
      const d = await apiFetch<RoomDetail>(`/api/chat/rooms/${roomId}`);
      const msgs: ChatMsg[] = d.messages.map((m: any) => ({
        id: m.id,
        userId: m.userId,
        nickname: m.nickname,
        avatar: m.avatar,
        content: m.content,
        replyTo: m.replyTo
          ? {
              id: m.replyTo.id,
              userId: m.replyTo.userId,
              nickname: m.replyTo.nickname,
              content: m.replyTo.content,
              attachmentType: m.replyTo.attachmentType ?? null,
            }
          : null,
        attachmentUrl: m.attachmentUrl,
        attachmentType: m.attachmentType,
        attachmentName: m.attachmentName,
        likesCount: m.likesCount ?? 0,
        likedByMe: false,
        createdAt: m.createdAt,
        isOwn: m.isOwn,
      }));
      setMessages(msgs);
      return d;
    },
    enabled: !!roomId,
  });

  const room = data?.room;
  const members = data?.members ?? [];
  const isAdmin = room?.myRole === 'owner' || room?.myRole === 'admin';

  // Realtime: neue Messages anderer User
  const onRoomInsert = useCallback(
    (row: any) => {
      const sender = members.find((m) => m.userId === row.user_id);
      setMessages((prev) => {
        if (prev.some((m) => m.id === row.id)) return prev;
        return [
          ...prev,
          {
            id: row.id,
            userId: row.user_id,
            nickname: sender?.nickname ?? 'Anonym',
            avatar: sender?.avatar ?? null,
            content: row.content ?? '',
            replyTo: null,
            attachmentUrl: row.attachment_url ?? null,
            attachmentType: row.attachment_type ?? null,
            attachmentName: row.attachment_name ?? null,
            likesCount: 0,
            likedByMe: false,
            createdAt: row.created_at,
            isOwn: false,
          },
        ];
      });
    },
    [members],
  );
  useRoomRealtime(roomId, myUserId, onRoomInsert, !!myUserId && !!room?.isMember);

  useEffect(() => {
    if (messages.length > 0) {
      requestAnimationFrame(() => flatRef.current?.scrollToEnd({ animated: true }));
    }
  }, [messages.length]);

  async function handleSend(payload: SendPayload) {
    if (sending || !room?.isMember) return;
    setSending(true);
    try {
      const newMsg = await apiFetch<any>(`/api/chat/rooms/${roomId}/messages`, {
        method: 'POST',
        body: payload,
      });
      setMessages((prev) => [
        ...prev,
        {
          id: newMsg.id,
          userId: myUserId ?? '',
          nickname: 'Du',
          avatar: null,
          content: newMsg.content,
          replyTo: newMsg.replyTo
            ? {
                id: newMsg.replyTo.id,
                userId: newMsg.replyTo.userId,
                nickname: newMsg.replyTo.nickname,
                content: newMsg.replyTo.content,
                attachmentType: newMsg.replyTo.attachmentType ?? null,
              }
            : null,
          attachmentUrl: newMsg.attachmentUrl,
          attachmentType: newMsg.attachmentType,
          attachmentName: newMsg.attachmentName,
          likesCount: 0,
          likedByMe: false,
          createdAt: newMsg.createdAt,
          isOwn: true,
        },
      ]);
      setReplyTo(null);
    } catch (err) {
      console.error('Room send failed:', err);
    } finally {
      setSending(false);
    }
  }

  async function toggleLike(msg: ChatMsg) {
    try {
      const { liked } = await apiFetch<{ liked: boolean }>('/api/chat/like', {
        method: 'POST',
        body: { messageId: msg.id, type: 'chat' },
      });
      setMessages((prev) =>
        prev.map((m) =>
          m.id === msg.id
            ? { ...m, likedByMe: liked, likesCount: m.likesCount + (liked ? 1 : -1) }
            : m,
        ),
      );
    } catch {}
  }

  function startReply(msg: ChatMsg) {
    setReplyTo({
      id: msg.id,
      nickname: msg.nickname ?? '?',
      content: msg.content?.slice(0, 100) || (msg.attachmentType === 'image' ? 'Bild' : ''),
    });
  }

  function sameAuthor(a: ChatMsg | undefined, b: ChatMsg | undefined): boolean {
    if (!a || !b) return false;
    if (a.userId !== b.userId) return false;
    return Math.abs(new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) <= GROUP_GAP_MS;
  }

  async function handleJoin() {
    if (joining) return;
    setJoining(true);
    try {
      const res = await apiFetch<{ status: 'joined' | 'pending' | 'already_member' }>(
        `/api/chat/rooms/${roomId}/join`,
        { method: 'POST' },
      );
      if (res.status === 'pending') {
        setJoinStatus('pending');
      } else {
        setJoinStatus('joined');
        await refetch();
        queryClient.invalidateQueries({ queryKey: ['chat-rooms'] });
      }
    } catch (err: any) {
      Alert.alert('Fehler', err?.message ?? 'Beitritt fehlgeschlagen');
    } finally {
      setJoining(false);
    }
  }

  async function handleAvatarUpload() {
    const perm = await ImagePicker.requestMediaLibraryPermissionsAsync();
    if (!perm.granted) return;
    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ['images'],
      quality: 0.8,
      allowsEditing: true,
      aspect: [1, 1],
    });
    if (result.canceled || !result.assets[0]) return;
    const asset = result.assets[0];
    try {
      const ext = asset.uri.split('.').pop()?.toLowerCase() || 'jpg';
      const path = `room-avatars/${roomId}-${Date.now()}.${ext}`;
      const b64 = await FileSystem.readAsStringAsync(asset.uri, {
        encoding: FileSystem.EncodingType.Base64,
      });
      const bytes = decodeBase64(b64);
      const { error: upErr } = await supabase.storage
        .from('rebreak-public')
        .upload(path, bytes, {
          contentType: asset.mimeType ?? `image/${ext}`,
          upsert: true,
        });
      if (upErr) throw upErr;
      const { data: pub } = supabase.storage.from('rebreak-public').getPublicUrl(path);
      await apiFetch(`/api/chat/rooms/${roomId}`, {
        method: 'PATCH',
        body: { avatarUrl: pub.publicUrl },
      });
      await refetch();
      queryClient.invalidateQueries({ queryKey: ['chat-rooms'] });
    } catch (err: any) {
      Alert.alert('Fehler', err?.message ?? t('chat.upload_failed'));
    }
  }

  const initials = (room?.name ?? '?')
    .split(' ')
    .slice(0, 2)
    .map((w) => w[0]?.toUpperCase() ?? '')
    .join('');

  return (
    <SafeAreaView style={styles.container} edges={['top']}>
      {/* Header */}
      <View style={styles.header}>
        <TouchableOpacity style={styles.iconBtn} onPress={() => router.back()} hitSlop={8} activeOpacity={0.7}>
          <Ionicons name="chevron-back" size={22} color={colors.text} />
        </TouchableOpacity>
        <View style={styles.headerCenter}>
          <View style={styles.headerAvatar}>
            {room?.avatarUrl ? (
              <Image source={{ uri: room.avatarUrl }} style={styles.headerAvatarImg} contentFit="cover" />
            ) : (
              <Text style={styles.headerAvatarInitials}>{initials}</Text>
            )}
          </View>
          <View style={{ flexShrink: 1 }}>
            <Text style={styles.headerName} numberOfLines={1}>
              {room?.name ?? '…'}
            </Text>
            {room && (() => {
              const onlineCount = members.filter((m) => isOnline(m.userId)).length;
              return (
                <Text style={styles.headerSub} numberOfLines={1}>
                  {onlineCount > 0
                    ? t('chat.member_count_online', { n: room.memberCount, online: onlineCount })
                    : t('chat.member_count', { n: room.memberCount })}
                </Text>
              );
            })()}
          </View>
        </View>
        <TouchableOpacity style={styles.iconBtn} onPress={() => setSettingsOpen(true)} hitSlop={8} activeOpacity={0.7}>
          <Ionicons name="ellipsis-horizontal" size={20} color={colors.text} />
        </TouchableOpacity>
      </View>

      {isLoading || !room ? (
        <View style={styles.loadingBox}>
          <ActivityIndicator color={colors.brandOrange} />
        </View>
      ) : !room.isMember ? (
        <View style={styles.joinBox}>
          <Ionicons name="people" size={48} color="#d4d4d4" />
          <Text style={styles.joinTitle}>{room.name}</Text>
          {room.description && <Text style={styles.joinDesc}>{room.description}</Text>}
          <Text style={styles.joinHint}>{t('chat.join_required')}</Text>
          {joinStatus === 'pending' ? (
            <View style={styles.pendingBadge}>
              <Ionicons name="time-outline" size={14} color="#92400e" />
              <Text style={styles.pendingText}>{t('chat.join_pending')}</Text>
            </View>
          ) : (
            <TouchableOpacity
              onPress={handleJoin}
              disabled={joining}
              activeOpacity={0.7}
              style={[styles.joinBtn, joining && { opacity: 0.7 }]}
            >
              {joining ? (
                <ActivityIndicator color="#fff" />
              ) : (
                <Text style={styles.joinBtnText}>{t('chat.join')}</Text>
              )}
            </TouchableOpacity>
          )}
        </View>
      ) : (
        <KeyboardAvoidingView
          style={{ flex: 1 }}
          behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
          keyboardVerticalOffset={0}
        >
          <FlatList
            ref={flatRef}
            data={messages}
            style={{ flex: 1 }}
            renderItem={({ item, index }) => (
              <ChatBubble
                msg={item}
                showName
                isFirstInGroup={!sameAuthor(messages[index - 1], item)}
                isLastInGroup={!sameAuthor(item, messages[index + 1])}
                hideReadStatus
                onReply={startReply}
                onLike={toggleLike}
                onOpenImage={() => {}}
              />
            )}
            keyExtractor={(m) => m.id}
            contentContainerStyle={{ paddingTop: 12, paddingBottom: 8 }}
            showsVerticalScrollIndicator={false}
            onContentSizeChange={() => flatRef.current?.scrollToEnd({ animated: false })}
          />
          <View style={{ paddingBottom: keyboardHeight > 0 ? 8 : Math.max(12, insets.bottom), backgroundColor: colors.bg }}>
            <ChatInput
              replyTo={replyTo}
              sending={sending}
              onSend={handleSend}
              onCancelReply={() => setReplyTo(null)}
            />
          </View>
        </KeyboardAvoidingView>
      )}

      {/* Settings Modal */}
      <RoomSettingsModal
        visible={settingsOpen}
        onClose={() => setSettingsOpen(false)}
        room={room}
        members={members}
        isAdmin={isAdmin}
        onAvatarChange={handleAvatarUpload}
        onRefetch={refetch}
        roomId={roomId}
      />
    </SafeAreaView>
  );
}

// ----- Settings Modal -----

function RoomSettingsModal({
  visible,
  onClose,
  room,
  members,
  isAdmin,
  onAvatarChange,
  onRefetch,
  roomId,
}: {
  visible: boolean;
  onClose: () => void;
  room: RoomDetail['room'] | undefined;
  members: RoomDetail['members'];
  isAdmin: boolean;
  onAvatarChange: () => void;
  onRefetch: () => void;
  roomId: string;
}) {
  const { t } = useTranslation();
  const colors = useColors();
  const modal = makeModalStyles(colors);
  const [pendingRequests, setPendingRequests] = useState<any[]>([]);
  const [loadingReqs, setLoadingReqs] = useState(false);

  useEffect(() => {
    if (!visible || !isAdmin) return;
    setLoadingReqs(true);
    apiFetch<{ requests: any[] }>(`/api/chat/rooms/${roomId}`, {
      method: 'PATCH',
      body: { action: 'list_requests' },
    })
      .then((d: any) => setPendingRequests(d?.requests ?? d ?? []))
      .catch(() => setPendingRequests([]))
      .finally(() => setLoadingReqs(false));
  }, [visible, isAdmin, roomId]);

  async function handleRequest(userId: string, action: 'approve' | 'reject') {
    try {
      await apiFetch(`/api/chat/rooms/${roomId}`, {
        method: 'PATCH',
        body: { action, userId },
      });
      setPendingRequests((prev) => prev.filter((r) => r.userId !== userId));
      onRefetch();
    } catch (err: any) {
      Alert.alert('Fehler', err?.message ?? 'Aktion fehlgeschlagen');
    }
  }

  async function handlePromote(userId: string) {
    try {
      await apiFetch(`/api/chat/rooms/${roomId}`, {
        method: 'PATCH',
        body: { action: 'promote_admin', userId },
      });
      onRefetch();
    } catch (err: any) {
      Alert.alert('Fehler', err?.message ?? 'Aktion fehlgeschlagen');
    }
  }

  async function handleBan(userId: string) {
    Alert.alert('Bannen?', 'User wird aus dem Raum entfernt.', [
      { text: 'Abbrechen', style: 'cancel' },
      {
        text: 'Bannen',
        style: 'destructive',
        onPress: async () => {
          try {
            await apiFetch(`/api/chat/rooms/${roomId}`, {
              method: 'PATCH',
              body: { action: 'ban', userId },
            });
            onRefetch();
          } catch (err: any) {
            Alert.alert('Fehler', err?.message ?? 'Aktion fehlgeschlagen');
          }
        },
      },
    ]);
  }

  async function handleLeave() {
    Alert.alert(t('chat.leave_room'), '', [
      { text: 'Abbrechen', style: 'cancel' },
      {
        text: t('chat.leave_room'),
        style: 'destructive',
        onPress: async () => {
          try {
            await apiFetch(`/api/chat/rooms/${roomId}/leave`, { method: 'POST' });
            onClose();
          } catch (err: any) {
            Alert.alert('Fehler', err?.message ?? 'Verlassen fehlgeschlagen');
          }
        },
      },
    ]);
  }

  if (!room) return null;

  return (
    <Modal visible={visible} animationType="slide" presentationStyle="pageSheet" onRequestClose={onClose}>
      <SafeAreaView style={modal.container} edges={['top']}>
        <View style={modal.header}>
          <TouchableOpacity onPress={onClose} hitSlop={8} activeOpacity={0.7}>
            <Ionicons name="close" size={24} color="#0a0a0a" />
          </TouchableOpacity>
          <Text style={modal.title}>{t('chat.settings')}</Text>
          <View style={{ width: 24 }} />
        </View>

        <ScrollView contentContainerStyle={{ padding: 16, paddingBottom: 60 }}>
          {/* Avatar + Name */}
          <View style={modal.section}>
            <TouchableOpacity
              onPress={isAdmin ? onAvatarChange : undefined}
              activeOpacity={0.7}
              style={modal.avatarWrap}
            >
              {room.avatarUrl ? (
                <Image source={{ uri: room.avatarUrl }} style={modal.avatar} contentFit="cover" />
              ) : (
                <View style={[modal.avatar, modal.avatarPlaceholder]}>
                  <Ionicons name="people" size={32} color="#737373" />
                </View>
              )}
              {isAdmin && (
                <View style={modal.avatarEdit}>
                  <Ionicons name="camera" size={14} color="#fff" />
                </View>
              )}
            </TouchableOpacity>
            <Text style={modal.roomName}>{room.name}</Text>
            {room.description && <Text style={modal.roomDesc}>{room.description}</Text>}
          </View>

          {/* Pending Requests */}
          {isAdmin && (
            <View style={modal.section}>
              <Text style={modal.sectionTitle}>{t('chat.pending_request')}</Text>
              {loadingReqs ? (
                <ActivityIndicator color={colors.brandOrange} style={{ marginVertical: 12 }} />
              ) : pendingRequests.length === 0 ? (
                <Text style={modal.emptyText}>—</Text>
              ) : (
                pendingRequests.map((req) => (
                  <View key={req.userId} style={modal.memberRow}>
                    <View style={{ flex: 1 }}>
                      <Text style={modal.memberName}>{req.nickname ?? 'Anonym'}</Text>
                    </View>
                    <TouchableOpacity
                      style={[modal.actionBtn, { backgroundColor: '#dcfce7' }]}
                      onPress={() => handleRequest(req.userId, 'approve')}
                      activeOpacity={0.7}
                    >
                      <Text style={[modal.actionText, { color: '#166534' }]}>
                        {t('chat.approve')}
                      </Text>
                    </TouchableOpacity>
                    <TouchableOpacity
                      style={[modal.actionBtn, { backgroundColor: '#fee2e2', marginLeft: 6 }]}
                      onPress={() => handleRequest(req.userId, 'reject')}
                      activeOpacity={0.7}
                    >
                      <Text style={[modal.actionText, { color: '#991b1b' }]}>
                        {t('chat.reject')}
                      </Text>
                    </TouchableOpacity>
                  </View>
                ))
              )}
            </View>
          )}

          {/* Members */}
          <View style={modal.section}>
            <Text style={modal.sectionTitle}>
              {t('chat.members')} ({members.length})
            </Text>
            {members.map((m) => (
              <View key={m.userId} style={modal.memberRow}>
                <View style={{ marginRight: 10 }}>
                  <UserAvatar
                    userId={m.userId}
                    avatar={m.avatar}
                    nickname={m.nickname}
                    size="md"
                  />
                </View>
                <View style={{ flex: 1 }}>
                  <Text style={modal.memberName}>{m.nickname}</Text>
                  {m.role !== 'member' && (
                    <Text style={modal.memberRole}>{m.role}</Text>
                  )}
                </View>
                {isAdmin && m.role === 'member' && (
                  <>
                    <TouchableOpacity
                      style={[modal.actionBtn, { backgroundColor: '#fef3c7' }]}
                      onPress={() => handlePromote(m.userId)}
                      activeOpacity={0.7}
                    >
                      <Text style={[modal.actionText, { color: '#92400e' }]}>Admin</Text>
                    </TouchableOpacity>
                    <TouchableOpacity
                      style={[modal.actionBtn, { backgroundColor: '#fee2e2', marginLeft: 6 }]}
                      onPress={() => handleBan(m.userId)}
                      activeOpacity={0.7}
                    >
                      <Text style={[modal.actionText, { color: '#991b1b' }]}>Ban</Text>
                    </TouchableOpacity>
                  </>
                )}
              </View>
            ))}
          </View>

          {/* Leave */}
          {!room.isDefault && (
            <TouchableOpacity style={modal.leaveBtn} onPress={handleLeave} activeOpacity={0.7}>
              <Ionicons name="exit-outline" size={18} color="#991b1b" />
              <Text style={modal.leaveText}>{t('chat.leave_room')}</Text>
            </TouchableOpacity>
          )}
        </ScrollView>
      </SafeAreaView>
    </Modal>
  );
}

function makeStyles(colors: ReturnType<typeof useColors>) {
  return StyleSheet.create({
    container: { flex: 1, backgroundColor: colors.bg },
    header: {
      flexDirection: 'row',
      alignItems: 'center',
      paddingHorizontal: 12,
      paddingVertical: 10,
      backgroundColor: colors.bg,
      borderBottomWidth: StyleSheet.hairlineWidth,
      borderBottomColor: colors.border,
    },
    iconBtn: {
      padding: 8,
      alignItems: 'center',
      justifyContent: 'center',
    },
    headerCenter: {
      flex: 1,
      flexDirection: 'row',
      alignItems: 'center',
      marginHorizontal: 8,
    },
    headerAvatar: {
      width: 36,
      height: 36,
      borderRadius: 18,
      backgroundColor: colors.surfaceElevated,
      alignItems: 'center',
      justifyContent: 'center',
      overflow: 'hidden',
      marginRight: 8,
    },
    headerAvatarImg: { width: 36, height: 36 },
    headerAvatarInitials: {
      fontSize: 12,
      fontFamily: 'Nunito_700Bold',
      color: colors.textMuted,
    },
    headerName: {
      fontSize: 15,
      fontFamily: 'Nunito_700Bold',
      color: colors.text,
    },
    headerSub: {
      fontSize: 11,
      fontFamily: 'Nunito_500Medium',
      color: colors.textMuted,
      marginTop: 1,
    },
    loadingBox: { flex: 1, alignItems: 'center', justifyContent: 'center' },
    joinBox: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
      paddingHorizontal: 32,
    },
    joinTitle: {
      fontSize: 20,
      fontFamily: 'Nunito_700Bold',
      color: colors.text,
      marginTop: 14,
    },
    joinDesc: {
      fontSize: 13,
      fontFamily: 'Nunito_500Medium',
      color: colors.textMuted,
      marginTop: 6,
      textAlign: 'center',
    },
    joinHint: {
      fontSize: 12,
      fontFamily: 'Nunito_500Medium',
      color: colors.textMuted,
      marginTop: 18,
      textAlign: 'center',
    },
    joinBtn: {
      marginTop: 16,
      backgroundColor: colors.brandOrange,
      paddingHorizontal: 32,
      paddingVertical: 12,
      borderRadius: 12,
      minWidth: 140,
      alignItems: 'center',
    },
    joinBtnText: {
      color: '#fff',
      fontSize: 14,
      fontFamily: 'Nunito_700Bold',
    },
    pendingBadge: {
      flexDirection: 'row',
      alignItems: 'center',
      backgroundColor: '#fef3c7',
      paddingHorizontal: 14,
      paddingVertical: 8,
      borderRadius: 20,
      marginTop: 16,
    },
    pendingText: {
      color: '#92400e',
      fontSize: 12,
      fontFamily: 'Nunito_700Bold',
      marginLeft: 6,
    },
  });
}

function makeModalStyles(colors: ReturnType<typeof useColors>) {
  return StyleSheet.create({
    container: { flex: 1, backgroundColor: colors.bg },
    header: {
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'space-between',
      paddingHorizontal: 16,
      paddingVertical: 12,
      backgroundColor: colors.bg,
      borderBottomWidth: StyleSheet.hairlineWidth,
      borderBottomColor: colors.border,
    },
    title: { fontSize: 16, fontFamily: 'Nunito_700Bold', color: colors.text },
    section: {
      backgroundColor: colors.surface,
      borderRadius: 12,
      padding: 14,
      marginBottom: 12,
    },
    sectionTitle: {
      fontSize: 12,
      fontFamily: 'Nunito_700Bold',
      color: colors.textMuted,
      textTransform: 'uppercase',
      marginBottom: 10,
      letterSpacing: 0.5,
    },
    avatarWrap: { alignSelf: 'center', marginBottom: 10 },
    avatar: { width: 80, height: 80, borderRadius: 40 },
    avatarPlaceholder: {
      backgroundColor: colors.surfaceElevated,
      alignItems: 'center',
      justifyContent: 'center',
    },
    avatarEdit: {
      position: 'absolute',
      right: -2,
      bottom: -2,
      width: 28,
      height: 28,
      borderRadius: 14,
      backgroundColor: colors.brandOrange,
      borderWidth: 3,
      borderColor: colors.bg,
      alignItems: 'center',
      justifyContent: 'center',
    },
    roomName: {
      fontSize: 17,
      fontFamily: 'Nunito_700Bold',
      color: colors.text,
      textAlign: 'center',
    },
    roomDesc: {
      fontSize: 12,
      fontFamily: 'Nunito_500Medium',
      color: colors.textMuted,
      textAlign: 'center',
      marginTop: 4,
    },
    memberRow: {
      flexDirection: 'row',
      alignItems: 'center',
      paddingVertical: 8,
      borderBottomWidth: StyleSheet.hairlineWidth,
      borderBottomColor: colors.border,
    },
    memberName: { fontSize: 13, fontFamily: 'Nunito_600SemiBold', color: colors.text },
    memberRole: { fontSize: 11, color: colors.textMuted, marginTop: 1, textTransform: 'capitalize' },
    actionBtn: {
      paddingHorizontal: 10,
      paddingVertical: 5,
      borderRadius: 6,
    },
    actionText: { fontSize: 11, fontFamily: 'Nunito_700Bold' },
    emptyText: { fontSize: 12, color: colors.textMuted },
    leaveBtn: {
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'center',
      backgroundColor: '#fee2e2',
      paddingVertical: 12,
      borderRadius: 10,
      marginTop: 8,
    },
    leaveText: {
      color: '#991b1b',
      fontSize: 13,
      fontFamily: 'Nunito_700Bold',
      marginLeft: 6,
    },
  });
}
