'use client';

/* eslint jsx-a11y/click-events-have-key-events: warn */

/* eslint jsx-a11y/no-static-element-interactions: warn */
import { useMessages, useOccupancy } from '@ably/chat/react';
import { useGateValue } from '@statsig/react-bindings';
import { observer } from 'mobx-react-lite';
import { useRouter } from 'next/navigation';
import React, {
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
} from 'react';
import { createPortal } from 'react-dom';

import CustomVolumeSlider from '@/app/(root)/live-radio/CustomVolumeSlider';
import LiveRadioAblyProvider from '@/app/(root)/live-radio/LiveRadioAblyProvider';
import { LiveRadioContext } from '@/app/(root)/live-radio/LiveRadioProvider';
import { STATION_ID } from '@/app/(root)/live-radio/constants';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import Avatar from '@/components/image/Avatar';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import Link from '@/components/link/Link';
import { toast } from '@/components/toast/Toast';
import { Tooltip } from '@/components/tooltip/Tooltip';
import {
  ExpandContentIcon,
  HeadphoneIcon,
  NextTrackIcon,
  PauseIcon,
  PlayIcon,
  PreviousTrackIcon,
  PulsingLinesIcon,
  RadioBroadcastIcon,
  ShareArrowIcon,
  Volume0Icon,
  VolumeDownIcon,
  VolumeOnIcon,
} from '@/icons';
import {
  FALLBACK_IMAGE_URL,
  SMALL_IMAGE,
  TAILWIND_LARGE_MIN_WIDTH,
  TAILWIND_SMALL_MIN_WIDTH,
  TAILWIND_XXL_MIN_WIDTH,
} from '@/utils/constants';
import { isValidResourceUrl } from '@/utils/utils';

interface RadioPlaybarProps {
  stationId?: string;
}

// Component for radio info section (image, title, status pills)
interface RadioInfoProps {
  connections?: number;
  onNavigate: () => void;
}

const RadioInfo: React.FC<RadioInfoProps> = ({ connections, onNavigate }) => {
  return (
    <div className='theme-dark relative flex w-full flex-1 items-center overflow-hidden md:w-8'>
      <div
        className='relative mr-2 h-16 w-[85px] shrink-0 cursor-pointer overflow-clip rounded-md transition-opacity hover:opacity-80 md:h-14'
        onClick={onNavigate}
      >
        <ImageWithFallback
          imageSize={SMALL_IMAGE}
          className='h-full w-full object-cover'
          src={'https://cdn-o.suno.com/suno-living-radio-poster.webp'}
          alt={`Cover image for Deep Focus Beats`}
          aria-label={`Radio Playbar: Cover image for Deep Focus Beats`}
        />
        <div className='absolute inset-0 flex items-center justify-center bg-black/10 p-1'>
          <RadioBroadcastIcon className='h-4 w-4 text-foreground-primary' />
        </div>
      </div>
      <div className='relative flex w-full flex-col gap-2 pr-2 md:w-auto'>
        <div className='relative flex w-fit cursor-pointer overflow-x-hidden text-sm font-medium text-foreground-primary hover:underline'>
          <Link
            href='/live-radio'
            className='mr-24 whitespace-nowrap'
            aria-label='Radio Playbar: Title for Deep Focus Beats'
          >
            Deep Focus Beats
          </Link>
        </div>
        <div className='flex flex-row items-start gap-1 md:items-center md:gap-2'>
          {/* Live pill */}
          <span className='flex h-[24px] min-w-0 items-center rounded-[24px] border border-foreground-tertiary/20 bg-transparent px-2 text-xs font-medium text-foreground-primary'>
            <span className='mr-1.5 inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-accent-red-on-primary' />
            Live
          </span>
          {/* Listeners pill */}
          {connections ? (
            <span className='flex h-[24px] min-w-0 items-center gap-1.5 rounded-[24px] border border-foreground-tertiary/20 bg-transparent px-2 text-xs font-medium text-foreground-secondary'>
              <HeadphoneIcon className='inline h-3 w-3' />
              {connections?.toLocaleString()} listener
              {connections === 1 ? '' : 's'}
            </span>
          ) : null}
        </div>
      </div>
    </div>
  );
};

// Component for loading state
const RadioLoadingState: React.FC = () => {
  return (
    <div className='flex w-8 flex-1'>
      <div className='flex items-center'>
        <div className='mr-2 h-16 w-10 shrink-0 overflow-clip rounded-md bg-background-tertiary md:h-14' />
        <div className='flex flex-col'>
          <span className='text-sm font-medium text-foreground-secondary'>
            Loading radio...
          </span>
          <div className='flex items-center gap-1'>
            <span className='inline-block h-2 w-2 rounded-full bg-foreground-secondary' />
            <span className='text-xs font-medium text-foreground-secondary'>
              Connecting
            </span>
          </div>
        </div>
      </div>
    </div>
  );
};

