import React, { useEffect, useRef, useState } from 'react';
import Modal from '@mui/material/Modal';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import Avatar from '@mui/material/Avatar';
import Paper from '@mui/material/Paper';
import Stack from '@mui/material/Stack';
import Fade from '@mui/material/Fade';
import {
  Call as CallIcon,
  CallEnd as CallEndIcon,
  Mic as MicIcon,
  MicOff as MicOffIcon,
  Videocam as VideocamIcon,
  VideocamOff as VideocamOffIcon,
  VolumeUp as SpeakerIcon,
  VolumeOff as SpeakerOffIcon,
  Phone as PhoneIcon,
} from '@mui/icons-material';
import { CallState, CallStatus } from '../../types/chat';

interface CallModalProps {
  callState: CallState;
  onAccept: () => void;
  onDecline: () => void;
  onEnd: () => void;
  onToggleMute: () => void;
  onToggleVideo: () => void;
  onToggleSpeaker: () => void;
}

// Helper to format call duration
const formatDuration = (seconds: number): string => {
  const mins = Math.floor(seconds / 60);
  const secs = seconds % 60;
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
};

// Helper to get status text
const getStatusText = (status: CallStatus, isIncoming: boolean): string => {
  switch (status) {
    case 'calling':
      return 'Anrufen...';
    case 'ringing':
      return isIncoming ? 'Eingehender Anruf' : 'Klingelt...';
    case 'connecting':
      return 'Verbinden...';
    case 'connected':
      return 'Verbunden';
    case 'ended':
      return 'Anruf beendet';
    case 'declined':
      return 'Abgelehnt';
    case 'cancelled':
      return 'Abgebrochen';
    case 'timeout':
      return 'Keine Antwort';
    case 'busy':
      return 'Besetzt';
    case 'failed':
      return 'Verbindungsfehler';
    default:
      return '';
  }
};

// Helper to generate initials
const getInitials = (name: string): string => {
  const parts = name.split(' ');
  if (parts.length >= 2) {
    return (parts[0][0] + parts[1][0]).toUpperCase();
  }
  return name.substring(0, 2).toUpperCase();
};

// Helper to generate color from string
const stringToColor = (str: string): string => {
  if (!str || str.length === 0) return '#808080';
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    hash = str.charCodeAt(i) + ((hash << 5) - hash);
  }
  let color = '#';
  for (let i = 0; i < 3; i++) {
    const value = (hash >> (i * 8)) & 0xff;
    color += ('00' + value.toString(16)).substr(-2);
  }
  return color;
};

