import React, { useEffect, useMemo, useRef, useState } from "react";
import {
  ActivityIndicator,
  FlatList,
  KeyboardAvoidingView,
  Platform,
  Pressable,
  RefreshControl,
  StyleSheet,
  Text,
  TextInput,
  View,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { useAuth } from "@clerk/clerk-expo";
import { useChat } from "../../contexts/ChatContext";
import { useTheme } from "../../contexts/ThemeContext";
import { MinimalCard } from "../../components/MinimalCard";
import { SectionHeader } from "../../components/SectionHeader";

export default function ChatScreen() {
  const { userId } = useAuth();
  const { colors, typography } = useTheme();
  const {
    threads,
    activeThreadId,
    messagesByThreadId,
    readByThreadId,
    loadingThreads,
    loadingMessages,
    socketConnected,
    totalUnreadCount,
    typingByThreadId,
    setActiveThread,
    refreshMessages,
    refreshThreads,
    sendMessage,
    setTyping,
    loadOlderMessages,
    hasMoreMessages,
    isLoadingOlderMessages,
  } = useChat();

  const [draft, setDraft] = useState("");
  const typingTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const activeMessages = useMemo(
    () => (activeThreadId ? (messagesByThreadId[activeThreadId] ?? []) : []),
    [activeThreadId, messagesByThreadId],
  );

  const typingUsers = useMemo(
    () => (activeThreadId ? (typingByThreadId[activeThreadId] ?? []) : []),
    [activeThreadId, typingByThreadId],
  );

  const activeThread = useMemo(
    () => threads.find((thread) => thread.id === activeThreadId) ?? null,
    [activeThreadId, threads],
  );

  const orderedThreads = useMemo(
    () =>
      [...threads].sort((a, b) => {
        const aTime = a.lastMessageAt ?? a.createdAt;
        const bTime = b.lastMessageAt ?? b.createdAt;
        return new Date(bTime).getTime() - new Date(aTime).getTime();
      }),
    [threads],
  );

  const handleSend = async () => {
    if (!activeThreadId) {
      return;
    }

    const body = draft.trim();
    if (!body) {
      return;
    }

    setDraft("");
    try {
      await sendMessage(activeThreadId, body);
      setTyping(activeThreadId, false);
    } catch {
      setDraft(body);
    }
  };

  const handleDraftChange = (value: string) => {
    setDraft(value);

    if (!activeThreadId) {
      return;
    }

    setTyping(activeThreadId, value.trim().length > 0);

    if (typingTimeoutRef.current) {
      clearTimeout(typingTimeoutRef.current);
    }

    typingTimeoutRef.current = setTimeout(() => {
      if (activeThreadId) {
        setTyping(activeThreadId, false);
      }
    }, 1200);
  };

  const handleLoadOlder = () => {
    if (!activeThreadId) {
      return;
    }

    void loadOlderMessages(activeThreadId);
  };

  useEffect(() => {
    return () => {
      if (typingTimeoutRef.current) {
        clearTimeout(typingTimeoutRef.current);
      }

      if (activeThreadId) {
        setTyping(activeThreadId, false);
      }
    };
  }, [activeThreadId, setTyping]);

  return (
    <View style={[styles.container, { backgroundColor: colors.background }]}>
      <View style={styles.headerWrap}>
        <SectionHeader
          title="Messages"
          subtitle={
            socketConnected
              ? `${totalUnreadCount} unread across chats`
              : "Reconnecting..."
          }
        />
      </View>

      <View style={styles.content}>
        <View style={styles.threadRail}>
          <Text style={[styles.railLabel, typography.label]}>
            Conversations
          </Text>
          {loadingThreads ? (
            <View style={styles.loaderWrap}>
              <ActivityIndicator color={colors.primary} />
            </View>
          ) : (
            <FlatList
              data={orderedThreads}
              keyExtractor={(item) => item.id}
              showsVerticalScrollIndicator={false}
              contentContainerStyle={styles.threadListContent}
              renderItem={({ item }) => {
                const selected = item.id === activeThreadId;
                return (
                  <Pressable onPress={() => setActiveThread(item.id)}>
                    <MinimalCard
                      variant={selected ? "elevated" : "bordered"}
                      padding={10}
                      style={[
                        styles.threadCard,
                        selected && {
                          borderWidth: 1,
                          borderColor: colors.primary,
                        },
                      ]}
                    >
                      <View style={styles.threadCardTopRow}>
                        <View style={styles.threadTypeChip}>
                          <Ionicons
                            name={item.type === "gym" ? "people" : "person"}
                            size={12}
                            color={colors.primary}
                          />
                          <Text
                            style={[
                              styles.threadTypeText,
                              { color: colors.primary },
                            ]}
                          >
                            {item.type === "gym" ? "Gym" : "Direct"}
                          </Text>
                        </View>
                        {item.unreadCount > 0 && (
                          <View
                            style={[
                              styles.threadUnreadBadge,
                              { backgroundColor: colors.danger },
                            ]}
                          >
                            <Text style={styles.threadUnreadText}>
                              {item.unreadCount > 9 ? "9+" : item.unreadCount}
                            </Text>
                          </View>
                        )}
                      </View>

                      <Text
                        numberOfLines={1}
                        style={[
                          styles.threadTitle,
                          { color: colors.textPrimary },
                        ]}
                      >
                        {item.type === "gym" ? "Gym Room" : "Trainer Chat"}
                      </Text>

                      <Text
                        numberOfLines={2}
                        style={[
                          styles.threadPreview,
                          { color: colors.textSecondary },
                        ]}
                      >
                        {item.lastMessageBody ?? "No messages yet"}
                      </Text>
                    </MinimalCard>
                  </Pressable>
                );
              }}
            />
          )}
        </View>

        <KeyboardAvoidingView
          style={styles.chatArea}
          behavior={Platform.OS === "ios" ? "padding" : undefined}
        >
          {!activeThreadId ? (
            <MinimalCard variant="bordered" style={styles.emptyCard}>
              <Ionicons
                name="chatbox-ellipses-outline"
                size={34}
                color={colors.textTertiary}
              />
              <Text
                style={[
                  typography.h3,
                  { color: colors.textPrimary, marginTop: 10 },
                ]}
              >
                Pick a chat
              </Text>
              <Text
                style={[
                  typography.body,
                  { color: colors.textSecondary, marginTop: 6 },
                ]}
              >
                Choose a conversation on the left to start messaging.
              </Text>
            </MinimalCard>
          ) : (
            <>
              <MinimalCard
                variant="default"
                padding={12}
                style={styles.chatHeadCard}
              >
                <Text style={[typography.h4, { color: colors.textPrimary }]}>
                  {activeThread?.type === "gym" ? "Gym Room" : "Trainer Chat"}
                </Text>
                <Text
                  style={[typography.caption, { color: colors.textSecondary }]}
                >
                  {socketConnected
                    ? "Live updates enabled"
                    : "Offline sync active"}
                </Text>
              </MinimalCard>

              {loadingMessages ? (
                <View style={styles.loaderWrap}>
                  <ActivityIndicator color={colors.primary} />
                </View>
              ) : (
                <FlatList
                  data={activeMessages}
                  keyExtractor={(item) => item.id}
                  showsVerticalScrollIndicator={false}
                  contentContainerStyle={styles.messagesContent}
                  refreshControl={
                    <RefreshControl
                      refreshing={loadingMessages}
                      onRefresh={() =>
                        activeThreadId
                          ? void refreshMessages(activeThreadId)
                          : void refreshThreads()
                      }
                      tintColor={colors.primary}
                    />
                  }
                  ListHeaderComponent={
                    activeThreadId && hasMoreMessages(activeThreadId) ? (
                      <Pressable onPress={handleLoadOlder}>
                        <MinimalCard
                          variant="bordered"
                          padding={8}
                          style={styles.loadOlderCard}
                        >
                          {isLoadingOlderMessages(activeThreadId) ? (
                            <ActivityIndicator
                              size="small"
                              color={colors.primary}
                            />
                          ) : (
                            <Text
                              style={[
                                typography.caption,
                                { color: colors.textSecondary },
                              ]}
                            >
                              Load earlier messages
                            </Text>
                          )}
                        </MinimalCard>
                      </Pressable>
                    ) : null
                  }
                  renderItem={({ item }) => {
                    const own = item.senderUserId === userId;
                    const threadReads = activeThreadId
                      ? (readByThreadId[activeThreadId] ?? {})
                      : {};
                    const seen = Object.entries(threadReads).some(
                      ([readerUserId, messageId]) =>
                        readerUserId !== userId && messageId === item.id,
                    );

                    return (
                      <View
                        style={[
                          styles.messageBubble,
                          {
                            alignSelf: own ? "flex-end" : "flex-start",
                            backgroundColor: own
                              ? colors.primary
                              : colors.surface,
                            borderColor: own
                              ? colors.primaryDark
                              : colors.border,
                          },
                        ]}
                      >
                        <Text
                          style={[
                            typography.body,
                            { color: own ? colors.white : colors.textPrimary },
                          ]}
                        >
                          {item.body}
                        </Text>
                        <View style={styles.metaRow}>
                          <Text
                            style={{
                              fontSize: 10,
                              color: own
                                ? "rgba(255,255,255,0.82)"
                                : colors.textTertiary,
                            }}
                          >
                            {formatTime(item.createdAt)}
                          </Text>
                          {own && seen && (
                            <Text
                              style={{
                                marginLeft: 8,
                                fontSize: 10,
                                fontWeight: "700",
                                color: own
                                  ? "rgba(255,255,255,0.92)"
                                  : colors.textSecondary,
                              }}
                            >
                              Seen
                            </Text>
                          )}
                        </View>
                      </View>
                    );
                  }}
                />
              )}

              {typingUsers.length > 0 && (
                <View style={styles.typingRow}>
                  <Ionicons
                    name="ellipsis-horizontal"
                    size={14}
                    color={colors.textSecondary}
                  />
                  <Text
                    style={[
                      typography.caption,
                      { color: colors.textSecondary },
                    ]}
                  >
                    {typingUsers.length === 1
                      ? "Someone is typing..."
                      : `${typingUsers.length} people are typing...`}
                  </Text>
                </View>
              )}

              <View
                style={[styles.composer, { borderTopColor: colors.border }]}
              >
                <TextInput
                  value={draft}
                  onChangeText={handleDraftChange}
                  placeholder="Message"
                  placeholderTextColor={colors.textTertiary}
                  multiline
                  maxLength={2000}
                  style={[
                    styles.input,
                    {
                      color: colors.textPrimary,
                      borderColor: colors.border,
                      backgroundColor: colors.surface,
                    },
                  ]}
                />
                <Pressable
                  onPress={handleSend}
                  style={[
                    styles.sendButton,
                    {
                      backgroundColor: draft.trim()
                        ? colors.primary
                        : colors.border,
                    },
                  ]}
                >
                  <Ionicons name="send" size={15} color={colors.white} />
                </Pressable>
              </View>
            </>
          )}
        </KeyboardAvoidingView>
      </View>
    </View>
  );
}

function formatTime(isoDate: string): string {
  const date = new Date(isoDate);
  if (Number.isNaN(date.getTime())) {
    return "";
  }

  return date.toLocaleTimeString([], {
    hour: "2-digit",
    minute: "2-digit",
  });
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  headerWrap: {
    paddingHorizontal: 16,
    paddingTop: 16,
    paddingBottom: 8,
  },
  content: {
    flex: 1,
    flexDirection: "row",
    paddingHorizontal: 12,
    paddingBottom: 8,
    gap: 10,
  },
  threadRail: {
    width: 148,
  },
  railLabel: {
    marginBottom: 8,
  },
  loaderWrap: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
  threadListContent: {
    gap: 8,
    paddingBottom: 20,
  },
  threadCard: {
    borderRadius: 16,
  },
  threadCardTopRow: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    marginBottom: 8,
  },
  threadTypeChip: {
    flexDirection: "row",
    alignItems: "center",
    gap: 4,
  },
  threadTypeText: {
    fontSize: 11,
    fontWeight: "700",
  },
  threadUnreadBadge: {
    minWidth: 18,
    height: 18,
    borderRadius: 9,
    alignItems: "center",
    justifyContent: "center",
    paddingHorizontal: 4,
  },
  threadUnreadText: {
    color: "white",
    fontSize: 10,
    fontWeight: "700",
  },
  threadTitle: {
    fontSize: 13,
    fontWeight: "700",
  },
  threadPreview: {
    fontSize: 11,
    marginTop: 4,
    lineHeight: 15,
  },
  chatArea: {
    flex: 1,
  },
  emptyCard: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    marginBottom: 8,
  },
  chatHeadCard: {
    borderRadius: 14,
    marginBottom: 8,
  },
  messagesContent: {
    paddingHorizontal: 6,
    paddingBottom: 12,
    gap: 8,
  },
  loadOlderCard: {
    alignSelf: "center",
    borderRadius: 12,
    marginBottom: 10,
  },
  messageBubble: {
    borderWidth: 1,
    borderRadius: 16,
    paddingHorizontal: 12,
    paddingVertical: 9,
    maxWidth: "84%",
  },
  metaRow: {
    marginTop: 4,
    flexDirection: "row",
    alignItems: "center",
  },
  typingRow: {
    paddingHorizontal: 6,
    paddingBottom: 6,
    flexDirection: "row",
    alignItems: "center",
    gap: 4,
  },
  composer: {
    borderTopWidth: 1,
    paddingTop: 8,
    paddingBottom: 10,
    flexDirection: "row",
    alignItems: "flex-end",
    gap: 8,
  },
  input: {
    flex: 1,
    borderWidth: 1,
    borderRadius: 14,
    paddingHorizontal: 12,
    paddingVertical: 9,
    minHeight: 42,
    maxHeight: 110,
    textAlignVertical: "top",
    fontSize: 14,
  },
  sendButton: {
    width: 40,
    height: 40,
    borderRadius: 20,
    alignItems: "center",
    justifyContent: "center",
  },
});