// Helper function to get play/pause button props based on state
const getPlayButtonProps = (
  isLoading: boolean,
  isPlaying: boolean,
  togglePlay: () => void
) => {
  if (isLoading) {
    return {
      icon: PulsingLinesIcon,
      disabled: true,
      onClick: undefined,
      'aria-label': 'Radio Playbar: Loading',
    };
  }

  if (isPlaying) {
    return {
      icon: PauseIcon,
      disabled: false,
      onClick: togglePlay,
      'aria-label': 'Radio Playbar: Pause',
    };
  }

  return {
    icon: PlayIcon,
    disabled: false,
    onClick: togglePlay,
    'aria-label': 'Radio Playbar: Play',
  };
};

// Component for desktop playback controls
const RadioPlaybackControls: React.FC = () => {
  const { isPlaying, isLoading, togglePlay } = useContext(LiveRadioContext);
  const playButtonProps = getPlayButtonProps(isLoading, isPlaying, togglePlay);

  return (
    <div className='hidden w-8 flex-1 flex-row items-center justify-center gap-1 md:flex'>
      <Button
        variant={ButtonVariant.Glass}
        size={ButtonSize.Small}
        shape={ButtonShape.Pill}
        icon={PreviousTrackIcon}
        iconClassName='w-6 h-6 m-0 opacity-30'
        disabled={true}
        onClick={() => {}}
        aria-label='Radio Playbar: Previous Song (disabled)'
      />

      <Button
        href={undefined}
        variant={ButtonVariant.Tertiary}
        size={ButtonSize.Small}
        shape={ButtonShape.Pill}
        icon={playButtonProps.icon}
        iconClassName='w-6 h-6 m-0'
        disabled={playButtonProps.disabled}
        onClick={playButtonProps.onClick}
        aria-label={playButtonProps['aria-label']}
      />

      <Button
        variant={ButtonVariant.Glass}
        size={ButtonSize.Small}
        shape={ButtonShape.Pill}
        icon={NextTrackIcon}
        iconClassName='w-6 h-6 m-0 opacity-30'
        disabled={true}
        onClick={() => {}}
        aria-label='Radio Playbar: Next Song (disabled)'
      />
    </div>
  );
};

// Component for volume control
interface RadioVolumeControlProps {
  volume: number;
  onToggleSlider: (rect: DOMRect) => void;
  buttonRef: React.RefObject<HTMLButtonElement | null>;
}

const RadioVolumeControl: React.FC<RadioVolumeControlProps> = ({
  volume,
  onToggleSlider,
  buttonRef,
}) => {
  return (
    <div className='volume-slider-container hidden md:block'>
      <Button
        variant={ButtonVariant.Tertiary}
        size={ButtonSize.Small}
        shape={ButtonShape.Pill}
        icon={
          volume === 0
            ? Volume0Icon
            : volume < 50
              ? VolumeDownIcon
              : VolumeOnIcon
        }
        className='cursor-pointer'
        enableHoverState
        onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
          const button = e.currentTarget;
          const rect = button.getBoundingClientRect();
          onToggleSlider(rect);
          e.preventDefault();
          e.stopPropagation();
        }}
        aria-label='Radio Playbar: Volume Slider'
        ref={buttonRef}
      />
    </div>
  );
};

// Component for action buttons (share, open radio)
interface RadioActionButtonsProps {
  onShare: () => void;
  onNavigate: () => void;
}

const RadioActionButtons: React.FC<RadioActionButtonsProps> = ({
  onShare,
  onNavigate,
}) => {
  return (
    <>
      {/* Share Button */}
      <Tooltip label='Share radio'>
        <Button
          className='hidden md:block'
          variant={ButtonVariant.Tertiary}
          size={ButtonSize.Small}
          shape={ButtonShape.Pill}
          icon={ShareArrowIcon}
          onClick={onShare}
          aria-label='Radio Playbar: Share'
        />
      </Tooltip>

      {/* Open Radio & Vote Button */}
      <Tooltip label='Open Radio & Vote'>
        <Button
          className='hidden md:block'
          variant={ButtonVariant.Tertiary}
          size={ButtonSize.Small}
          shape={ButtonShape.Pill}
          icon={ExpandContentIcon}
          onClick={onNavigate}
          aria-label='Radio Playbar: Open Radio & Vote'
        >
          <span className='ml-1 hidden text-xs lg:block'>
            Open Radio & Vote
          </span>
          <span className='ml-1 block text-xs lg:hidden'>Open Radio</span>
        </Button>
      </Tooltip>
    </>
  );
};

