import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useAtomValue } from 'jotai';
import { Box, Button, Icon, Icons, Text, color, config, toRem } from 'folds';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useNavigate } from 'react-router-dom';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { factoryRoomIdByActivity } from '../../../utils/sort';
import { NavCategory, NavEmptyCenter, NavEmptyLayout } from '../../../components/nav';
import { getDirectCreatePath, getDirectRoomPath } from '../../pathUtils';
import { getCanonicalAliasOrRoomId } from '../../../utils/matrix';
import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom';
import { VirtualTile } from '../../../components/virtualizer';
import { DmStreamRow } from '../../../features/room-nav';
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
import { useDirectRooms } from './useDirectRooms';
import { PageNav, PageNavContent } from '../../../components/page';
import {
  getRoomNotificationMode,
  useRoomsNotificationPreferencesContext,
} from '../../../hooks/useRoomsNotificationPreferences';
import { DirectStreamHeader } from './DirectStreamHeader';
import { DirectNewChatRow } from './DirectNewChatRow';
import { DirectSelfRow } from './DirectSelfRow';

const MONO_FONT = '"JetBrains Mono Variable", ui-monospace, monospace';

function DirectEmpty() {
  const { t } = useTranslation();
  const navigate = useNavigate();

  return (
    <NavEmptyCenter>
      <NavEmptyLayout
        icon={<Icon size="600" src={Icons.Mention} />}
        title={
          <Text size="H5" align="Center">
            {t('Direct.no_direct_messages')}
          </Text>
        }
        content={
          <Text size="T300" align="Center">
            {t('Direct.no_direct_messages_desc')}
          </Text>
        }
        options={
          <Button variant="Primary" size="300" onClick={() => navigate(getDirectCreatePath())}>
            <Text size="B300" truncate>
              {t('Direct.start_first_chat')}
            </Text>
          </Button>
        }
      />
    </NavEmptyCenter>
  );
}

function DirectFooterStatus() {
  const { t } = useTranslation();
  return (
    <Box
      alignItems="Center"
      gap="200"
      style={{
        padding: `${toRem(8)} ${toRem(14)}`,
        borderTop: `${config.borderWidth.B300} solid ${color.Surface.ContainerLine}`,
        fontFamily: MONO_FONT,
        fontSize: toRem(11),
        color: color.Surface.OnContainer,
        opacity: 0.45,
      }}
    >
      <span
        style={{
          width: toRem(6),
          height: toRem(6),
          borderRadius: '50%',
          background: color.Success.Main,
          display: 'inline-block',
        }}
        aria-hidden
      />
      <span>vojo.chat</span>
      <Box grow="Yes" />
      <span>{t('Direct.status_e2ee')}</span>
    </Box>
  );
}

export function Direct() {
  const mx = useMatrixClient();
  useNavToActivePathMapper('direct');
  const scrollRef = useRef<HTMLDivElement>(null);
  const directs = useDirectRooms();
  const notificationPreferences = useRoomsNotificationPreferencesContext();
  // roomToUnreadAtom only changes on read/unread transitions and ignores own
  // events — covers incoming notifying messages but not own sends or muted
  // incoming. Kept as a subscribe-only re-render trigger.
  useAtomValue(roomToUnreadAtom);

  // Activity tick: bump on every live timeline event in any DM room so list
  // order, preview text and time labels refresh on own sends, muted incoming,
  // reactions — anything roomToUnread misses. Uses the 'Room.timeline'
  // literal (= RoomEvent.Timeline) to avoid named imports from matrix-js-sdk
  // that the project's moduleResolution flags as TS2614 (see
  // docs/known-tech-debt-lint/).
  const [, setActivityTick] = useState(0);
  useEffect(() => {
    const directsSet = new Set(directs);
    const handleTimeline = (
      _ev: unknown,
      room: { roomId: string } | undefined,
      _start: unknown,
      _removed: unknown,
      data: { liveEvent?: boolean } | undefined
    ) => {
      if (!room || !data?.liveEvent) return;
      if (!directsSet.has(room.roomId)) return;
      setActivityTick((n) => n + 1);
    };
    const emitter = mx as unknown as {
      on: (e: string, h: typeof handleTimeline) => void;
      removeListener: (e: string, h: typeof handleTimeline) => void;
    };
    emitter.on('Room.timeline', handleTimeline);
    return () => {
      emitter.removeListener('Room.timeline', handleTimeline);
    };
  }, [mx, directs]);

  const selectedRoomId = useSelectedRoom();
  const noRoomToDisplay = directs.length === 0;

  // Sort each render — small list, getLastActiveTimestamp changes outside
  // React's dep model so memoising would need a manual trigger anyway.
  const sortedDirects = Array.from(directs).sort(factoryRoomIdByActivity(mx));

  const virtualizer = useVirtualizer({
    count: sortedDirects.length,
    getScrollElement: () => scrollRef.current,
    estimateSize: () => 68,
    overscan: 10,
  });

  return (
    <PageNav size="500">
      <DirectStreamHeader />
      {noRoomToDisplay ? (
        <DirectEmpty />
      ) : (
        <PageNavContent scrollRef={scrollRef}>
          <Box direction="Column" gap="300">
            <NavCategory>
              <div
                style={{
                  position: 'relative',
                  height: virtualizer.getTotalSize(),
                }}
              >
                {virtualizer.getVirtualItems().map((vItem) => {
                  const roomId = sortedDirects[vItem.index];
                  const room = mx.getRoom(roomId);
                  if (!room) return null;
                  const selected = selectedRoomId === roomId;

                  return (
                    <VirtualTile
                      virtualItem={vItem}
                      key={vItem.index}
                      ref={virtualizer.measureElement}
                    >
                      <DmStreamRow
                        room={room}
                        selected={selected}
                        linkPath={getDirectRoomPath(getCanonicalAliasOrRoomId(mx, roomId))}
                        notificationMode={getRoomNotificationMode(
                          notificationPreferences,
                          room.roomId
                        )}
                      />
                    </VirtualTile>
                  );
                })}
              </div>
            </NavCategory>
          </Box>
        </PageNavContent>
      )}
      <DirectNewChatRow />
      <DirectSelfRow />
      <DirectFooterStatus />
    </PageNav>
  );
}
