import React, {
  createContext,
  useContext,
  useState,
  useEffect,
  useRef,
} from 'react';
import { Track } from '../types';

export interface VisualizerSettings {
  mode: 'waveform' | 'spectrogram' | 'bars' | 'off';
  color: string;
  sensitivity: number;
}

interface AudioContextType {
  currentTrack: Track | null;
  isPlaying: boolean;
  queue: Track[];
  history: Track[];
  progress: number; // 0-100
  currentTime: number;
  duration: number;
  volume: number;
  isMuted: boolean;
  shuffle: boolean;
  repeatMode: 'off' | 'all' | 'one';
  playbackRate: number;
  pitchCorrection: boolean;
  visualizerSettings: VisualizerSettings;
  autoplay: boolean;

  // Actions
  playTrack: (track: Track, context?: Track[]) => void;
  togglePlay: () => void;
  nextTrack: () => void;
  prevTrack: () => void;
  seek: (percent: number) => void;
  setVolume: (val: number) => void;
  toggleMute: () => void;
  toggleShuffle: () => void;
  toggleRepeat: () => void;
  setPlaybackRate: (rate: number) => void;
  togglePitchCorrection: () => void;
  setVisualizerSettings: (settings: VisualizerSettings) => void;
  addToQueue: (track: Track) => void;
  removeFromQueue: (trackId: string) => void;
  playNext: (track: Track) => void;
  reorderQueue: (fromIndex: number, toIndex: number) => void;
  clearQueue: () => void;
  toggleAutoplay: () => void;
}

const AudioContext = createContext<AudioContextType | undefined>(undefined);

export const useAudio = () => {
  const context = useContext(AudioContext);
  if (!context) throw new Error('useAudio must be used within AudioProvider');
  return context;
};

// Mock Data for Initial State
const mockTracks: Track[] = [
  {
    id: '1',
    title: 'Neon Nightrider',
    artist: 'Cyber_Punk_OST',
    album: 'Night City Vol.1',
    duration: '3:45',
    durationSec: 225,
    plays: 12000,
    like_count: 3400,
    coverUrl: 'https://picsum.photos/id/55/400/400',
    isPremium: true,
    waveformData: Array.from({ length: 100 }, () => Math.random()),
    lyrics: [
      { time: 10, text: 'Neon lights flickering...' },
      { time: 15, text: 'Driving through the cyber city' },
      { time: 20, text: 'Bass dropping heavy on the pavement' },
    ],
  },
  {
    id: '2',
    title: 'Glitch in the Matrix',
    artist: 'Null Pointer',
    album: 'System Failure',
    duration: '4:20',
    durationSec: 260,
    plays: 8500,
    like_count: 2100,
    coverUrl: 'https://picsum.photos/id/58/400/400',
    waveformData: Array.from({ length: 100 }, () => Math.random()),
  },
  {
    id: '3',
    title: 'Tokyo Drift (Lofi)',
    artist: 'Sakura Beats',
    album: 'Chillhop Essentials',
    duration: '2:55',
    durationSec: 175,
    plays: 45000,
    like_count: 12000,
    coverUrl: 'https://picsum.photos/id/60/400/400',
    isPremium: true,
    waveformData: Array.from({ length: 100 }, () => Math.random()),
  },
  {
    id: '4',
    title: 'Neural Link',
    artist: 'Mainframe',
    album: 'AI Dreams',
    duration: '5:10',
    durationSec: 310,
    plays: 2300,
    like_count: 450,
    coverUrl: 'https://picsum.photos/id/70/200/200',
    waveformData: Array.from({ length: 100 }, () => Math.random()),
  },
  {
    id: '5',
    title: 'Synthwave Sunset',
    artist: 'Retro Boy',
    album: 'Analog Memories',
    duration: '3:30',
    durationSec: 210,
    plays: 1200,
    like_count: 300,
    coverUrl: 'https://picsum.photos/id/80/200/200',
    waveformData: Array.from({ length: 100 }, () => Math.random()),
  },
] as unknown as Track[];