// Component for mobile controls
const RadioMobileControls: React.FC = () => {
  const { isPlaying, isLoading, togglePlay } = useContext(LiveRadioContext);
  const buttonProps = getPlayButtonProps(isLoading, isPlaying, togglePlay);

  return (
    <div className='flex h-auto w-fit flex-col items-center gap-2 bg-transparent md:hidden'>
      <div className='flex h-auto w-fit flex-row items-center gap-1'>
        <Button
          href={undefined}
          variant={ButtonVariant.Tertiary}
          size={ButtonSize.Small}
          shape={ButtonShape.Pill}
          icon={buttonProps.icon}
          iconClassName='w-6 h-6 m-0'
          disabled={buttonProps.disabled}
          onClick={buttonProps.onClick}
          aria-label={buttonProps['aria-label']}
        />
      </div>
    </div>
  );
};

// Component for volume slider portal
interface RadioVolumeSliderPortalProps {
  isOpen: boolean;
  buttonRect: DOMRect | null;
  volume: number;
  onVolumeChange: (volume: number) => void;
}

const RadioVolumeSliderPortal: React.FC<RadioVolumeSliderPortalProps> = ({
  isOpen,
  buttonRect,
  volume,
  onVolumeChange,
}) => {
  if (!isOpen || !buttonRect) return null;

  return createPortal(
    <div
      className='volume-slider-portal fixed z-9999 animate-fade-in'
      style={{
        left: `${buttonRect.left + buttonRect.width / 2}px`,
        // Show above if enough space, otherwise show below
        ...(buttonRect.top > 160
          ? { top: `${buttonRect.top - 150}px` }
          : { top: `${buttonRect.bottom + 10}px` }),
        transform: 'translateX(-50%)',
      }}
    >
      <div className='flex items-center justify-center'>
        <CustomVolumeSlider
          volume={volume / 100}
          onChange={onVolumeChange}
          className='h-[140px] w-[30px]'
        />
      </div>
    </div>,
    document.body
  );
};

// Component for floating messages
interface FloatingMessage {
  id: string;
  text: string;
  clientId?: string;
  timestamp: number;
}

interface FloatingMessageDisplayProps {
  message: FloatingMessage;
  onAnimationComplete: (id: string) => void;
}

