import React from 'react';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { getMemberDisplayName } from '../../utils/room';
import { getMxIdLocalPart } from '../../utils/matrix';
import { useRoomCallMembers } from './useRoomCallMembers';
import { useCall } from './useCall';
import { useSendCursor, useReceiveCursors, RemoteCursorState } from './useRemoteCursor';
import colorMXID from '../../../util/colorMXID';
import * as css from './CallOverlay.css';

/** Props for RemoteCursorOverlay */
interface RemoteCursorOverlayProps {
  /** The screen share ID to track cursors for */
  shareId: string;
  /** The room ID of the active call */
  roomId: string;
}

/**
 * Resolves a LiveKit participant identity to a Matrix user ID
 * LiveKit identities are typically in the format "deviceId_timestamp"
 */
function resolveParticipantUserId(
  livekitIdentity: string,
  callMembers: { userId: string; deviceId: string }[]
): string {
  const underscoreIndex = livekitIdentity.lastIndexOf('_');
  const possibleDeviceId =
    underscoreIndex > 0 ? livekitIdentity.substring(0, underscoreIndex) : livekitIdentity;

  const match = callMembers.find((m) => m.deviceId === possibleDeviceId);
  return match?.userId ?? livekitIdentity;
}

/**
 * Single remote cursor dot with label
 */
function CursorDot({
  cursor,
  displayName,
  cursorColor,
}: {
  cursor: RemoteCursorState;
  displayName: string;
  cursorColor: string;
}) {
  if (!cursor.visible) return null;

  const left = `${cursor.x * 100}%`;
  const top = `${cursor.y * 100}%`;

  return (
    <>
      <div
        className={css.RemoteCursorDot}
        style={{
          left,
          top,
          backgroundColor: cursorColor,
          opacity: cursor.visible ? 1 : 0,
        }}
      />
      <div
        className={css.RemoteCursorLabel}
        style={{ left, top, color: 'white' }}
      >
        {displayName}
      </div>
    </>
  );
}

/**
 * Overlay that renders remote cursor positions on top of a screen share
 * Also provides mouse event handlers for sending local cursor position
 */
export function RemoteCursorOverlay({ shareId, roomId }: RemoteCursorOverlayProps) {
  const mx = useMatrixClient();
  const { callMembers } = useRoomCallMembers(roomId);
  const { activeCall } = useCall();
  const cursors = useReceiveCursors(shareId);
  const room = mx.getRoom(roomId);
  const myUserId = mx.getUserId() ?? '';

  /**
   * Gets a display name for a LiveKit participant
   */
  const getDisplayName = (livekitIdentity: string): string => {
    const userId = resolveParticipantUserId(livekitIdentity, callMembers);
    if (!room) return getMxIdLocalPart(userId) ?? userId;
    return getMemberDisplayName(room, userId) ?? getMxIdLocalPart(userId) ?? userId;
  };

  // Filter out our own cursor and only show visible cursors
  const myIdentity = activeCall?.participants.find((p) => {
    const underscoreIndex = p.lastIndexOf('_');
    const deviceId = underscoreIndex > 0 ? p.substring(0, underscoreIndex) : p;
    const member = callMembers.find((m) => m.deviceId === deviceId);
    return member?.userId === myUserId;
  });

  const remoteCursors = Array.from(cursors.entries()).filter(
    ([participantId]) => participantId !== myIdentity
  );

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

  return (
    <div className={css.RemoteCursorOverlay}>
      {remoteCursors.map(([participantId, cursor]) => {
        const userId = resolveParticipantUserId(participantId, callMembers);
        return (
          <CursorDot
            key={participantId}
            cursor={cursor}
            displayName={getDisplayName(participantId)}
            cursorColor={colorMXID(userId)}
          />
        );
      })}
    </div>
  );
}

/**
 * Wrapper that provides mouse event handlers for cursor sending on a screenshare
 * @param shareId - The screen share ID
 * @returns Mouse event handlers to attach to the container
 */
export function useScreenShareCursor(shareId: string) {
  return useSendCursor(shareId);
}
