import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'package:matrix/matrix.dart';
import 'package:pyramid/features/call_signaling/voip_manager.dart';

/// Öffentliche Schnittstelle des Moduls `call_signaling` – natives
/// Matrix-1:1-VoIP (`m.call.*`-Events, direkte WebRTC-Peer-Connection,
/// kein SFU). Schnitt nach `docs/M2_MODULE_SCHNITT.md`.
///
/// Andere Module (UI, Settings, Shell) konsumieren AUSSCHLIESSLICH diese
/// Schnittstelle über [callSignalingProvider] – nie `voip_manager.dart`
/// direkt. Einzige Ausnahme ist der Kompositions-Punkt in
/// `matrix_client.dart`, der die Implementierung konstruiert.
///
/// Bewusste Abweichungen vom Entwurf im Doc (Verhaltensgleichheit vor
/// Schönheit, heiliger Call-Pfad):
///  * ChangeNotifier statt Streams – die gesamte UI hängt heute an
///    `ref.watch(...)` mit notifyListeners; ein Stream-Umbau wäre eine
///    Verhaltensänderung ohne Not.
///  * [currentCall] bleibt als matrix-SDK-`CallSession` sichtbar (die UI
///    braucht state/room/answer/reject), ebenso die WebRTC-Renderer –
///    das Doc sieht Letzteres ausdrücklich vor.
abstract class CallSignalingService extends ChangeNotifier {
  /// Der laufende 1:1-Call (null = keiner). UI liest state/room und
  /// beantwortet eingehende Calls über [safeAction] + answer()/reject().
  CallSession? get currentCall;

  rtc.RTCVideoRenderer get localRenderer;
  rtc.RTCVideoRenderer get remoteRenderer;

  bool get isMicMuted;
  bool get isCameraMuted;
  bool get isScreensharing;
  bool get isRemoteScreensharing;
  bool get isDeafened;

  /// Sende-Qualität ('sd' | 'hd' | 'fhd' | '4k').
  String get currentQualityKey;

  Future<void> startCall(String roomId, {bool video});
  Future<void> hangup();
  Future<void> toggleMic();
  Future<void> toggleCamera();
  Future<void> toggleDeafen();

  /// Auf Windows öffnet ein [context] den Quellen-Picker fürs Screensharing.
  Future<void> toggleScreenSharing([BuildContext? context]);

  Future<void> changeQuality(String key);

  /// Wendet die in den Einstellungen gewählte Ausgabelautstärke auf den
  /// Remote-Stream an. Ohne [value] wird der Pref-Wert gelesen.
  Future<void> applyOutputVolume([double? value]);

  /// Führt eine Call-Aktion (answer/reject/…) fehlertolerant aus und stößt
  /// danach die interne Zustands-/Renderer-Aktualisierung an.
  Future<void> safeAction(Future<dynamic> Function() action);
}

/// Einziger Zugriffsweg der UI auf das 1:1-VoIP-Modul. Die Instanz wird beim
/// Client-Aufbau in `matrix_client.dart` erzeugt (existiert also, sobald die
/// eingeloggte Shell steht).
final callSignalingProvider =
    ChangeNotifierProvider<CallSignalingService>((ref) {
  return PyramidVoipManager.instance;
});