const CallModal: React.FC<CallModalProps> = ({
  callState,
  onAccept,
  onDecline,
  onEnd,
  onToggleMute,
  onToggleVideo,
  onToggleSpeaker,
}) => {
  const [callDuration, setCallDuration] = useState(0);
  const [audioLevel, setAudioLevel] = useState(0);
  const localVideoRef = useRef<HTMLVideoElement>(null);
  const remoteVideoRef = useRef<HTMLVideoElement>(null);
  const remoteAudioRef = useRef<HTMLAudioElement>(null);
  const audioContextRef = useRef<AudioContext | null>(null);
  const analyserRef = useRef<AnalyserNode | null>(null);
  const animationFrameRef = useRef<number | null>(null);

  const {
    status,
    type,
    isIncoming,
    remoteUserName,
    remoteUserAvatar,
    startTime,
    localStream,
    remoteStream,
    isMuted,
    isVideoOff,
    isSpeakerOn,
  } = callState;

  const isOpen = status !== 'idle';
  const isConnected = status === 'connected';
  const isRinging = status === 'ringing';
  const isEnding = ['ended', 'declined', 'cancelled', 'timeout', 'busy', 'failed'].includes(status);
  const isVideoCall = type === 'video';

  // Update call duration
  useEffect(() => {
    if (!startTime || !isConnected) {
      setCallDuration(0);
      return;
    }

    const interval = setInterval(() => {
      const now = new Date();
      const duration = Math.floor((now.getTime() - startTime.getTime()) / 1000);
      setCallDuration(duration);
    }, 1000);

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

  // Set up local video
  useEffect(() => {
    if (localVideoRef.current && localStream) {
      localVideoRef.current.srcObject = localStream;
    }
  }, [localStream]);

  // Set up remote video
  useEffect(() => {
    if (remoteVideoRef.current && remoteStream) {
      remoteVideoRef.current.srcObject = remoteStream;
    }
  }, [remoteStream]);

  // Set up remote audio for audio-only calls
  useEffect(() => {
    if (remoteAudioRef.current && remoteStream) {
      console.log('[CallModal] Setting up remote audio stream');
      remoteAudioRef.current.srcObject = remoteStream;
      remoteAudioRef.current.play().catch((err) => {
        console.error('[CallModal] Failed to play remote audio:', err);
      });
    }
  }, [remoteStream]);

  // Audio level analysis for sound wave animation
  useEffect(() => {
    if (!remoteStream || !isConnected) {
      setAudioLevel(0);
      return;
    }

    // Create audio context and analyser
    const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
    const analyser = audioContext.createAnalyser();
    analyser.fftSize = 256;
    analyser.smoothingTimeConstant = 0.8;

    audioContextRef.current = audioContext;
    analyserRef.current = analyser;

    // Connect remote stream to analyser
    const source = audioContext.createMediaStreamSource(remoteStream);
    source.connect(analyser);

    // Read audio levels
    const dataArray = new Uint8Array(analyser.frequencyBinCount);

    const updateAudioLevel = () => {
      if (!analyserRef.current) return;

      analyserRef.current.getByteFrequencyData(dataArray);

      // Calculate average audio level
      let sum = 0;
      for (let i = 0; i < dataArray.length; i++) {
        sum += dataArray[i];
      }
      const average = sum / dataArray.length;

      // Normalize to 0-1 range (typical values are 0-150)
      const normalizedLevel = Math.min(average / 100, 1);
      setAudioLevel(normalizedLevel);

      animationFrameRef.current = requestAnimationFrame(updateAudioLevel);
    };

    updateAudioLevel();

    return () => {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }
      if (audioContextRef.current) {
        audioContextRef.current.close();
      }
      setAudioLevel(0);
    };
  }, [remoteStream, isConnected]);

  const userName = remoteUserName || 'Unbekannt';

  return (
    <Modal
      open={isOpen}
      onClose={() => {}} // Prevent closing by clicking outside
      closeAfterTransition
      sx={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      <Fade in={isOpen}>
        <Paper
          elevation={24}
          sx={{
            width: isVideoCall && isConnected ? 600 : 400,
            maxWidth: '95vw',
            maxHeight: '90vh',
            borderRadius: 3,
            overflow: 'hidden',
            outline: 'none',
            backgroundColor: '#1a1a2e',
            color: '#ffffff',
          }}
        >
          {/* Video area for video calls */}
          {isVideoCall && isConnected && (
            <Box
              sx={{
                position: 'relative',
                width: '100%',
                height: 400,
                backgroundColor: '#000',
              }}
            >
              {/* Remote video (full size) */}
              <video
                ref={remoteVideoRef}
                autoPlay
                playsInline
                style={{
                  width: '100%',
                  height: '100%',
                  objectFit: 'cover',
                }}
              />

              {/* Local video (picture-in-picture) */}
              <Box
                sx={{
                  position: 'absolute',
                  bottom: 16,
                  right: 16,
                  width: 120,
                  height: 90,
                  borderRadius: 2,
                  overflow: 'hidden',
                  border: '2px solid #fff',
                  boxShadow: 3,
                }}
              >
                <video
                  ref={localVideoRef}
                  autoPlay
                  playsInline
                  muted
                  style={{
                    width: '100%',
                    height: '100%',
                    objectFit: 'cover',
                    transform: 'scaleX(-1)', // Mirror local video
                  }}
                />
                {isVideoOff && (
                  <Box
                    sx={{
                      position: 'absolute',
                      inset: 0,
                      backgroundColor: '#333',
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                    }}
                  >
                    <VideocamOffIcon sx={{ color: '#999' }} />
                  </Box>
                )}
              </Box>

              {/* Call duration overlay */}
              <Box
                sx={{
                  position: 'absolute',
                  top: 16,
                  left: '50%',
                  transform: 'translateX(-50%)',
                  backgroundColor: 'rgba(0,0,0,0.5)',
                  px: 2,
                  py: 0.5,
                  borderRadius: 2,
                }}
              >
                <Typography variant="body2">{formatDuration(callDuration)}</Typography>
              </Box>
            </Box>
          )}

          {/* Non-video or non-connected state */}
          {(!isVideoCall || !isConnected) && (
            <Box
              sx={{
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                py: 5,
                px: 3,
              }}
            >
              {/* Avatar with sound wave rings */}
              <Box
                sx={{
                  position: 'relative',
                  mb: 2,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                }}
              >
                {/* Sound wave rings - only show when connected and there's audio */}
                {isConnected && (
                  <>
                    {/* Ring 1 - innermost */}
                    <Box
                      sx={{
                        position: 'absolute',
                        width: 100 + audioLevel * 30,
                        height: 100 + audioLevel * 30,
                        borderRadius: '50%',
                        border: `2px solid rgba(144, 202, 249, ${0.3 + audioLevel * 0.4})`,
                        transition: 'all 0.1s ease-out',
                      }}
                    />
                    {/* Ring 2 */}
                    <Box
                      sx={{
                        position: 'absolute',
                        width: 100 + audioLevel * 50,
                        height: 100 + audioLevel * 50,
                        borderRadius: '50%',
                        border: `2px solid rgba(144, 202, 249, ${0.2 + audioLevel * 0.3})`,
                        transition: 'all 0.15s ease-out',
                      }}
                    />
                    {/* Ring 3 - outermost */}
                    <Box
                      sx={{
                        position: 'absolute',
                        width: 100 + audioLevel * 70,
                        height: 100 + audioLevel * 70,
                        borderRadius: '50%',
                        border: `2px solid rgba(144, 202, 249, ${0.1 + audioLevel * 0.2})`,
                        transition: 'all 0.2s ease-out',
                      }}
                    />
                  </>
                )}
                <Avatar
                  src={remoteUserAvatar || undefined}
                  sx={{
                    width: 100,
                    height: 100,
                    fontSize: '2.5rem',
                    bgcolor: stringToColor(userName),
                    border: '3px solid rgba(255,255,255,0.2)',
                    zIndex: 1,
                  }}
                >
                  {getInitials(userName)}
                </Avatar>
              </Box>

              {/* Name */}
              <Typography variant="h5" sx={{ fontWeight: 500, mb: 1 }}>
                {userName}
              </Typography>

              {/* Status */}
              <Typography
                variant="body1"
                sx={{
                  color: isEnding ? '#f44336' : '#90caf9',
                  mb: 1,
                }}
              >
                {getStatusText(status, isIncoming)}
              </Typography>

              {/* Duration (when connected) */}
              {isConnected && (
                <Typography variant="body2" sx={{ color: '#90caf9' }}>
                  {formatDuration(callDuration)}
                </Typography>
              )}

              {/* Call type indicator */}
              {!isConnected && !isEnding && (
                <Box sx={{ mt: 2, display: 'flex', alignItems: 'center', gap: 1 }}>
                  {isVideoCall ? (
                    <VideocamIcon sx={{ color: '#90caf9' }} />
                  ) : (
                    <PhoneIcon sx={{ color: '#90caf9' }} />
                  )}
                  <Typography variant="body2" sx={{ color: '#90caf9' }}>
                    {isVideoCall ? 'Videoanruf' : 'Sprachanruf'}
                  </Typography>
                </Box>
              )}
            </Box>
          )}

          {/* Control buttons */}
          <Box
            sx={{
              display: 'flex',
              justifyContent: 'center',
              alignItems: 'center',
              gap: 2,
              py: 3,
              px: 3,
              backgroundColor: 'rgba(0,0,0,0.3)',
            }}
          >
            {/* Incoming call - Accept/Decline buttons */}
            {isRinging && isIncoming && (
              <>
                <IconButton
                  onClick={onDecline}
                  sx={{
                    backgroundColor: '#f44336',
                    color: '#fff',
                    width: 64,
                    height: 64,
                    '&:hover': { backgroundColor: '#d32f2f' },
                  }}
                >
                  <CallEndIcon sx={{ fontSize: 32 }} />
                </IconButton>

                <IconButton
                  onClick={onAccept}
                  sx={{
                    backgroundColor: '#4caf50',
                    color: '#fff',
                    width: 64,
                    height: 64,
                    '&:hover': { backgroundColor: '#388e3c' },
                  }}
                >
                  <CallIcon sx={{ fontSize: 32 }} />
                </IconButton>
              </>
            )}

            {/* Outgoing call - Cancel button */}
            {(status === 'calling' || (isRinging && !isIncoming)) && (
              <IconButton
                onClick={onEnd}
                sx={{
                  backgroundColor: '#f44336',
                  color: '#fff',
                  width: 64,
                  height: 64,
                  '&:hover': { backgroundColor: '#d32f2f' },
                }}
              >
                <CallEndIcon sx={{ fontSize: 32 }} />
              </IconButton>
            )}

            {/* Connected - Full controls */}
            {(isConnected || status === 'connecting') && (
              <Stack direction="row" spacing={2}>
                {/* Mute button */}
                <IconButton
                  onClick={onToggleMute}
                  sx={{
                    backgroundColor: isMuted ? '#f44336' : 'rgba(255,255,255,0.1)',
                    color: '#fff',
                    width: 56,
                    height: 56,
                    '&:hover': {
                      backgroundColor: isMuted ? '#d32f2f' : 'rgba(255,255,255,0.2)',
                    },
                  }}
                >
                  {isMuted ? <MicOffIcon /> : <MicIcon />}
                </IconButton>

                {/* Video toggle (for video calls) */}
                {isVideoCall && (
                  <IconButton
                    onClick={onToggleVideo}
                    sx={{
                      backgroundColor: isVideoOff ? '#f44336' : 'rgba(255,255,255,0.1)',
                      color: '#fff',
                      width: 56,
                      height: 56,
                      '&:hover': {
                        backgroundColor: isVideoOff ? '#d32f2f' : 'rgba(255,255,255,0.2)',
                      },
                    }}
                  >
                    {isVideoOff ? <VideocamOffIcon /> : <VideocamIcon />}
                  </IconButton>
                )}

                {/* Speaker toggle */}
                <IconButton
                  onClick={onToggleSpeaker}
                  sx={{
                    backgroundColor: !isSpeakerOn ? '#f44336' : 'rgba(255,255,255,0.1)',
                    color: '#fff',
                    width: 56,
                    height: 56,
                    '&:hover': {
                      backgroundColor: !isSpeakerOn ? '#d32f2f' : 'rgba(255,255,255,0.2)',
                    },
                  }}
                >
                  {isSpeakerOn ? <SpeakerIcon /> : <SpeakerOffIcon />}
                </IconButton>

                {/* End call button */}
                <IconButton
                  onClick={onEnd}
                  sx={{
                    backgroundColor: '#f44336',
                    color: '#fff',
                    width: 56,
                    height: 56,
                    '&:hover': { backgroundColor: '#d32f2f' },
                  }}
                >
                  <CallEndIcon />
                </IconButton>
              </Stack>
            )}

            {/* Ending states - just show a close hint */}
            {isEnding && (
              <Typography variant="body2" sx={{ color: '#999' }}>
                Anruf wird beendet...
              </Typography>
            )}
          </Box>

          {/* Hidden audio element for playing remote audio stream */}
          <audio
            ref={remoteAudioRef}
            autoPlay
            playsInline
            style={{ display: 'none' }}
          />
        </Paper>
      </Fade>
    </Modal>
  );
};

export default CallModal;
