import { observer } from 'mobx-react-lite';
import React, { useCallback, useRef, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import { CloseIcon, PauseIcon, PlayIcon } from '@/icons';
import audioContext from '@/lib/audioContext';

import { OrpheusReferenceIcon } from '../../OrpheusReferenceIcon';
import { ReferenceButton } from './ReferenceButton';
import { ReferenceImage } from './ReferenceImage';
import { ReferenceText } from './ReferenceText';
import {
  AudioFileReference,
  ClipReference,
  LyricsReference,
  PersonaReference,
  PlaylistReference,
  StylesReference,
} from './ReferenceTypes';

interface ReferenceRendererProps {
  onRemove: () => void;
}

export const ClipRenderer: React.FC<ClipReference & ReferenceRendererProps> = ({
  title,
  imageUrl,
  batchIndex,
  onRemove,
}) => {
  // Generate upload title from date if title is not provided
  const uploadTitle = `${title || 'Loading...'}${batchIndex !== undefined ? ` (${batchIndex + 1})` : ''}`;

  return (
    <div className='flex min-h-[48px] min-w-0 flex-row items-center gap-2 overflow-hidden'>
      {/* 1. Reference Image */}
      <div className='relative h-8 w-8 flex-shrink-0'>
        <ReferenceImage src={imageUrl} alt={uploadTitle} />
      </div>

      {/* 2. Upload Title - max width 75% with truncation */}
      <div className='max-w-[75%] min-w-0 overflow-hidden'>
        <ReferenceText truncate>{uploadTitle}</ReferenceText>
      </div>

      {/* 3. Spacer to push close button to the right */}
      <div className='flex-1' />

      <div className='flex flex-shrink-0 items-center'>
        <ReferenceButton
          icon={CloseIcon}
          onClick={onRemove}
          aria-label='Remove reference'
        />
      </div>
    </div>
  );
};

export const LyricsRenderer: React.FC<
  LyricsReference & ReferenceRendererProps
> = ({ message, selectionOverlayRange, onRemove }) => {
  // Extract the lyrics text and ensure it's a single line
  const lyricsText = message
    .slice(selectionOverlayRange.start, selectionOverlayRange.end)
    .replace(/\s+/g, ' ') // Replace any whitespace (including newlines) with single spaces
    .trim();

  return (
    <div className='flex min-h-[48px] min-w-0 flex-row items-center gap-2 overflow-hidden'>
      <OrpheusReferenceIcon className='h-4 w-4 flex-shrink-0' />

      {/* Lyrics Text Container - must have min-w-0 and max-w-[75%] to allow truncation */}
      <div className='max-w-[75%] min-w-0 overflow-hidden'>
        <div className='flex min-w-0 items-center gap-4 overflow-hidden text-sm'>
          <ReferenceText mode='muted' className='min-w-0 flex-1' truncate>
            &quot;{lyricsText}&quot;
          </ReferenceText>
        </div>
      </div>

      {/* Spacer to push close button to the right */}
      <div className='flex-1' />

      <div className='flex flex-shrink-0 items-center'>
        <ReferenceButton
          icon={CloseIcon}
          onClick={onRemove}
          aria-label='Remove reference'
        />
      </div>
    </div>
  );
};

export const StylesRenderer: React.FC<
  StylesReference & ReferenceRendererProps
> = ({ message, selectionOverlayRange, onRemove }) => {
  // Extract the styles text and ensure it's a single line
  const stylesText = message
    .slice(
      selectionOverlayRange?.start ?? 0,
      selectionOverlayRange?.end ?? message.length
    )
    .replace(/\s+/g, ' ') // Replace any whitespace (including newlines) with single spaces
    .trim();

  return (
    <div className='flex min-h-[48px] min-w-0 flex-row items-center gap-2 overflow-hidden'>
      <OrpheusReferenceIcon className='h-4 w-4 flex-shrink-0' />

      {/* Styles Text Container - must have min-w-0 and max-w-[75%] to allow truncation */}
      <div className='max-w-[75%] min-w-0 overflow-hidden'>
        <div className='flex min-w-0 items-center gap-4 overflow-hidden text-sm'>
          <ReferenceText mode='muted' className='min-w-0 flex-1' truncate>
            &quot;{stylesText}&quot;
          </ReferenceText>
        </div>
      </div>

      {/* Spacer to push close button to the right */}
      <div className='flex-1' />

      <div className='flex flex-shrink-0 items-center'>
        <ReferenceButton icon={CloseIcon} onClick={onRemove} />
      </div>
    </div>
  );
};

export const PlaylistRenderer: React.FC<
  PlaylistReference & ReferenceRendererProps
> = ({ name, trackCount, onRemove }) => (
  <div className='flex flex-row items-center'>
    <ReferenceText mode='normal' className='line-clamp-1'>
      <span className='font-bold'>Playlist:</span> {name}
      {trackCount !== undefined && (
        <ReferenceText mode='muted' className='text-sm'>
          {' '}
          ({trackCount} tracks)
        </ReferenceText>
      )}
    </ReferenceText>
    <div className='flex flex-1 flex-row-reverse items-center'>
      <ReferenceButton icon={CloseIcon} onClick={onRemove} />
    </div>
  </div>
);

export const PersonaRenderer: React.FC<
  PersonaReference & ReferenceRendererProps
> = ({ name, avatar, onRemove }) => (
  <div className='flex flex-row items-center'>
    {avatar && (
      <ImageWithFallback alt='Persona Avatar' src={avatar} className='w-5' />
    )}
    <ReferenceText mode='normal' className='line-clamp-1'>
      <span className='font-bold'>Persona:</span> {name}
    </ReferenceText>
    <div className='flex flex-1 flex-row-reverse items-center'>
      <ReferenceButton icon={CloseIcon} onClick={onRemove} />
    </div>
  </div>
);

export const AudioFileRenderer: React.FC<
  AudioFileReference & ReferenceRendererProps
> = observer(({ fileName, audioBuffer, clipId, onRemove }) => {
  const { playbar, clips } = useStores();

  // Get the clip from the store if clipId is available
  const clip = clipId ? clips.clipById[clipId] : null;

  // Determine if this audio file is currently playing in the global playbar
  const isCurrentlyPlaying = playbar.clip?.id === clipId && playbar.isPlaying;

  // If no clipId available, fall back to local AudioContext playback
  const [localIsPlaying, setLocalIsPlaying] = useState(false);
  const audioSourceRef = useRef<AudioBufferSourceNode | null>(null);

  const handlePlayPauseToggle = useCallback(() => {
    if (clipId && clip) {
      // Use global playbar for uploaded clips
      if (playbar.clip?.id === clipId) {
        playbar.togglePlay();
      } else {
        playbar.playClip(clip);
      }
    } else {
      // Fall back to local playback for clips without clipId
      if (localIsPlaying) {
        // Stop playback
        if (audioSourceRef.current) {
          audioSourceRef.current.stop();
          audioSourceRef.current = null;
        }
        setLocalIsPlaying(false);
      } else {
        // Start playback
        try {
          const source = audioContext.createBufferSource();
          source.buffer = audioBuffer;
          source.connect(audioContext.destination);

          source.onended = () => {
            setLocalIsPlaying(false);
            audioSourceRef.current = null;
          };

          source.start();
          audioSourceRef.current = source;
          setLocalIsPlaying(true);
        } catch (error) {
          console.error('Error playing audio file:', error);
        }
      }
    }
  }, [clipId, clip, playbar, localIsPlaying, audioBuffer]);

  // Generate upload title from date if fileName is not provided
  const uploadTitle = fileName || new Date().toLocaleDateString();

  return (
    <div className='flex min-h-[48px] min-w-0 flex-row items-center gap-2 overflow-hidden'>
      {/* 1. Reference Image (placeholder for audio files) */}
      <div className='relative h-8 w-8 flex-shrink-0'>
        <ReferenceImage
          src={undefined} // No image for audio files
          alt={uploadTitle}
        />
        {/* Dark overlay */}
        <div className='absolute inset-0 rounded-md bg-black/40' />
        <ReferenceButton
          icon={
            clipId && clip && isCurrentlyPlaying
              ? PauseIcon
              : !clipId && localIsPlaying
                ? PauseIcon
                : PlayIcon
          }
          onClick={handlePlayPauseToggle}
          className='absolute top-1/2 left-1/2 z-10 -translate-x-1/2 -translate-y-1/2 transition-colors duration-150'
          iconClassName='text-white'
        />
      </div>

      {/* 2. Upload Title - max width 75% with truncation */}
      <div className='max-w-[75%] min-w-0 overflow-hidden'>
        <ReferenceText truncate>{uploadTitle}</ReferenceText>
      </div>

      {/* 3. Spacer to push close button to the right */}
      <div className='flex-1' />

      <div className='flex flex-shrink-0 items-center'>
        <ReferenceButton
          icon={CloseIcon}
          onClick={onRemove}
          aria-label='Remove reference'
        />
      </div>
    </div>
  );
});
