// Audio Player Service for Podcast Playback

import { Audio, AVPlaybackStatus, AVPlaybackStatusSuccess } from 'expo-av';
import { FeedItem } from '@/types/feed';

type PlaybackState = 'idle' | 'loading' | 'playing' | 'paused' | 'error';
type PlaybackSpeed = 0.5 | 0.75 | 1 | 1.25 | 1.5 | 1.75 | 2;

interface PlayerState {
  state: PlaybackState;
  currentItem: FeedItem | null;
  position: number;
  duration: number;
  playbackSpeed: PlaybackSpeed;
  isBuffering: boolean;
}

type StateChangeCallback = (state: PlayerState) => void;

class AudioPlayerService {
  private sound: Audio.Sound | null = null;
  private state: PlayerState = {
    state: 'idle',
    currentItem: null,
    position: 0,
    duration: 0,
    playbackSpeed: 1,
    isBuffering: false,
  };
  private listeners: Set<StateChangeCallback> = new Set();

  async initialize(): Promise<void> {
    await Audio.setAudioModeAsync({
      allowsRecordingIOS: false,
      playsInSilentModeIOS: true,
      staysActiveInBackground: true,
      shouldDuckAndroid: true,
      playThroughEarpieceAndroid: false,
    });
  }

  subscribe(callback: StateChangeCallback): () => void {
    this.listeners.add(callback);
    callback(this.state);
    return () => this.listeners.delete(callback);
  }

  private updateState(updates: Partial<PlayerState>): void {
    this.state = { ...this.state, ...updates };
    this.listeners.forEach(cb => cb(this.state));
  }

  async play(item: FeedItem): Promise<void> {
    if (!item.enclosure?.url) {
      this.updateState({ state: 'error' });
      return;
    }

    try {
      this.updateState({ state: 'loading', currentItem: item, isBuffering: true });

      // Unload previous sound
      if (this.sound) {
        await this.sound.unloadAsync();
        this.sound = null;
      }

      // Create and load new sound
      const { sound } = await Audio.Sound.createAsync(
        { uri: item.enclosure.url },
        { shouldPlay: true, progressUpdateIntervalMillis: 1000 },
        this.onPlaybackStatusUpdate
      );
      
      this.sound = sound;
    } catch (error) {
      console.error('Playback error:', error);
      this.updateState({ state: 'error' });
    }
  }

  private onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
    if (!status.isLoaded) {
      if (status.error) {
        this.updateState({ state: 'error' });
      }
      return;
    }

    const loadedStatus = status as AVPlaybackStatusSuccess;
    
    this.updateState({
      state: loadedStatus.isPlaying ? 'playing' : 'paused',
      position: loadedStatus.positionMillis,
      duration: loadedStatus.durationMillis || 0,
      isBuffering: loadedStatus.isBuffering || false,
    });
  };

  async pause(): Promise<void> {
    if (this.sound) {
      await this.sound.pauseAsync();
    }
  }

  async resume(): Promise<void> {
    if (this.sound) {
      await this.sound.playAsync();
    }
  }

  async stop(): Promise<void> {
    if (this.sound) {
      await this.sound.stopAsync();
      await this.sound.unloadAsync();
      this.sound = null;
    }
    this.updateState({
      state: 'idle',
      currentItem: null,
      position: 0,
      duration: 0,
    });
  }

  async seekTo(positionMs: number): Promise<void> {
    if (this.sound) {
      await this.sound.setPositionAsync(positionMs);
    }
  }

  async setPlaybackSpeed(speed: PlaybackSpeed): Promise<void> {
    if (this.sound) {
      await this.sound.setRateAsync(speed, true);
      this.updateState({ playbackSpeed: speed });
    }
  }

  async skipForward(seconds: number = 30): Promise<void> {
    if (this.sound) {
      const newPosition = Math.min(
        this.state.position + seconds * 1000,
        this.state.duration
      );
      await this.sound.setPositionAsync(newPosition);
    }
  }

  async skipBackward(seconds: number = 10): Promise<void> {
    if (this.sound) {
      const newPosition = Math.max(this.state.position - seconds * 1000, 0);
      await this.sound.setPositionAsync(newPosition);
    }
  }

  getState(): PlayerState {
    return this.state;
  }
}

export const audioPlayer = new AudioPlayerService();
export type { PlaybackState, PlaybackSpeed, PlayerState };