import React, { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Avatar, Box, Text, Badge } from 'folds';
import { Icon, Icons } from '../../../components/icons';
import { useAtom, useSetAtom } from 'jotai';
import { Room, Thread, ThreadEvent } from 'matrix-js-sdk';
import { NavCategory, NavCategoryHeader, NavItem, NavItemContent, NavButton } from '../../../components/nav';
import { RoomNavCategoryButton } from '../../../features/room-nav';
import { makeNavCategoryId } from '../../../state/closedNavCategories';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { useCategoryHandler } from '../../../hooks/useCategoryHandler';
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
import { activeThreadIdAtomFamily } from '../../../state/activeThread';
import { getCanonicalAliasOrRoomId, getMxIdLocalPart } from '../../../utils/matrix';
import { getHomeRoomPath } from '../../pathUtils';
import { getMemberDisplayName } from '../../../utils/room';

const THREADS_CATEGORY_ID = makeNavCategoryId('home', 'threads');

type ThreadEntry = {
  room: Room;
  thread: Thread;
};

type ThreadNavItemProps = {
  room: Room;
  thread: Thread;
  selected: boolean;
};

/**
 * A single nav item representing a thread the user has participated in.
 * Navigates to the room and opens the thread when clicked.
 */
function ThreadNavItem({ room, thread, selected }: ThreadNavItemProps) {
  const navigate = useNavigate();
  const setActiveThreadId = useSetAtom(activeThreadIdAtomFamily(room.roomId));
  const mx = useMatrixClient();

  const { rootEvent } = thread;
  const senderId = rootEvent?.getSender() ?? '';
  const senderName =
    getMemberDisplayName(room, senderId) ?? getMxIdLocalPart(senderId) ?? senderId;
  const rootBody = rootEvent?.getContent()?.body ?? '';
  const replyCount = thread.length;

  const handleClick = useCallback(() => {
    const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, room.roomId);
    navigate(getHomeRoomPath(roomIdOrAlias));
    // Defer slightly so RoomView has time to render before we set the atom.
    requestAnimationFrame(() => {
      // eslint-disable-next-line no-console
      console.log('[HomeThreadsCategory] Opening thread', {
        threadId: thread.id,
        rootEventId: thread.rootEvent?.getId(),
        roomId: room.roomId,
      });
      // Use rootEvent ID if available, fallback to thread.id
      const threadIdToUse = thread.rootEvent?.getId() || thread.id;
      setActiveThreadId(threadIdToUse);
    });
  }, [navigate, mx, room.roomId, setActiveThreadId, thread.id, thread.rootEvent]);

  return (
    <NavItem variant="Background" radii="400" aria-selected={selected}>
      <NavButton onClick={handleClick}>
        <NavItemContent>
          <Box as="span" grow="Yes" alignItems="Center" gap="200">
            <Avatar size="200" radii="400">
              <Icon src={Icons.Thread} size="100" />
            </Avatar>
            <Box as="span" grow="Yes" direction="Column" style={{ overflow: 'hidden', minWidth: 0 }}>
              <Text as="span" size="Inherit" truncate>
                {senderName}
              </Text>
              {rootBody && (
                <Text as="span" size="T200" priority="300" truncate>
                  {rootBody}
                </Text>
              )}
            </Box>
            {replyCount > 0 && (
              <Badge variant="Secondary" size="400" fill="Soft" radii="Pill">
                <Text as="span" size="L400">
                  {replyCount}
                </Text>
              </Badge>
            )}
          </Box>
        </NavItemContent>
      </NavButton>
    </NavItem>
  );
}

type HomeThreadsCategoryProps = {
  rooms: string[];
};

/**
 * Nav category for the left sidebar showing threads in Home rooms where the
 * current user has participated.
 */
export function HomeThreadsCategory({ rooms }: HomeThreadsCategoryProps) {
  const mx = useMatrixClient();
  const [closedCategories, setClosedCategories] = useAtom(useClosedNavCategoriesAtom());

  const getParticipatedThreads = useCallback((): ThreadEntry[] =>
    rooms.reduce<ThreadEntry[]>((acc, roomId) => {
      const room = mx.getRoom(roomId);
      if (!room) return acc;
      return acc.concat(
        room
          .getThreads()
          .filter((t) => t.hasCurrentUserParticipated)
          .map((t) => ({ room, thread: t }))
      );
    }, []),
  [mx, rooms]);

  const [threads, setThreads] = useState<ThreadEntry[]>(getParticipatedThreads);

  // Re-compute when thread events fire in any home room.
  useEffect(() => {
    const handleUpdate = () => setThreads(getParticipatedThreads());

    const roomObjects = rooms.reduce<Room[]>((acc, roomId) => {
      const room = mx.getRoom(roomId);
      if (room) acc.push(room);
      return acc;
    }, []);

    roomObjects.forEach((room) => {
      room.getThreads().forEach((thread) => {
        thread.on(ThreadEvent.Update, handleUpdate);
        thread.on(ThreadEvent.NewReply, handleUpdate);
      });
    });

    return () => {
      roomObjects.forEach((room) => {
        room.getThreads().forEach((thread) => {
          thread.off(ThreadEvent.Update, handleUpdate);
          thread.off(ThreadEvent.NewReply, handleUpdate);
        });
      });
    };
  }, [mx, rooms, getParticipatedThreads]);

  const handleCategoryClick = useCategoryHandler(setClosedCategories, (categoryId) =>
    closedCategories.has(categoryId)
  );

  if (threads.length === 0) return null;

  return (
    <NavCategory data-nav-dropdown="">
      <NavCategoryHeader>
        <RoomNavCategoryButton
          closed={closedCategories.has(THREADS_CATEGORY_ID)}
          data-category-id={THREADS_CATEGORY_ID}
          onClick={handleCategoryClick}
        >
          My Threads
        </RoomNavCategoryButton>
      </NavCategoryHeader>
      {!closedCategories.has(THREADS_CATEGORY_ID) && (
        <div data-nav-rooms="">
          {threads.map(({ room, thread }) => (
            <ThreadNavItem
              key={`${room.roomId}:${thread.id}`}
              room={room}
              thread={thread}
              selected={false}
            />
          ))}
        </div>
      )}
    </NavCategory>
  );
}