export const AudioProvider: React.FC<{ children: React.ReactNode }> = ({
  children,
}) => {
  const [currentTrack, setCurrentTrack] = useState<Track | null>(mockTracks[0]);
  const [queue, setQueue] = useState<Track[]>(mockTracks.slice(1));
  const [history, setHistory] = useState<Track[]>([]);
  const [isPlaying, setIsPlaying] = useState(false);
  const [progress, setProgress] = useState(0);
  const [currentTime, setCurrentTime] = useState(0);
  const [volume, setVolumeState] = useState(80);
  const [isMuted, _setIsMuted] = useState(false);
  const [shuffle, setShuffle] = useState(false);
  const [repeatMode, setRepeatMode] = useState<'off' | 'all' | 'one'>('off');

  // Phase 8 & 9 New States
  const [playbackRate, setPlaybackRate] = useState(1.0);
  const [pitchCorrection, setPitchCorrection] = useState(true);
  const [visualizerSettings, setVisualizerSettings] =
    useState<VisualizerSettings>({
      mode: 'waveform',
      color: '#66FCF1',
      sensitivity: 50,
    });
  const [autoplay, setAutoplay] = useState(true);

  const audioInterval = useRef<number | null>(null);

  // Simulation of Audio Playback
  useEffect(() => {
    if (isPlaying && currentTrack) {
      audioInterval.current = window.setInterval(() => {
        setCurrentTime((prev) => {
          if (prev >= currentTrack.durationSec) {
            // Track finished
            if (repeatMode === 'one') {
              return 0; // Restart
            }
            if (queue.length > 0 || autoplay) {
              nextTrack(); // Auto next logic handled there
            } else {
              setIsPlaying(false);
              return prev;
            }
            return 0;
          }
          // Adjust increment based on playback rate
          return prev + 1 * playbackRate;
        });
      }, 1000 / playbackRate); // Interval adjusts to speed
    } else {
      if (audioInterval.current) clearInterval(audioInterval.current);
    }
    return () => {
      if (audioInterval.current) clearInterval(audioInterval.current);
    };
  }, [isPlaying, currentTrack, repeatMode, playbackRate, queue, autoplay]);

  // Sync Progress Percentage
  useEffect(() => {
    if (currentTrack) {
      setProgress((currentTime / currentTrack.durationSec) * 100);
    }
  }, [currentTime, currentTrack]);

  const playTrack = (track: Track, context?: Track[]) => {
    if (currentTrack && currentTrack.id !== track.id) {
      setHistory((prev) => [...prev, currentTrack]);
    }
    setCurrentTrack(track);
    if (context) {
      const trackIndex = context.findIndex((t) => t.id === track.id);
      if (trackIndex !== -1) {
        setQueue(context.slice(trackIndex + 1));
      }
    }
    setIsPlaying(true);
    setCurrentTime(0);
  };

  const togglePlay = () => setIsPlaying(!isPlaying);

  const nextTrack = () => {
    if (queue.length > 0) {
      const next = shuffle
        ? queue[Math.floor(Math.random() * queue.length)]
        : queue[0];
      setHistory((prev) => (currentTrack ? [...prev, currentTrack] : prev));

      if (repeatMode !== 'all') {
        setQueue((prev) => prev.filter((t) => t.id !== next.id));
      } else {
        setQueue((prev) => [...prev.filter((t) => t.id !== next.id), next]);
      }

      setCurrentTrack(next);
      setCurrentTime(0);
      setIsPlaying(true);
    } else if (autoplay) {
      // Mock Autoplay logic: Pick random track from "Network"
      // In real app, this fetches recommendation
      const randomMock =
        mockTracks[Math.floor(Math.random() * mockTracks.length)];
      // Don't add to history if it's autoplay transition usually, but for mock simplicty:
      setHistory((prev) => (currentTrack ? [...prev, currentTrack] : prev));
      setCurrentTrack({
        ...randomMock,
        id: `auto-${Date.now()}`,
        title: `Autoplay: ${randomMock.title}`,
      });
      setCurrentTime(0);
      setIsPlaying(true);
    } else {
      setIsPlaying(false);
      setCurrentTime(0);
    }
  };

  const prevTrack = () => {
    if (currentTime > 3) {
      setCurrentTime(0);
    } else if (history.length > 0) {
      const prev = history[history.length - 1];
      setQueue((prevQ) => (currentTrack ? [currentTrack, ...prevQ] : prevQ));
      setHistory((prevH) => prevH.slice(0, -1));
      setCurrentTrack(prev);
      setCurrentTime(0);
      setIsPlaying(true);
    }
  };

  const seek = (percent: number) => {
    if (currentTrack) {
      const newTime = (percent / 100) * currentTrack.durationSec;
      setCurrentTime(newTime);
      setProgress(percent);
    }
  };

  const setVolume = (val: number) => setVolumeState(val);
  const toggleMute = () => setIsPlaying((prev) => !prev); // Simplified mock
  const toggleShuffle = () => setShuffle(!shuffle);
  const toggleRepeat = () => {
    const modes: ('off' | 'all' | 'one')[] = ['off', 'all', 'one'];
    const next = modes[(modes.indexOf(repeatMode) + 1) % modes.length];
    setRepeatMode(next);
  };

  const togglePitchCorrection = () => setPitchCorrection(!pitchCorrection);
  const toggleAutoplay = () => setAutoplay(!autoplay);

  const addToQueue = (track: Track) => setQueue((prev) => [...prev, track]);
  const playNext = (track: Track) => setQueue((prev) => [track, ...prev]);
  const removeFromQueue = (id: string) =>
    setQueue((prev) => prev.filter((t) => t.id !== id));
  const clearQueue = () => setQueue([]);

  const reorderQueue = (fromIndex: number, toIndex: number) => {
    const result = Array.from(queue);
    const [removed] = result.splice(fromIndex, 1);
    result.splice(toIndex, 0, removed);
    setQueue(result);
  };

  return (
    <AudioContext.Provider
      value={{
        currentTrack,
        isPlaying,
        queue,
        history,
        progress,
        currentTime,
        duration: currentTrack?.durationSec || 0,
        volume,
        isMuted,
        shuffle,
        repeatMode,
        playbackRate,
        pitchCorrection,
        visualizerSettings,
        autoplay,
        playTrack,
        togglePlay,
        nextTrack,
        prevTrack,
        seek,
        setVolume,
        toggleMute,
        toggleShuffle,
        toggleRepeat,
        setPlaybackRate,
        togglePitchCorrection,
        setVisualizerSettings,
        toggleAutoplay,
        addToQueue,
        removeFromQueue,
        playNext,
        reorderQueue,
        clearQueue,
      }}
    >
      {children}
    </AudioContext.Provider>
  );
};