const FloatingMessageDisplay: React.FC<FloatingMessageDisplayProps> = ({
  message,
  onAnimationComplete,
}) => {
  // Calculate animation duration based on window width
  const [animationDuration, setAnimationDuration] = useState(() => {
    const width = window.innerWidth;
    if (width < TAILWIND_SMALL_MIN_WIDTH) return 6000; // 6s for mobile
    if (width < TAILWIND_LARGE_MIN_WIDTH) return 8000; // 8s for tablet
    if (width < TAILWIND_XXL_MIN_WIDTH) return 10000; // 10s for smaller desktop
    return 12000; // 12s for large desktop
  });

  // Update animation duration on window resize
  useEffect(() => {
    const handleResize = () => {
      const width = window.innerWidth;
      if (width < TAILWIND_SMALL_MIN_WIDTH)
        setAnimationDuration(6000); // 6s for mobile
      else if (width < TAILWIND_LARGE_MIN_WIDTH)
        setAnimationDuration(8000); // 8s for tablet
      else if (width < TAILWIND_XXL_MIN_WIDTH)
        setAnimationDuration(10000); // 10s for smaller desktop
      else setAnimationDuration(12000); // 12s for large desktop
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  useEffect(() => {
    const timer = setTimeout(() => {
      onAnimationComplete(message.id);
    }, animationDuration);

    return () => clearTimeout(timer);
  }, [message.id, onAnimationComplete, animationDuration]);

  // Parse clientId JSON to get user data
  let clientIdData: {
    handle?: string;
    avatar_image_url?: string;
  } | null = null;
  try {
    if (message.clientId && typeof message.clientId === 'string') {
      clientIdData = JSON.parse(message.clientId);
    }
  } catch (error) {
    // Silent fail, will use defaults
  }

  // Use clientId data if available, otherwise use defaults
  const avatarUrl = isValidResourceUrl(clientIdData?.avatar_image_url)
    ? clientIdData?.avatar_image_url
    : FALLBACK_IMAGE_URL;
  const displayName = clientIdData?.handle || 'Anonymous';

  return (
    <div
      key={message.id}
      className='pointer-events-none absolute top-1/2 left-0 -translate-y-1/2 whitespace-nowrap'
      style={{
        animation: `floatMessage ${animationDuration / 1000}s linear forwards`,
      }}
    >
      <div className='ml-2 rounded-lg border border-border-primary bg-background-glass-dense px-2 py-1 backdrop-blur-2xl'>
        <div className='flex items-center gap-2 text-xs'>
          {/* User avatar */}
          <div className='h-4 w-4 shrink-0 overflow-hidden rounded-full'>
            <Avatar
              src={avatarUrl}
              displayName={displayName}
              size={16}
              className='h-full w-full object-cover'
            />
          </div>
          {/* Message content */}
          <div className='flex items-center gap-1'>
            <span className='font-medium text-foreground-primary'>
              {displayName}
            </span>
            <span className='text-foreground-primary/60'>{message.text}</span>
          </div>
        </div>
      </div>
    </div>
  );
};

// Inner component that uses the occupancy hook
const RadioPlaybarContent: React.FC<RadioPlaybarProps> = observer(
  ({ stationId: _stationId = STATION_ID }) => {
    const isCommentsEnabled = useGateValue('living-radio-playbar-comments');
    const router = useRouter();
    const playbarRef = useRef<HTMLDivElement>(null);
    const volumeButtonRef = useRef<HTMLButtonElement>(null);
    const lastMessageTimeRef = useRef<number>(0);

    // Get live listener count from Ably occupancy
    const { connections } = useOccupancy();
    const { currentSong, volume, setVolume } = useContext(LiveRadioContext);

    // State management for UI only
    const [isVolumeSliderOpen, setIsVolumeSliderOpen] =
      useState<boolean>(false);
    const [volumeButtonRect, setVolumeButtonRect] = useState<DOMRect | null>(
      null
    );
    const [floatingMessages, setFloatingMessages] = useState<FloatingMessage[]>(
      []
    );
    const [showMessagePanel, setShowMessagePanel] = useState<boolean>(false);
    const [isPanelAnimatingOut, setIsPanelAnimatingOut] =
      useState<boolean>(false);

    // Listen for messages
    useMessages({
      listener: (message) => {
        const now = Date.now();
        // Rate limit: only show one message every 2 seconds
        if (now - lastMessageTimeRef.current < 2000) {
          return;
        }
        if (
          message.message &&
          message.message.text &&
          typeof message.message.text === 'string'
        ) {
          lastMessageTimeRef.current = now;

          const floatingMessage: FloatingMessage = {
            id: `${message.message.serial || Date.now()}`,
            text: message.message.text,
            clientId: message.message.clientId || undefined,
            timestamp: now,
          };
          setFloatingMessages((prev) => [...prev, floatingMessage]);
          setShowMessagePanel(true);
        }
      },
    });

    // Remove completed floating messages
    const removeFloatingMessage = useCallback((id: string) => {
      setFloatingMessages((prev) => {
        const newMessages = prev.filter((msg) => msg.id !== id);
        // If this was the last message, start hide animation
        if (newMessages.length === 0) {
          setIsPanelAnimatingOut(true);
          setTimeout(() => {
            setShowMessagePanel(false);
            setIsPanelAnimatingOut(false);
          }, 300); // Match animation duration
        }
        return newMessages;
      });
    }, []);

    const handleVolumeChange = useCallback(
      (newVolume: number) => {
        // CustomVolumeSlider expects 0-1 range, but context uses 0-100
        const clampedVolume = Math.max(0, Math.min(100, newVolume * 100));
        setVolume(clampedVolume);
      },
      [setVolume]
    );

    const handleShare = useCallback(async () => {
      const shareData = {
        title: 'Suno Living Radio',
        text: 'Listening to Deep Focus Beats on Suno Living Radio',
        url: window.location.origin + '/live-radio',
      };
      if (navigator.share) {
        await navigator.share(shareData);
      } else {
        await navigator.clipboard.writeText(shareData.url);
        toast({
          title: 'Copied to clipboard',
          description: 'Share radio with your friends',
          status: 'success',
        });
      }
    }, []);

    const handleNavigateToRadio = useCallback(() => {
      router.push('/live-radio');
    }, [router]);

    const handleToggleVolumeSlider = useCallback(
      (rect: DOMRect) => {
        setVolumeButtonRect(rect);
        setIsVolumeSliderOpen(!isVolumeSliderOpen);
      },
      [isVolumeSliderOpen]
    );

    // Close volume slider when clicking outside
    useEffect(() => {
      const handleClickOutside = (event: MouseEvent) => {
        if (
          isVolumeSliderOpen &&
          volumeButtonRef.current &&
          !volumeButtonRef.current.contains(event.target as Node) &&
          !document
            .querySelector('.volume-slider-portal')
            ?.contains(event.target as Node)
        ) {
          setIsVolumeSliderOpen(false);
        }
      };

      document.addEventListener('mousedown', handleClickOutside);
      return () =>
        document.removeEventListener('mousedown', handleClickOutside);
    }, [isVolumeSliderOpen]);

    // Update button rect when window resizes
    useEffect(() => {
      if (!isVolumeSliderOpen || !volumeButtonRef.current) return;

      const handleResize = () => {
        if (volumeButtonRef.current) {
          setVolumeButtonRect(volumeButtonRef.current.getBoundingClientRect());
        }
      };

      window.addEventListener('resize', handleResize);

      return () => {
        window.removeEventListener('resize', handleResize);
      };
    }, [isVolumeSliderOpen]);

    return (
      <>
        <div className='relative'>
          {/* Floating Messages Container */}
          {showMessagePanel && isCommentsEnabled && (
            <div
              className='pointer-events-none mb-1 h-10 w-full overflow-visible rounded-xl border border-solid border-border-primary/15 bg-background-smoke-dense backdrop-blur-xl'
              style={{
                animation: isPanelAnimatingOut
                  ? 'slideDown 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards'
                  : 'slideUp 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards',
              }}
            >
              <div className='relative h-full w-full overflow-hidden'>
                {floatingMessages.map((message) => (
                  <FloatingMessageDisplay
                    key={message.id}
                    message={message}
                    onAnimationComplete={removeFloatingMessage}
                  />
                ))}
              </div>
            </div>
          )}

          <div
            ref={playbarRef}
            className='relative flex h-auto min-h-16 flex-1 flex-col overflow-x-hidden overflow-y-visible border-t border-solid border-border-primary bg-background-secondary/70 font-sans text-sm font-medium text-foreground-primary backdrop-blur-xl'
          >
            <div className='flex flex-1 flex-row content-between items-center p-2'>
              {!!currentSong ? (
                <RadioInfo
                  connections={connections}
                  onNavigate={handleNavigateToRadio}
                />
              ) : (
                <RadioLoadingState />
              )}

              {/* Desktop controls - center */}
              <RadioPlaybackControls />

              {/* Right side controls */}
              <div className='items-left justify-right flex w-fit flex-row-reverse gap-2 md:flex-1'>
                <div className='flex w-fit flex-row-reverse items-center gap-1'>
                  {/* Volume Control */}
                  <RadioVolumeControl
                    volume={volume}
                    onToggleSlider={handleToggleVolumeSlider}
                    buttonRef={volumeButtonRef}
                  />

                  {/* Action Buttons */}
                  <RadioActionButtons
                    onShare={handleShare}
                    onNavigate={handleNavigateToRadio}
                  />
                </div>

                {/* Mobile controls */}
                <RadioMobileControls />
              </div>
            </div>
          </div>
        </div>

        {/* Volume Slider Portal */}
        <RadioVolumeSliderPortal
          isOpen={isVolumeSliderOpen}
          buttonRect={volumeButtonRect}
          volume={volume}
          onVolumeChange={handleVolumeChange}
        />
      </>
    );
  }
);

const RadioPlaybar: React.FC<RadioPlaybarProps> = ({
  stationId = STATION_ID,
}) => {
  return (
    <>
      {/* CSS Animation for floating messages */}
      <style jsx>{`
        @keyframes floatMessage {
          0% {
            left: -350px;
            opacity: 0;
          }
          3% {
            opacity: 1;
          }
          97% {
            opacity: 1;
          }
          100% {
            left: calc(100% + 50px);
            opacity: 0;
          }
        }

        @keyframes slideUp {
          0% {
            transform: translateY(100%);
            opacity: 0;
          }
          100% {
            transform: translateY(0);
            opacity: 1;
          }
        }

        @keyframes slideDown {
          0% {
            transform: translateY(0);
            opacity: 1;
          }
          100% {
            transform: translateY(100%);
            opacity: 0;
          }
        }
      `}</style>
      <LiveRadioAblyProvider stationId={stationId}>
        <RadioPlaybarContent stationId={stationId} />
      </LiveRadioAblyProvider>
    </>
  );
};

export default RadioPlaybar;
