import { MaterialCommunityIcons } from "@expo/vector-icons";
import { router, useFocusEffect } from "expo-router";
import { useCallback, useEffect, useMemo, useState } from "react";
import {
  ActivityIndicator,
  FlatList,
  Image,
  Keyboard,
  Pressable,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from "react-native";
import {
  SafeAreaView,
  useSafeAreaInsets,
} from "react-native-safe-area-context";

import { images } from "@/constants";
import { driverPhotoUri } from "@/lib/driver-photo";
import { fetchAPI } from "@/lib/fetch";
import { useT } from "@/lib/i18n";
import { ensureMicPermission } from "@/lib/use-call";
import { useChat } from "@/lib/use-chat";
import { useTheme } from "@/lib/theme";
import type { ChatActiveRide, Message } from "@/types/type";

const initials = (name: string): string => {
  const parts = name.trim().split(/\s+/).filter(Boolean);
  if (!parts.length) return "?";
  return (parts[0][0] + (parts[1]?.[0] ?? "")).toUpperCase();
};

type ChatThreadProps = {
  /**
   * Extra clearance (px) the composer needs below the safe area — nonzero
   * when this screen sits under the rider's floating tab bar (position:
   * "absolute", ~78px tall + 20px margin), which doesn't reserve layout
   * space of its own and would otherwise sit on top of the composer. Pass 0
   * for a standalone screen (no tab bar underneath, e.g. the driver's).
   */
  tabBarClearance?: number;
};

// Ride-scoped chat thread: header with the peer + call button, message list,
// and composer. Shared by the rider's (tabs) Chat screen and the driver's
// standalone chat screen — both resolve the same conversation via
// GET /(api)/chat/active, which returns the correct peer for either role.
export const ChatThread = ({ tabBarClearance = 0 }: ChatThreadProps) => {
  const t = useT();
  const { isDark } = useTheme();
  const insets = useSafeAreaInsets();

  const [active, setActive] = useState<ChatActiveRide | null>(null);
  const [resolving, setResolving] = useState(true);

  // Resolve which conversation (if any) is open for the signed-in user. Re-run
  // whenever the screen is focused so a just-matched ride appears immediately.
  useFocusEffect(
    useCallback(() => {
      let cancelled = false;
      (async () => {
        setResolving(true);
        try {
          const res = await fetchAPI("/(api)/chat/active");
          if (!cancelled) setActive((res.data ?? null) as ChatActiveRide);
        } catch (err) {
          console.log("[CHAT_ACTIVE]: ", err);
          if (!cancelled) setActive(null);
        } finally {
          if (!cancelled) setResolving(false);
        }
      })();
      return () => {
        cancelled = true;
      };
    }, []),
  );

  const rideId = active?.ride_id ?? null;
  const role = active?.role ?? null;
  const { messages, loading, sending, sendMessage } = useChat(rideId, role);

  const [draft, setDraft] = useState("");

  const peer = active?.peer ?? null;
  const peerName = peer?.name ?? "";

  // Prime the mic permission as soon as a conversation (and its Call button)
  // is on screen, so the OS prompt lands here — not mid-handshake after the
  // user has already tapped Call and navigated to the call screen.
  const hasPeer = Boolean(peer);
  useEffect(() => {
    if (hasPeer) void ensureMicPermission();
  }, [hasPeer]);

  const openCall = useCallback(() => {
    if (!active) return;
    router.push({
      pathname: "/(root)/call",
      params: {
        rideId: String(active.ride_id),
        role: active.role,
        mode: "start",
      },
    });
  }, [active]);

  const submit = useCallback(() => {
    const text = draft.trim();
    if (!text || sending) return;
    setDraft("");
    void sendMessage(text);
    Keyboard.dismiss();
  }, [draft, sending, sendMessage]);

  const renderBubble = useCallback(
    ({ item }: { item: Message }) => {
      const mine = item.sender_type === role;
      return (
        <View
          className={`flex-row ${mine ? "justify-end" : "justify-start"} my-1`}
        >
          <View
            className={`max-w-[78%] rounded-2xl px-4 py-2.5 ${
              mine ? "bg-general-400" : "bg-neutral-100 dark:bg-neutral-800"
            }`}
          >
            <Text
              className={`text-[15px] ${
                mine ? "text-white" : "text-black dark:text-white"
              }`}
            >
              {item.body}
            </Text>
          </View>
        </View>
      );
    },
    [role],
  );

  const emptyConversation = useMemo(
    () => (
      <View className="flex-1 h-fit flex justify-center items-center">
        <Image
          source={images.message}
          alt={t("chat.messageAlt")}
          className="w-full h-40"
          resizeMode="contain"
        />
        <Text className="text-3xl font-JakartaBold mt-3 text-black dark:text-white">
          {t("chat.noMessages")}
        </Text>
        <Text className="text-base mt-2 text-center px-7 text-general-200 dark:text-neutral-400">
          {t("chat.startConversation")}
        </Text>
      </View>
    ),
    [t],
  );

  if (resolving) {
    return (
      <SafeAreaView className="flex-1 bg-white dark:bg-neutral-950 items-center justify-center">
        <ActivityIndicator size="large" color={isDark ? "#fff" : "#0286ff"} />
      </SafeAreaView>
    );
  }

  return (
    <SafeAreaView
      className="flex-1 bg-white dark:bg-neutral-950"
      edges={["top"]}
    >
      {/* Conversation header — only when a ride is matched */}
      {active && peer ? (
        <View className="flex-row items-center px-4 py-3 border-b border-neutral-100 dark:border-neutral-800">
          <Pressable
            onPress={() =>
              router.push({
                pathname: "/(root)/book-ride",
                params: { id: String(active.ride_id) },
              })
            }
            className="flex-row items-center flex-1"
          >
            {peer.avatar ? (
              <Image
                source={{ uri: driverPhotoUri(peer.avatar) }}
                className="w-10 h-10 rounded-full bg-neutral-200 dark:bg-neutral-700"
                resizeMode="cover"
              />
            ) : (
              <View className="w-10 h-10 rounded-full bg-general-400 items-center justify-center">
                <Text className="text-white font-JakartaBold">
                  {initials(peerName)}
                </Text>
              </View>
            )}
            <View className="ml-3">
              <Text className="text-base font-JakartaBold text-black dark:text-white">
                {peerName}
              </Text>
              {peer.car_model ? (
                <Text className="text-xs text-general-200 dark:text-neutral-400">
                  {peer.car_model}
                </Text>
              ) : null}
            </View>
          </Pressable>

          <TouchableOpacity
            onPress={openCall}
            hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
            accessibilityLabel={t("chat.call")}
            className="w-10 h-10 rounded-full bg-general-300 dark:bg-neutral-800 items-center justify-center"
          >
            <MaterialCommunityIcons name="phone" size={20} color="white" />
          </TouchableOpacity>
        </View>
      ) : null}

      {active && peer ? (
        <>
          {loading && messages.length === 0 ? (
            <View className="flex-1 items-center justify-center">
              <ActivityIndicator
                size="small"
                color={isDark ? "#fff" : "#0286ff"}
              />
            </View>
          ) : (
            <FlatList
              data={messages}
              keyExtractor={(m) => String(m.id)}
              renderItem={renderBubble}
              contentContainerStyle={{
                flexGrow: 1,
                paddingHorizontal: 16,
                paddingVertical: 12,
              }}
              onScrollBeginDrag={Keyboard.dismiss}
              keyboardShouldPersistTaps="never"
              ListEmptyComponent={emptyConversation}
            />
          )}

          {/* Composer */}
          <View
            className="flex-row items-center px-3 py-2 border-t border-neutral-100 dark:border-neutral-800"
            style={{ paddingBottom: insets.bottom + 8 + tabBarClearance }}
          >
            <TextInput
              value={draft}
              onChangeText={setDraft}
              placeholder={t("chat.inputPlaceholder")}
              placeholderTextColor={isDark ? "#737373" : "#9ca3af"}
              className="flex-1 min-h-[44px] max-h-28 rounded-full bg-neutral-100 dark:bg-neutral-800 px-4 py-2.5 text-[15px] text-black dark:text-white"
              multiline
            />
            <TouchableOpacity
              onPress={submit}
              disabled={sending || !draft.trim()}
              accessibilityLabel={t("chat.send")}
              className="w-11 h-11 ml-2 rounded-full bg-general-400 items-center justify-center disabled:opacity-40"
            >
              <MaterialCommunityIcons name="send" size={20} color="white" />
            </TouchableOpacity>
          </View>
        </>
      ) : (
        <View className="flex-1 px-5">{emptyConversation}</View>
      )}
    </SafeAreaView>
  );
};
