import { useState, useRef, useEffect, useCallback } from 'react';
import type { StorySegmentDto } from '../../../types/api/story';

interface StoryPlayerProps {
  segment: StorySegmentDto;
  autoPlay?: boolean;
  onPlay?: () => void;
  onPause?: () => void;
  onEnded?: () => void;
}

/**
 * StoryPlayer component - Handles audio playback for story segments.
 * Uses the HTML5 audio element to play audio files served from the backend.
 */
export function StoryPlayer({
  segment,
  autoPlay = false,
  onPlay,
  onPause,
  onEnded,
}: StoryPlayerProps) {
  const audioRef = useRef<HTMLAudioElement>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [volume, setVolume] = useState(0.8);

  // Construct audio URL from segment audioUrl
  // Backend serves files from wwwroot, so URLs are like /audio/story/level1-segment1.wav
  const audioUrl = segment.audioUrl
    ? `${import.meta.env.VITE_API_URL || 'http://localhost:5000'}${segment.audioUrl}`
    : null;

  // Load audio metadata when component mounts or segment changes
  useEffect(() => {
    if (audioUrl && audioRef.current) {
      const audio = audioRef.current;
      
      const handleLoadedMetadata = () => {
        setDuration(audio.duration);
        setIsLoading(false);
      };

      const handleError = () => {
        setError('Failed to load audio file');
        setIsLoading(false);
      };

      audio.addEventListener('loadedmetadata', handleLoadedMetadata);
      audio.addEventListener('error', handleError);

      // Load the audio source
      audio.src = audioUrl;
      audio.load();

      return () => {
        audio.removeEventListener('loadedmetadata', handleLoadedMetadata);
        audio.removeEventListener('error', handleError);
      };
    }
  }, [audioUrl]);

  // Handle audio events
  useEffect(() => {
    if (!audioRef.current) return;

    const audio = audioRef.current;

    const handlePlay = () => {
      setIsPlaying(true);
      onPlay?.();
    };

    const handlePause = () => {
      setIsPlaying(false);
      onPause?.();
    };

    const handleEnded = () => {
      setIsPlaying(false);
      setCurrentTime(0);
      onEnded?.();
    };

    const handleTimeUpdate = () => {
      setCurrentTime(audio.currentTime);
    };

    audio.addEventListener('play', handlePlay);
    audio.addEventListener('pause', handlePause);
    audio.addEventListener('ended', handleEnded);
    audio.addEventListener('timeupdate', handleTimeUpdate);

    return () => {
      audio.removeEventListener('play', handlePlay);
      audio.removeEventListener('pause', handlePause);
      audio.removeEventListener('ended', handleEnded);
      audio.removeEventListener('timeupdate', handleTimeUpdate);
    };
  }, [onPlay, onPause, onEnded]);

  // Auto-play effect
  useEffect(() => {
    if (autoPlay && audioRef.current && !isPlaying && !isLoading) {
      audioRef.current.play().catch(() => setError('Audio playback failed'));
    }
  }, [autoPlay, isPlaying, isLoading]);

  const togglePlayPause = useCallback(() => {
    if (!audioRef.current) return;

    if (isPlaying) {
      audioRef.current.pause();
    } else {
      if (audioUrl) {
        audioRef.current.play().catch(() => setError('Audio playback failed'));
      }
    }
  }, [isPlaying, audioUrl]);

  const handleSeek = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    if (!audioRef.current) return;
    const seekTime = parseFloat(e.target.value);
    audioRef.current.currentTime = seekTime;
    setCurrentTime(seekTime);
  }, []);

  const handleVolumeChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const newVolume = parseFloat(e.target.value);
    setVolume(newVolume);
    if (audioRef.current) {
      audioRef.current.volume = newVolume;
    }
  }, []);

  const handlePrevious = useCallback(() => {
    // Previous segment logic would be handled by parent
    onEnded?.();
  }, [onEnded]);

  const handleNext = useCallback(() => {
    // Next segment logic would be handled by parent
    onEnded?.();
  }, [onEnded]);

  const formatTime = (seconds: number) => {
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  };

  if (!audioUrl) {
    return (
      <div className="story-player" data-testid="story-player">
        <div className="no-audio-notice">
          <p>🎧 No audio available for this segment</p>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="story-player" data-testid="story-player">
        <div className="player-error">
          <p>⚠️ {error}</p>
          <button onClick={() => setError(null)}>Retry</button>
        </div>
      </div>
    );
  }

  return (
    <div className="story-player" data-testid="story-player">
      <div className="player-controls">
        <button
          className="player-btn"
          onClick={handlePrevious}
          title="Previous segment"
          disabled={!segment.audioUrl}
        >
          ⏮️
        </button>

        <button
          className="player-btn play-pause-btn"
          onClick={togglePlayPause}
          title={isPlaying ? 'Pause' : 'Play'}
          disabled={isLoading}
          data-testid="play-pause-btn"
        >
          {isLoading ? '⏳' : isPlaying ? '⏸️' : '▶️'}
        </button>

        <button
          className="player-btn"
          onClick={handleNext}
          title="Next segment"
          disabled={!segment.audioUrl}
        >
          ⏭️
        </button>
      </div>

      <div className="player-progress">
        <span className="player-time">{formatTime(currentTime)}</span>
        <input
          type="range"
          min="0"
          max={duration || 0}
          value={currentTime}
          onChange={handleSeek}
          className="seek-slider"
          disabled={!duration}
          data-testid="seek-slider"
        />
        <span className="player-time">{formatTime(duration)}</span>
      </div>

      <div className="player-volume">
        <span className="volume-icon">🔊</span>
        <input
          type="range"
          min="0"
          max="1"
          step="0.01"
          value={volume}
          onChange={handleVolumeChange}
          className="volume-slider"
          data-testid="volume-slider"
        />
      </div>

      {/* Hidden audio element */}
      <audio
        ref={audioRef}
        preload="metadata"
        style={{ display: 'none' }}
      />
    </div>
  );
}

export default StoryPlayer;
