import React, { useEffect, useMemo, useState } from 'react';
import { Box, Icon, IconButton, Icons, Text, Tooltip, TooltipProvider, Scroll, color } from 'folds';
import { useSetAtom } from 'jotai';
import { useCall } from './useCall';
import { ScreenShareItem, ScreenShareEntry } from './CallOverlay';
import { useRoomCallMembers } from './useRoomCallMembers';
import { CallState, CallType } from './types';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { getMemberDisplayName, getMemberAvatarMxc } from '../../utils/room';
import { getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { UserAvatar } from '../../components/user-avatar';
import { useSelectedRoom } from '../../hooks/router/useSelectedRoom';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
import { UnreadBadge } from '../../components/unread-badge';
import { useRoomUnread } from '../../state/hooks/unread';
import { roomToUnreadAtom } from '../../state/room/roomToUnread';
import { useSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
import { pendingUndockDragAtom } from './pendingDragState';
import * as css from './CallOverlay.css';

/**
 * Formats call duration in MM:SS format
 */
function formatDuration(seconds: number): string {
  const mins = Math.floor(seconds / 60);
  const secs = seconds % 60;
  return `${mins}:${secs.toString().padStart(2, '0')}`;
}

/**
 * Docked call panel content - renders call UI in the layout flow
 * This is used when the call panel is docked to the right side
 */
/**
 * Custom Screen share icon SVG (Phosphor-style)
 */
function ScreenShareIcon() {
  return (
    <svg width="1em" height="1em" viewBox="0 0 24 24" fill="currentColor">
      <path d="M21 16V8a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h5v2H8v2h8v-2h-2v-2h5a2 2 0 0 0 2-2zm-2 0H5V8h14v8z" />
      <path d="M12 9l-4 4h3v3h2v-3h3l-4-4z" />
    </svg>
  );
}

/**
 * Custom Screen share off icon SVG (Phosphor-style)
 */
function ScreenShareOffIcon() {
  return (
    <svg width="1em" height="1em" viewBox="0 0 24 24" fill="currentColor">
      <path d="M21 16V8a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h5v2H8v2h8v-2h-2v-2h5a2 2 0 0 0 2-2zm-2 0H5V8h14v8z" />
      <path d="M2 4l20 16" stroke="currentColor" strokeWidth="2" />
    </svg>
  );
}

export function DockedCallContent() {
  const { activeCall, endCall, toggleMute, toggleDeafen, toggleScreenShare } = useCall();
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();
  const selectedRoomId = useSelectedRoom();
  const [duration, setDuration] = useState(0);
  const [isTogglingScreenShare, setIsTogglingScreenShare] = useState(false);
  const [showParticipants, setShowParticipants] = useState(true);
  const { navigateRoom } = useRoomNavigate();
  const [, setIsDocked] = useSetting(settingsAtom, 'isCallPanelDocked');
  const setPendingDrag = useSetAtom(pendingUndockDragAtom);
  
  const unread = useRoomUnread(activeCall?.roomId ?? '', roomToUnreadAtom);
  const { callMembers } = useRoomCallMembers(activeCall?.roomId ?? '');
  const myUserId = mx.getUserId() ?? '';

  /** Memoized list of active screen shares (local + remote) */
  const allScreenShares = useMemo((): ScreenShareEntry[] => {
    const shares: ScreenShareEntry[] = [];

    if (activeCall?.isScreenSharing && activeCall?.localScreenStream) {
      shares.push({
        id: 'local',
        isLocal: true,
        participantId: myUserId,
        roomId: activeCall.roomId,
        stream: activeCall.localScreenStream,
      });
    }

    const remoteScreenTracks = activeCall?.remoteScreenTracks
      ? Array.from(activeCall.remoteScreenTracks.values())
      : [];

    remoteScreenTracks.forEach((trackInfo) => {
      const livekitId = trackInfo.participantId;
      const underscoreIndex = livekitId.lastIndexOf('_');
      const possibleDeviceId = underscoreIndex > 0 ? livekitId.substring(0, underscoreIndex) : livekitId;
      const matchingMember = callMembers.find((m) => m.deviceId === possibleDeviceId);
      const matrixUserId = matchingMember?.userId ?? livekitId;

      shares.push({
        id: livekitId,
        isLocal: false,
        participantId: matrixUserId,
        roomId: activeCall?.roomId ?? '',
        livekitId,
        track: trackInfo.track,
        stream: trackInfo.stream,
      });
    });

    return shares;
  }, [activeCall?.isScreenSharing, activeCall?.localScreenStream, activeCall?.remoteScreenTracks, activeCall?.roomId, callMembers, myUserId]);

  useEffect(() => {
    if (!activeCall || activeCall.state !== CallState.Connected) {
      setDuration(0);
      return undefined;
    }

    const { startTime } = activeCall;
    const updateDuration = () => {
      const elapsed = Math.floor((Date.now() - startTime) / 1000);
      setDuration(elapsed);
    };

    updateDuration();
    const interval = setInterval(updateDuration, 1000);

    return () => clearInterval(interval);
  }, [activeCall]);

  /**
   * Checks if a participant is currently speaking
   */
  const isParticipantSpeaking = (userId: string): boolean => {
    if (!activeCall) return false;
    if (activeCall.activeSpeakers.has(userId)) return true;
    
    const member = callMembers.find((m) => m.userId === userId);
    if (!member) return false;
    
    return Array.from(activeCall.activeSpeakers).some((speakerId) => {
      const underscoreIndex = speakerId.lastIndexOf('_');
      const deviceId = underscoreIndex > 0 ? speakerId.substring(0, underscoreIndex) : speakerId;
      return deviceId === member.deviceId;
    });
  };

  /**
   * Checks if a participant is currently muted
   */
  const isParticipantMuted = (userId: string): boolean => {
    if (!activeCall) return false;
    if (userId === myUserId) return activeCall.isMuted;
    
    const member = callMembers.find((m) => m.userId === userId);
    if (!member) return false;
    
    return Array.from(activeCall.mutedParticipants).some((mutedId) => {
      const underscoreIndex = mutedId.lastIndexOf('_');
      const deviceId = underscoreIndex > 0 ? mutedId.substring(0, underscoreIndex) : mutedId;
      return deviceId === member.deviceId;
    });
  };

  const handleEndCall = () => {
    endCall();
  };

  const handleToggleMute = () => {
    toggleMute();
  };

  const handleToggleDeafen = () => {
    toggleDeafen();
  };

  const handleToggleScreenShare = async () => {
    if (isTogglingScreenShare) return;
    setIsTogglingScreenShare(true);
    try {
      await toggleScreenShare();
    } finally {
      setIsTogglingScreenShare(false);
    }
  };

  /**
   * Handle mousedown on header to start drag-to-undock
   * Sets pending drag state so the floating overlay can continue the drag
   */
  const handleHeaderMouseDown = async (e: React.MouseEvent) => {
    // Don't start drag if clicking a button
    if ((e.target as HTMLElement).closest('button')) return;
    
    // Exit browser fullscreen if active before undocking
    if (document.fullscreenElement) {
      try {
        await document.exitFullscreen();
      } catch {
        // Fullscreen exit may fail
      }
    }
    
    // Get the header element to calculate offset
    const header = e.currentTarget as HTMLElement;
    const rect = header.getBoundingClientRect();
    
    // Store the drag start position with mouse offset from panel edges
    setPendingDrag({
      startX: e.clientX,
      startY: e.clientY,
      offsetX: e.clientX - rect.left,
      offsetY: e.clientY - rect.top,
      timestamp: Date.now(),
    });
    
    // Undock immediately - the floating overlay will pick up the drag
    setIsDocked(false);
  };

  if (!activeCall || activeCall.state === CallState.Idle || activeCall.state === CallState.Ended) {
    return null;
  }

  const isConnecting = activeCall.state === CallState.Connecting;
  const isVideoCall = activeCall.callType === CallType.Video;
  const room = mx.getRoom(activeCall.roomId);
  const allParticipants = callMembers.map((m) => m.userId);
  const participantCount = allParticipants.length;

  return (
    <div className={css.DockedCallPanelContent}>
      {/* Header - drag to undock */}
      {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
      <div 
        className={css.CallOverlayHeader}
        onMouseDown={handleHeaderMouseDown}
        style={{ cursor: 'grab' }}
      >
        <Box alignItems="Center" gap="200" style={{ minWidth: 0, flex: 1 }}>
          <Icon
            size="200"
            src={isVideoCall ? Icons.VideoCamera : Icons.Phone}
          />
          <Text size="T300" truncate>
            {isConnecting ? 'Connecting...' : room?.name ?? 'Unknown Room'}
            {selectedRoomId === activeCall.roomId && (
              <TooltipProvider
                position="Top"
                offset={4}
                tooltip={<Tooltip><Text>Current Room</Text></Tooltip>}
              >
                {(triggerRef) => (
                  <Icon 
                    ref={triggerRef}
                    size="100" 
                    src={Icons.Check} 
                    style={{ marginLeft: '4px', opacity: 0.7, verticalAlign: 'middle' }} 
                  />
                )}
              </TooltipProvider>
            )}
          </Text>
          {unread && unread.total > 0 && (
            <UnreadBadge highlight={unread.highlight > 0} count={unread.total} />
          )}
        </Box>
        <Box alignItems="Center" gap="100">
          <Text size="T200" className={css.CallDuration}>
            {formatDuration(duration)}
          </Text>
          {selectedRoomId !== activeCall.roomId && (
            <TooltipProvider
              position="Top"
              offset={4}
              tooltip={<Tooltip><Text>Go to Room</Text></Tooltip>}
            >
              {(triggerRef) => (
                <IconButton 
                  ref={triggerRef} 
                  onClick={() => navigateRoom(activeCall.roomId)} 
                  variant="Secondary" 
                  size="300"
                >
                  <Icon size="100" src={Icons.Link} />
                </IconButton>
              )}
            </TooltipProvider>
          )}
        </Box>
      </div>

      {/* Participants */}
      <Box direction="Column" grow="Yes" style={{ overflow: 'hidden' }}>
        <div className={css.ParticipantsSection} style={{ flex: 1 }}>
          <button
            type="button"
            className={css.ParticipantsHeader}
            onClick={() => setShowParticipants(!showParticipants)}
          >
            <Text size="T200" className={css.ParticipantsHeaderText}>
              Participants ({participantCount})
            </Text>
            <Icon
              size="100"
              src={showParticipants ? Icons.ChevronTop : Icons.ChevronBottom}
              style={{ opacity: 0.7 }}
            />
          </button>
          {showParticipants && room && (
            <Scroll hideTrack visibility="Hover" style={{ maxHeight: '100%' }}>
              <div className={css.ParticipantsList}>
                {allParticipants.map((participantId) => {
                  const avatarMxc = getMemberAvatarMxc(room, participantId);
                  const avatarUrl = avatarMxc
                    ? mxcUrlToHttp(mx, avatarMxc, useAuthentication, 32, 32, 'crop') ?? undefined
                    : undefined;
                  const displayName = getMemberDisplayName(room, participantId) 
                    ?? getMxIdLocalPart(participantId) 
                    ?? participantId;
                  const isMe = participantId === myUserId;
                  const isMuted = isParticipantMuted(participantId);
                  const isSpeaking = isParticipantSpeaking(participantId);
                  
                  return (
                    <div key={participantId} className={css.ParticipantItem}>
                      <div 
                        className={`${css.ParticipantAvatarWrapper} ${isSpeaking ? css.ParticipantSpeaking : ''}`}
                      >
                        <UserAvatar
                          className={css.ParticipantAvatar}
                          userId={participantId}
                          src={avatarUrl}
                          alt={displayName}
                          renderFallback={() => (
                            <Text size="H6" style={{ color: color.Surface.Container }}>
                              {displayName.charAt(0).toUpperCase()}
                            </Text>
                          )}
                        />
                      </div>
                      <Box direction="Column" style={{ minWidth: 0, flex: 1 }}>
                        <Text size="T300" className={css.ParticipantName} truncate>
                          {displayName}
                          {isMe && <span className={css.YouBadge}> (You)</span>}
                        </Text>
                      </Box>
                      {isMuted && (
                        <Icon 
                          size="100" 
                          src={Icons.MicMute} 
                          className={css.ParticipantMutedIcon}
                        />
                      )}
                    </div>
                  );
                })}
              </div>
            </Scroll>
          )}
        </div>
      </Box>

      {/* Screen shares */}
      {allScreenShares.length > 0 && (
        <Box direction="Column" gap="200" style={{ padding: '0 8px 8px' }}>
          {allScreenShares.map((share) => (
            <ScreenShareItem key={share.id} share={share} />
          ))}
        </Box>
      )}

      {/* Controls */}
      <div className={css.CallOverlayControls}>
        <TooltipProvider
          position="Top"
          offset={4}
          tooltip={<Tooltip><Text>{activeCall.isMuted ? 'Unmute' : 'Mute'}</Text></Tooltip>}
        >
          {(triggerRef) => (
            <IconButton
              ref={triggerRef}
              onClick={handleToggleMute}
              variant={activeCall.isMuted ? 'Critical' : 'Secondary'}
            >
              <Icon size="300" src={activeCall.isMuted ? Icons.MicMute : Icons.Mic} />
            </IconButton>
          )}
        </TooltipProvider>

        <TooltipProvider
          position="Top"
          offset={4}
          tooltip={<Tooltip><Text>{activeCall.isDeafened ? 'Undeafen' : 'Deafen'}</Text></Tooltip>}
        >
          {(triggerRef) => (
            <IconButton
              ref={triggerRef}
              onClick={handleToggleDeafen}
              variant={activeCall.isDeafened ? 'Critical' : 'Secondary'}
            >
              <Icon size="300" src={activeCall.isDeafened ? Icons.VolumeMute : Icons.VolumeHigh} />
            </IconButton>
          )}
        </TooltipProvider>

        <TooltipProvider
          position="Top"
          offset={4}
          tooltip={<Tooltip><Text>{activeCall.isScreenSharing ? 'Stop Screen Share' : 'Share Screen'}</Text></Tooltip>}
        >
          {(triggerRef) => (
            <IconButton
              ref={triggerRef}
              onClick={handleToggleScreenShare}
              variant={activeCall.isScreenSharing ? 'Primary' : 'Secondary'}
              disabled={isTogglingScreenShare}
            >
              <Box
                as="span"
                style={{
                  width: '1.5rem',
                  height: '1.5rem',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                }}
              >
                {activeCall.isScreenSharing ? <ScreenShareOffIcon /> : <ScreenShareIcon />}
              </Box>
            </IconButton>
          )}
        </TooltipProvider>

        <TooltipProvider
          position="Top"
          offset={4}
          tooltip={<Tooltip><Text>End Call</Text></Tooltip>}
        >
          {(triggerRef) => (
            <IconButton
              ref={triggerRef}
              onClick={handleEndCall}
              variant="Critical"
            >
              <Icon size="300" src={Icons.Phone} />
            </IconButton>
          )}
        </TooltipProvider>
      </div>
    </div>
  );
}
