import { useFocusEffect } from "expo-router";
import { useCallback, useEffect, useState } from "react";
import { getSocket } from "../lib/socket.io";

type RoomUpdatePayload<T> = {
	roomId: string;
	payloads: T[];
};

type RoomErrorPayload = {
	roomId?: string;
	message?: string;
};

type UpdateMode = "append" | "replace";

export function useSocketRoom<T>(
	roomId: string,
	getKey?: (item: T) => string | number,
	updateMode: UpdateMode = "append",
) {
	const [data, setData] = useState<T[]>([]);
	const [info, setInfo] = useState(
		"No data yet — join the room to start receiving",
	);

	const clearRoom = useCallback(
		(id?: string | number) => {
			if (id !== undefined && getKey) {
				setData((prev) => prev.filter((item) => getKey(item) !== id));
				setInfo(`Removed item ${id}`);
				return;
			}

			setData([]);
			setInfo("Room data cleared");
		},
		[getKey],
	);

	useFocusEffect(
		useCallback(() => {
			const socket = getSocket();
			function handleConnect() {
				socket.emit("join-room", roomId);
				setInfo(`Joined room: ${roomId}`);
			}

			function handleUpdate(payload: RoomUpdatePayload<T>) {
				// protects against other room updates hitting this hook
				if (payload.roomId !== roomId) return;

				// resetting room data for rooms that just need updated data.
				if (updateMode === "replace") {
					setData(payload.payloads);
				} else {
					setData((prev) => [...payload.payloads, ...prev]);
				}

				setInfo("");
			}

			function handleError(err: RoomErrorPayload) {
				if (err.roomId && err.roomId !== roomId) return;
				setInfo(err.message ?? "Room error");
			}

			socket.on("connect", handleConnect);
			socket.on("room-update", handleUpdate);
			socket.on("room-error", handleError);

			if (!socket.connected && socket.disconnected) {
				socket.connect();
			}

			// If already connected, join immediately
			if (socket.connected) {
				socket.emit("join-room", roomId);
				setInfo(`Joined room: ${roomId}`);
			}

			return () => {
				socket.emit("leave-room", roomId);

				socket.off("connect", handleConnect);
				socket.off("room-update", handleUpdate);
				socket.off("room-error", handleError);
			};
		}, [roomId, updateMode]),
	);

	// useEffect(() => {
	// 	const socket = getSocket();
	// 	function handleConnect() {
	// 		socket.emit("join-room", roomId);
	// 		setInfo(`Joined room: ${roomId}`);
	// 	}

	// 	function handleUpdate(payload: RoomUpdatePayload<T>) {
	// 		// protects against other room updates hitting this hook
	// 		if (payload.roomId !== roomId) return;

	// 		setData((prev) => [...payload.payloads, ...prev]);
	// 		setInfo("");
	// 	}

	// 	function handleError(err: RoomErrorPayload) {
	// 		if (err.roomId && err.roomId !== roomId) return;
	// 		setInfo(err.message ?? "Room error");
	// 	}

	// 	if (!socket.connected && socket.disconnected) {
	// 		socket.connect();
	// 	}

	// 	// If already connected, join immediately
	// 	if (socket.connected) {
	// 		socket.emit("join-room", roomId);
	// 		setInfo(`Joined room: ${roomId}`);
	// 	}

	// 	socket.on("connect", handleConnect);
	// 	socket.on("room-update", handleUpdate);
	// 	socket.on("room-error", handleError);

	// 	return () => {
	// 		socket.emit("leave-room", roomId);
	// 		console.log("leaving Room");
	// 		socket.off("connect", handleConnect);
	// 		socket.off("room-update", handleUpdate);
	// 		socket.off("room-error", handleError);
	// 	};
	// }, [roomId]);

	return { data, info, clearRoom };
}
