import React from 'react';
import { Avatar, Box, Text, config } from 'folds';
import { Icon, Icons } from '../../components/icons';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useRoomCallMembers } from '../call/useRoomCallMembers';
import { getMemberAvatarMxc, getMemberDisplayName } from '../../utils/room';
import { mxcUrlToHttp, getMxIdLocalPart } from '../../utils/matrix';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { nameInitials } from '../../utils/common';
import { useCall } from '../call/useCall';
import * as css from './CallParticipantsIndicator.css';

const MAX_VISIBLE_PARTICIPANTS = 8;

type CallParticipantsIndicatorProps = {
  roomId: string;
};

export function CallParticipantsIndicator({ roomId }: CallParticipantsIndicatorProps) {
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();
  const room = mx.getRoom(roomId);
  const { callMembers, isCallActive } = useRoomCallMembers(roomId);
  const { activeCall } = useCall();
  const myUserId = mx.getUserId();

  if (!isCallActive || callMembers.length === 0 || !room) {
    return null;
  }

  const visibleMembers = callMembers.slice(0, MAX_VISIBLE_PARTICIPANTS);
  const remainingCount = callMembers.length - MAX_VISIBLE_PARTICIPANTS;

  const getParticipantAvatar = (userId: string): string | undefined => {
    const mxcUrl = getMemberAvatarMxc(room, userId);
    if (!mxcUrl) return undefined;
    return mxcUrlToHttp(mx, mxcUrl, useAuthentication, 48, 48, 'crop') ?? undefined;
  };

  const getParticipantName = (userId: string): string => {
    return getMemberDisplayName(room, userId) ?? getMxIdLocalPart(userId) ?? userId;
  };

  /**
   * Check if a participant is currently speaking
   */
  const isParticipantSpeaking = (userId: string): boolean => {
    if (!activeCall) return false;
    
    // Direct check for Matrix user ID (works for local user)
    if (activeCall.activeSpeakers.has(userId)) return true;
    
    // For remote users, activeSpeakers contains LiveKit identities (deviceId_timestamp)
    const member = callMembers.find((m) => m.userId === userId);
    if (!member) return false;
    
    // Check if any active speaker has this user's deviceId
    return Array.from(activeCall.activeSpeakers).some((speakerId) => {
      const underscoreIndex = speakerId.lastIndexOf('_');
      const deviceId = underscoreIndex > 0 ? speakerId.substring(0, underscoreIndex) : speakerId;
      return deviceId === member.deviceId;
    });
  };

  /**
   * Check if a participant is currently muted
   */
  const isParticipantMuted = (userId: string): boolean => {
    if (!activeCall) return false;
    
    // For local user, check activeCall.isMuted
    if (userId === myUserId) return activeCall.isMuted;
    
    // For remote users, mutedParticipants contains LiveKit identities (deviceId_timestamp)
    const member = callMembers.find((m) => m.userId === userId);
    if (!member) return false;
    
    // Check if any muted participant has this user's deviceId
    return Array.from(activeCall.mutedParticipants).some((mutedId) => {
      const underscoreIndex = mutedId.lastIndexOf('_');
      const deviceId = underscoreIndex > 0 ? mutedId.substring(0, underscoreIndex) : mutedId;
      return deviceId === member.deviceId;
    });
  };

  /**
   * Check if the local user is deafened
   */
  const isLocalUserDeafened = (userId: string): boolean => {
    if (!activeCall || userId !== myUserId) return false;
    return activeCall.isDeafened;
  };

  /**
   * Get the appropriate audio icon for a participant
   */
  const getAudioIcon = (userId: string): string => {
    if (isLocalUserDeafened(userId)) {
      return Icons.VolumeMute;
    }
    return isParticipantMuted(userId) ? Icons.MicMute : Icons.Mic;
  };

  return (
    <Box
      direction="Column"
      gap="200"
      style={{
        paddingLeft: config.space.S500,
        paddingTop: config.space.S200,
        width: '100%',
      }}
    >
      {visibleMembers.map((member) => {
        const isSpeaking = isParticipantSpeaking(member.userId);
        const isMuted = isParticipantMuted(member.userId);
        const isDeafened = isLocalUserDeafened(member.userId);
        
        return (
          <Box
            key={member.userId}
            alignItems="Center"
            gap="100"
            style={{
              opacity: config.opacity.P300,
            }}
          >
            <Avatar 
              size="200" 
              radii="Pill"
              className={isSpeaking ? css.ParticipantSpeaking : undefined}
            >
              {getParticipantAvatar(member.userId) ? (
                <img
                  src={getParticipantAvatar(member.userId)}
                  alt={getParticipantName(member.userId)}
                  style={{
                    width: '100%',
                    height: '100%',
                    objectFit: 'cover',
                    borderRadius: 'inherit',
                  }}
                />
              ) : (
                <Text as="span" size="H6">
                  {nameInitials(getParticipantName(member.userId))}
                </Text>
              )}
            </Avatar>
            <Box alignItems="Center" gap="100" grow="Yes">
              <Icon 
                src={getAudioIcon(member.userId)} 
                size="50" 
                style={{ 
                  opacity: config.opacity.P500,
                  color: isDeafened ? 'var(--color-Critical-Main)' : isMuted ? 'var(--color-Critical-Main)' : undefined 
                }} 
              />
              <Text as="span" size="T200" truncate>
                {getParticipantName(member.userId)}
              </Text>
            </Box>
          </Box>
        );
      })}
      {remainingCount > 0 && (
        <Box
          alignItems="Center"
          gap="200"
          style={{
            opacity: config.opacity.P300,
            paddingLeft: config.space.S300,
          }}
        >
          <Text as="span" size="T200">
            +{remainingCount} more
          </Text>
        </Box>
      )}
    </Box>
  );
}
