import 'dart:async';
import 'package:aves_video/aves_video.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:aves/remote/remote_http.dart' as remote;

class RemoteNetworkVideoController extends AvesVideoController {
  final String url;
  Map<String, String>? httpHeaders;

  late final VideoPlayerController _vp;
  final _statusCtr = StreamController<VideoStatus>.broadcast();
  final _positionCtr = StreamController<int>.broadcast();
  final _speedCtr = StreamController<double>.broadcast();
  final _volumeCtr = StreamController<double>.broadcast();
  final ValueNotifier<bool> _canCaptureFrame = ValueNotifier(false);
  final ValueNotifier<bool> _canMute = ValueNotifier(true);
  final ValueNotifier<bool> _canSetSpeed = ValueNotifier(true);
  final ValueNotifier<bool> _canSelectStream = ValueNotifier(false);
  final ValueNotifier<double?> _sar = ValueNotifier<double?>(null);
  final _playCompleted = ValueNotifier<bool>(false);

  Timer? _posTimer;
  double _speed = 1.0;
  bool _muted = false;

  RemoteNetworkVideoController(
    super.entry, {
    required this.url,
    this.httpHeaders,
    required super.playbackStateHandler,
    required super.settings,
  }) {
    _init();
  }

  Future<void> _init() async {
    try {
      // headers: usa cache se presente, altrimenti fetch adesso
      httpHeaders ??= remote.RemoteHttp.peekHeaders() ?? await remote.RemoteHttp.headers();

      // ✅ networkUrl con headers NON nulli
      _vp = VideoPlayerController.networkUrl(Uri.parse(url), httpHeaders: httpHeaders ?? const {});
      // Se la tua versione del plugin non ha networkUrl(...), usa la riga sotto:
      // _vp = VideoPlayerController.network(url, httpHeaders: httpHeaders ?? const {});

      await _vp.initialize();

      _statusCtr.add(VideoStatus.initialized);
      _speed = _vp.value.playbackSpeed;
      _speedCtr.add(_speed);
      _muted = _vp.value.volume == 0;
      _volumeCtr.add(_vp.value.volume);

      // Poll leggero della posizione
      _posTimer = Timer.periodic(const Duration(milliseconds: 250), (_) {
        final v = _vp.value;
        if (!v.isInitialized) return;
        _positionCtr.add(v.position.inMilliseconds);

        final d = v.duration;
        if (d.inMilliseconds > 0 &&
            (d - v.position).inMilliseconds <= 200 &&
            !_playCompleted.value) {
          _playCompleted.value = true;
          _statusCtr.add(VideoStatus.completed);
        }
      });
    } catch (_) {
      _statusCtr.add(VideoStatus.error);
    }
  }

  @override
  Future<void> dispose() async {
    _posTimer?.cancel();
    await _vp.dispose();
    _statusCtr.close();
    _positionCtr.close();
    _speedCtr.close();
    _volumeCtr.close();
    _canCaptureFrame.dispose();
    _canMute.dispose();
    _canSetSpeed.dispose();
    _canSelectStream.dispose();
    _sar.dispose();
    _playCompleted.dispose();
    await super.dispose();
  }

  @override
  void onVisualChanged() {}

  @override
  Future<void> play() async {
    await _vp.play();
    _statusCtr.add(VideoStatus.playing);
  }

  @override
  Future<void> pause() async {
    await _vp.pause();
    _statusCtr.add(VideoStatus.paused);
  }

  @override
  Future<void> seekTo(int targetMillis) async {
    await _vp.seekTo(Duration(milliseconds: targetMillis));
  }

  @override
  Future<void> skipFrames(int frameCount) async {
    // stima ~30fps
    final delta = Duration(milliseconds: (1000 / 30 * frameCount).round());
    await _vp.seekTo(_vp.value.position + delta);
  }

  @override
  Listenable get playCompletedListenable => _playCompleted;

  @override
  VideoStatus get status {
    final v = _vp.value;
    if (!v.isInitialized) return VideoStatus.idle;
    if (v.hasError) return VideoStatus.error;
    return v.isPlaying ? VideoStatus.playing : VideoStatus.paused;
  }

  @override
  Stream<VideoStatus> get statusStream => _statusCtr.stream;

  @override
  Stream<double> get volumeStream => _volumeCtr.stream;

  @override
  Stream<double> get speedStream => _speedCtr.stream;

  @override
  bool get isReady => _vp.value.isInitialized;

  @override
  int get duration => _vp.value.isInitialized ? _vp.value.duration.inMilliseconds : 0;

  @override
  int get currentPosition => _vp.value.position.inMilliseconds;

  @override
  Stream<int> get positionStream => _positionCtr.stream;

  @override
  Stream<String?> get timedTextStream => const Stream.empty();

  @override
  ValueNotifier<bool> get canCaptureFrameNotifier => _canCaptureFrame;

  @override
  ValueNotifier<bool> get canMuteNotifier => _canMute;

  @override
  ValueNotifier<bool> get canSetSpeedNotifier => _canSetSpeed;

  @override
  ValueNotifier<bool> get canSelectStreamNotifier => _canSelectStream;

  @override
  ValueNotifier<double?> get sarNotifier => _sar;

  @override
  bool get isMuted => _muted;

  @override
  double get speed => _speed;

  @override
  double get minSpeed => 0.25;

  @override
  double get maxSpeed => 2.0;

  @override
  set speed(double s) {
    _speed = s.clamp(minSpeed, maxSpeed);
    _vp.setPlaybackSpeed(_speed);
    _speedCtr.add(_speed);
  }

  @override
  Future<void> selectStream(MediaStreamType type, MediaStreamSummary? selected) async {
    // non implementato in questa versione minima
  }

  @override
  Future<MediaStreamSummary?> getSelectedStream(MediaStreamType type) async => null;

  @override
  List<MediaStreamSummary> get streams => const [];

  @override
  Future<Uint8List?> captureFrame() async => null;

  @override
  Future<void> mute(bool muted) async {
    _muted = muted;
    await _vp.setVolume(muted ? 0 : 1);
    _volumeCtr.add(_vp.value.volume);
  }

  @override
  Widget buildPlayerWidget(BuildContext context) {
    if (!isReady) return const SizedBox();
    final ar = _vp.value.aspectRatio == 0 ? 16 / 9 : _vp.value.aspectRatio;
    return AspectRatio(aspectRatio: ar, child: VideoPlayer(_vp));
  }
}
