import 'package:web/web.dart' as web;
import 'dart:async';

class AudioPlayer {
  web.HTMLAudioElement? _audioElement;
  final StreamController<Duration> _positionController =
      StreamController<Duration>.broadcast();
  final StreamController<Duration> _durationController =
      StreamController<Duration>.broadcast();
  final StreamController<bool> _playingController =
      StreamController<bool>.broadcast();
  final StreamController<String> _errorController =
      StreamController<String>.broadcast();

  Stream<Duration> get positionStream => _positionController.stream;
  Stream<Duration> get durationStream => _durationController.stream;
  Stream<bool> get playingStream => _playingController.stream;
  Stream<String> get errorStream => _errorController.stream;

  Future<void> setUrl(String url) async {
    try {
      _audioElement = web.HTMLAudioElement();
      _audioElement!.src = url;
      _audioElement!.crossOrigin = 'anonymous'; // Handle CORS

      // Set up event listeners
      _audioElement!.onLoadedMetadata.listen((_) {
        _durationController.add(
          Duration(milliseconds: (_audioElement!.duration * 1000).toInt()),
        );
      });

      _audioElement!.onTimeUpdate.listen((_) {
        _positionController.add(
          Duration(milliseconds: (_audioElement!.currentTime * 1000).toInt()),
        );
      });

      _audioElement!.onPlay.listen((_) {
        _playingController.add(true);
      });

      _audioElement!.onPause.listen((_) {
        _playingController.add(false);
      });

      _audioElement!.onEnded.listen((_) {
        _playingController.add(false);
      });

      _audioElement!.onError.listen((_) {
        _errorController.add('Failed to load audio');
      });

      // Load the audio
      _audioElement!.load();
    } catch (e) {
      _errorController.add('Error initializing audio: $e');
    }
  }

  Future<void> play() async {
    try {
      if (_audioElement != null) {
        // The play() method returns a JSPromise, but we can call it without await
        // since we're not depending on the promise resolution for our logic
        _audioElement!.play();
      }
    } catch (e) {
      _errorController.add('Error playing audio: $e');
    }
  }

  Future<void> pause() async {
    _audioElement?.pause();
  }

  Future<void> seek(Duration position) async {
    if (_audioElement != null) {
      _audioElement!.currentTime = position.inMilliseconds / 1000;
    }
  }

  void dispose() {
    _audioElement?.pause();
    _audioElement = null;
    _positionController.close();
    _durationController.close();
    _playingController.close();
    _errorController.close();
  }
}
